Skip to content

Commit 924aeba

Browse files
committed
chore(cli): add snapshot tests for reporters
1 parent 37ff15a commit 924aeba

11 files changed

+186
-97
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,4 @@ squawk/
3030
# Auto generated treesitter files
3131
crates/pgt_treesitter_grammar/src/grammar.json
3232
crates/pgt_treesitter_grammar/src/node-types.json
33-
crates/pgt_treesitter_grammar/src/parser.c
33+
crates/pgt_treesitter_grammar/src/parser.c

Cargo.lock

Lines changed: 2 additions & 19 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/pgt_cli/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ tikv-jemallocator = "0.6.0"
5353

5454
[dev-dependencies]
5555
assert_cmd = "2.0.16"
56-
predicates = "3.1.3"
56+
insta = { version = "1.40.0", features = ["yaml"] }
5757

5858
[lib]
5959
doctest = false

crates/pgt_cli/tests/assert_cmd.rs

Lines changed: 49 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,58 @@
11
use std::path::PathBuf;
22

33
use assert_cmd::Command;
4-
use predicates::prelude::*;
4+
use insta::assert_snapshot;
5+
6+
const BIN: &str = "postgres-language-server";
57

68
#[test]
79
fn test_cli_check_command() {
8-
let mut cmd = Command::cargo_bin("postgrestools").unwrap();
10+
let output = Command::cargo_bin(BIN)
11+
.unwrap()
12+
.args([
13+
"check",
14+
PathBuf::from("tests/fixtures/test.sql").to_str().unwrap(),
15+
])
16+
.output()
17+
.unwrap();
18+
19+
assert!(!output.status.success(), "command unexpectedly succeeded");
920

10-
let test_sql_path = PathBuf::from("tests/fixtures/test.sql");
21+
let stdout = String::from_utf8_lossy(&output.stdout).to_string();
22+
assert_snapshot!(normalize_durations(&stdout));
23+
}
1124

12-
cmd.args(["check", test_sql_path.to_str().unwrap()])
13-
.assert()
14-
.failure()
15-
.stdout(predicate::str::contains("Found 1 error"));
25+
fn normalize_durations(input: &str) -> String {
26+
let mut content = input.to_owned();
27+
let mut search_start = 0;
28+
while let Some(relative) = content[search_start..].find(" in ") {
29+
let start = search_start + relative + 4;
30+
if let Some(end_rel) = content[start..].find('.') {
31+
let end = start + end_rel;
32+
let slice = &content[start..end];
33+
if slice.chars().any(|c| c.is_ascii_digit()) {
34+
content.replace_range(start..end, "<duration>");
35+
search_start = start + "<duration>".len() + 1;
36+
continue;
37+
}
38+
search_start = end + 1;
39+
} else {
40+
break;
41+
}
42+
}
43+
let mut time_search = 0;
44+
while let Some(relative) = content[time_search..].find("time=\"") {
45+
let start = time_search + relative + 6;
46+
if let Some(end_rel) = content[start..].find('"') {
47+
let end = start + end_rel;
48+
let slice = &content[start..end];
49+
if slice.chars().any(|c| c.is_ascii_digit()) {
50+
content.replace_range(start..end, "<duration>");
51+
}
52+
time_search = end + 1;
53+
} else {
54+
break;
55+
}
56+
}
57+
content
1658
}
Lines changed: 71 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,78 @@
1-
use bpaf::Args;
2-
use std::path::Path;
1+
use assert_cmd::Command;
2+
use insta::assert_snapshot;
3+
use std::path::PathBuf;
34

