use assert_cmd::Command;
use predicates::prelude::*;
use serial_test::serial;
use tempfile::TempDir;
fn cmd_idioma(dir: &TempDir) -> Command {
let mut cmd = Command::cargo_bin("context7").unwrap();
cmd.env_clear()
.env("XDG_CONFIG_HOME", dir.path())
.env("HOME", dir.path());
cmd
}
#[test]
#[serial]
fn testa_help_renderiza_sem_panico_independente_de_lang() {
let dir = TempDir::new().unwrap();
cmd_idioma(&dir).arg("--help").assert().success();
}
#[test]
#[serial]
fn testa_keys_list_vazio_mensagem_em_portugues() {
let dir = TempDir::new().unwrap();
cmd_idioma(&dir)
.env("CONTEXT7_LANG", "pt")
.args(["keys", "list"])
.assert()
.success()
.stdout(
predicate::str::contains("Nenhuma chave")
.or(predicate::str::contains("nenhuma"))
.or(predicate::str::contains("Use"))
.or(predicate::str::contains("0 chave")),
);
}
#[test]
#[serial]
fn testa_keys_list_vazio_nao_exibe_erro_sistema() {
let dir = TempDir::new().unwrap();
let saida = cmd_idioma(&dir).args(["keys", "list"]).output().unwrap();
assert!(
saida.status.success(),
"keys list sem chaves deve retornar exit 0"
);
let stderr = String::from_utf8_lossy(&saida.stderr);
assert!(
!stderr.contains("Error") || stderr.is_empty(),
"keys list não deve produzir mensagens de erro no stderr: {stderr}"
);
}
#[test]
#[serial]
fn testa_env_context7_lang_pt_aceita_sem_crash() {
let dir = TempDir::new().unwrap();
cmd_idioma(&dir)
.env("CONTEXT7_LANG", "pt")
.args(["keys", "list"])
.assert()
.success();
}
#[test]
#[serial]
fn testa_env_context7_lang_en_aceita_sem_crash() {
let dir = TempDir::new().unwrap();
cmd_idioma(&dir)
.env("CONTEXT7_LANG", "en")
.args(["keys", "list"])
.assert()
.success();
}
#[test]
#[serial]
fn testa_env_context7_lang_invalido_usa_fallback_sem_panic() {
let dir = TempDir::new().unwrap();
let saida = cmd_idioma(&dir)
.env("CONTEXT7_LANG", "xx-invalido")
.args(["keys", "list"])
.output()
.unwrap();
let stderr = String::from_utf8_lossy(&saida.stderr);
assert!(
!stderr.contains("thread 'main' panicked"),
"CONTEXT7_LANG inválido não deve causar panic: {stderr}"
);
}
#[test]
#[serial]
fn testa_erro_sem_chave_mensagem_legivel_pt() {
let dir = TempDir::new().unwrap();
let saida = cmd_idioma(&dir)
.env("CONTEXT7_LANG", "pt")
.args(["library", "react"])
.output()
.unwrap();
assert!(!saida.status.success());
let stderr = String::from_utf8_lossy(&saida.stderr);
let stdout = String::from_utf8_lossy(&saida.stdout);
let combinado = format!("{stdout}{stderr}");
assert!(
!combinado.contains("thread 'main' panicked"),
"não deve panic: {combinado}"
);
}
#[test]
#[serial]
fn testa_erro_sem_chave_mensagem_legivel_en() {
let dir = TempDir::new().unwrap();
let saida = cmd_idioma(&dir)
.env("CONTEXT7_LANG", "en")
.args(["library", "react"])
.output()
.unwrap();
assert!(!saida.status.success());
let stderr = String::from_utf8_lossy(&saida.stderr);
let stdout = String::from_utf8_lossy(&saida.stdout);
let combinado = format!("{stdout}{stderr}");
assert!(
!combinado.contains("thread 'main' panicked"),
"não deve panic: {combinado}"
);
}
#[test]
#[serial]
fn testa_keys_list_mascara_chave_longa() {
let dir = TempDir::new().unwrap();
let chave = "ctx7sk-chave-muito-longa-para-mascarar";
cmd_idioma(&dir)
.args(["keys", "add", chave])
.assert()
.success();
let output = cmd_idioma(&dir).args(["keys", "list"]).output().unwrap();
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(
!stdout.contains(chave),
"chave completa não deve aparecer em texto claro no list: {stdout}"
);
assert!(
stdout.contains("..."),
"chave longa mascarada deve usar '...': {stdout}"
);
}
#[test]
#[serial]
fn testa_keys_list_mascara_chave_curta() {
let dir = TempDir::new().unwrap();
let chave = "abc1234"; cmd_idioma(&dir)
.args(["keys", "add", chave])
.assert()
.success();
let output = cmd_idioma(&dir).args(["keys", "list"]).output().unwrap();
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(
!stdout.contains(chave),
"chave curta completa não deve aparecer no list: {stdout}"
);
}
use context7_cli::i18n::{resolver_idioma, Idioma, Mensagem};
#[test]
fn testa_resolver_flag_explicita_en() {
let idioma = resolver_idioma(Some("en"));
assert!(matches!(idioma, Idioma::English));
}
#[test]
fn testa_resolver_flag_explicita_pt() {
let idioma = resolver_idioma(Some("pt"));
assert!(matches!(idioma, Idioma::Portugues));
}
#[test]
#[serial]
fn testa_resolver_env_context7_lang_pt_quando_sem_flag() {
unsafe { std::env::set_var("CONTEXT7_LANG", "pt") };
let idioma = resolver_idioma(None);
unsafe { std::env::remove_var("CONTEXT7_LANG") };
assert!(matches!(idioma, Idioma::Portugues));
}
#[test]
fn testa_resolver_fallback_quando_tudo_none_retorna_idioma_valido() {
let idioma = resolver_idioma(None);
assert!(matches!(idioma, Idioma::English | Idioma::Portugues));
}
#[test]
fn testa_mensagem_operacao_cancelada_en_vs_pt_sao_distintas() {
let variante = Mensagem::OperacaoCancelada;
let _ = variante; let _ = resolver_idioma(Some("en"));
let _ = resolver_idioma(Some("pt"));
}