4-
use crate::run_cli;
5-
use pgt_console::BufferConsole;
6-
use pgt_fs::MemoryFileSystem;
7-
use pgt_workspace::DynRef;
5+
const BIN: &str = "postgres-language-server";
6+
7+
fn run_check(args: &[&str]) -> String {
8+
let mut cmd = Command::cargo_bin(BIN).expect("binary not built");
9+
let mut full_args = vec!["check".to_string()];
10+
full_args.extend(args.iter().map(|s| s.to_string()));
11+
let test_sql = PathBuf::from("tests/fixtures/test.sql");
12+
full_args.push(test_sql.to_str().unwrap().to_string());
13+
14+
let output = cmd.args(&full_args).output().expect("failed to run CLI");
15+
assert!(
16+
!output.status.success(),
17+
"command unexpectedly succeeded: {:?}",
18+
output.status
19+
);
20+
21+
normalize_durations(&String::from_utf8_lossy(&output.stdout))
22+
}
23+
24+
fn normalize_durations(input: &str) -> String {
25+
let mut content = input.to_owned();
26+
27+
let mut search_start = 0;
28+
while let Some(relative) = content[search_start..].find(" in ") {
29+
let start = search_start + relative + 4;
30+
if let Some(end_rel) = content[start..].find('.') {
31+
let end = start + end_rel;
32+
if content[start..end].chars().any(|c| c.is_ascii_digit()) {
33+
content.replace_range(start..end, "<duration>");
34+
search_start = start + "<duration>".len() + 1;
35+
continue;
36+
}
37+
search_start = end + 1;
38+
} else {
39+
break;
40+
}
41+
}
42+
43+
let mut time_search = 0;
44+
while let Some(relative) = content[time_search..].find("time=\"") {
45+
let start = time_search + relative + 6;
46+
if let Some(end_rel) = content[start..].find('"') {
47+
let end = start + end_rel;
48+
if content[start..end].chars().any(|c| c.is_ascii_digit()) {
49+
content.replace_range(start..end, "<duration>");
50+
}
51+
time_search = end + 1;
52+
} else {
53+
break;
54+
}
55+
}
56+
57+
content
58+
}
859

960
#[test]
10-
fn syntax_error() {
11-
let mut fs = MemoryFileSystem::default();
12-
let mut console = BufferConsole::default();
61+
fn check_default_reporter_snapshot() {
62+
assert_snapshot!(run_check(&[]));
63+
}
1364

14-
let file_path = Path::new("test.sql");
15-
fs.insert(file_path.into(), "select 1".as_bytes());
65+
#[test]
66+
fn check_github_reporter_snapshot() {
67+
assert_snapshot!(run_check(&["--reporter", "github"]));
68+
}
1669

17-
let result = run_cli(
18-
DynRef::Borrowed(&mut fs),
19-
&mut console,
20-
Args::from([("check"), file_path.as_os_str().to_str().unwrap()].as_slice()),
21-
);
70+
#[test]
71+
fn check_gitlab_reporter_snapshot() {
72+
assert_snapshot!(run_check(&["--reporter", "gitlab"]));
73+
}
2274

23-
assert!(result.is_ok(), "run_cli returned {result:?}");
75+
#[test]
76+
fn check_junit_reporter_snapshot() {
77+
assert_snapshot!(run_check(&["--reporter", "junit"]));
2478
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
source: crates/pgt_cli/tests/commands/check.rs
3+
expression: "run_check(&[])"
4+
snapshot_kind: text
5+
---
6+
Warning: You are using the deprecated config filename 'postgrestools.jsonc'. Please rename it to 'postgres-language-server.jsonc'. Support for the old filename will be removed in a future version.
7+
8+
Checked 1 file in <duration>. No fixes applied.
9+
Found 1 error.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
source: crates/pgt_cli/tests/commands/check.rs
3+
expression: "run_check(&[\"--reporter\", \"github\"])"
4+
snapshot_kind: text
5+
---
6+
Warning: You are using the deprecated config filename 'postgrestools.jsonc'. Please rename it to 'postgres-language-server.jsonc'. Support for the old filename will be removed in a future version.
7+
8+
::error title=syntax,file=tests/fixtures/test.sql,line=1,endLine=1,col=1,endColumn=35::Invalid statement: syntax error at or near "tqjable"
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
---
2+
source: crates/pgt_cli/tests/commands/check.rs
3+
expression: "run_check(&[\"--reporter\", \"gitlab\"])"
4+
snapshot_kind: text
5+
---
6+
Warning: You are using the deprecated config filename 'postgrestools.jsonc'. Please rename it to 'postgres-language-server.jsonc'. Support for the old filename will be removed in a future version.
7+
8+
[
9+
{
10+
"description": "Invalid statement: syntax error at or near \"tqjable\"",
11+
"check_name": "syntax",
12+
"fingerprint": "15806099827984337215",
13+
"severity": "critical",
14+
"location": {
15+
"path": "tests/fixtures/test.sql",
16+
"lines": {
17+
"begin": 1
18+
}
19+
}
20+
}
21+
]
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
source: crates/pgt_cli/tests/commands/check.rs
3+
expression: "run_check(&[\"--reporter\", \"junit\"])"
4+
snapshot_kind: text
5+
---
6+
Warning: You are using the deprecated config filename 'postgrestools.jsonc'. Please rename it to 'postgres-language-server.jsonc'. Support for the old filename will be removed in a future version.
7+
8+
<?xml version="1.0" encoding="UTF-8"?>
9+
<testsuites name="PostgresTools" tests="1" failures="1" errors="1" time="<duration>">
10+
<testsuite name="tests/fixtures/test.sql" tests="1" disabled="0" errors="0" failures="1" package="org.pgt">
11+
<testcase name="org.pgt.syntax" line="1" column="1">
12+
<failure message="Invalid statement: syntax error at or near &quot;tqjable&quot;">line 0, col 0, Invalid statement: syntax error at or near &quot;tqjable&quot;</failure>
13+
</testcase>
14+
</testsuite>
15+
</testsuites>

crates/pgt_cli/tests/main.rs

Lines changed: 0 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1 @@
11
mod commands;
2-
3-
use bpaf::ParseFailure;
4-
use pgt_cli::{CliDiagnostic, CliSession, pgt_command};
5-
use pgt_console::{Console, ConsoleExt, markup};
6-
use pgt_fs::FileSystem;
7-
use pgt_workspace::{App, DynRef};
8-
9-
/// Create an [App] instance using the provided [FileSystem] and [Console]
10-
/// instance, and using an in-process "remote" instance of the workspace
11-
pub(crate) fn run_cli<'app>(
12-
fs: DynRef<'app, dyn FileSystem>,
13-
console: &'app mut dyn Console,
14-
args: bpaf::Args,
15-
) -> Result<(), CliDiagnostic> {
16-
use pgt_cli::SocketTransport;
17-
use pgt_lsp::ServerFactory;
18-
use pgt_workspace::{WorkspaceRef, workspace};
19-
use tokio::{
20-
io::{duplex, split},
21-
runtime::Runtime,
22-
};
23-
24-
let factory = ServerFactory::default();
25-
let connection = factory.create(None);
26-
27-
let runtime = Runtime::new().expect("failed to create runtime");
28-
29-
let (client, server) = duplex(4096);
30-
let (stdin, stdout) = split(server);
31-
runtime.spawn(connection.accept(stdin, stdout));
32-
33-
let (client_read, client_write) = split(client);
34-
let transport = SocketTransport::open(runtime, client_read, client_write);
35-
36-
let workspace = workspace::client(transport).unwrap();
37-
let app = App::new(fs, console, WorkspaceRef::Owned(workspace));
38-
39-
let mut session = CliSession { app };
40-
let command = pgt_command().run_inner(args);
41-
match command {
42-
Ok(command) => session.run(command),
43-
Err(failure) => {
44-
if let ParseFailure::Stdout(help, _) = &failure {
45-
let console = &mut session.app.console;
46-
console.log(markup! {{help.to_string()}});
47-
Ok(())
48-
} else {
49-
Err(CliDiagnostic::parse_error_bpaf(failure))
50-
}
51-
}
52-
}
53-
}

0 commit comments

Comments
 (0)