Skip to content

Commit b4ed5a3

Browse files
committed
test(language_server): add Tester for ServerFormatter
1 parent 9836c1c commit b4ed5a3

File tree

5 files changed

+151
-0
lines changed

5 files changed

+151
-0
lines changed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
class C1 {
2+
#name: string;
3+
4+
public get name() {
5+
return this.#name;
6+
}
7+
8+
private set name(name: string) {
9+
this.#name = name;
10+
}
11+
}
12+
13+
class C2 {
14+
#name: string;
15+
16+
private set name(name: string) {
17+
this.#name = name;
18+
}
19+
20+
public get name() {
21+
return this.#name;
22+
}
23+
}
24+
25+
const c1 = new C1();
26+
const c2 = new C2();
27+
28+
29+
// no error
30+
c1.name;
31+
32+
// no error
33+
c2.name;
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
pub mod options;
22
pub mod server_formatter;
3+
#[cfg(test)]
4+
mod tester;

crates/oxc_language_server/src/formatter/server_formatter.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ fn compute_minimal_text_edit<'a>(
107107
#[cfg(test)]
108108
mod tests {
109109
use super::compute_minimal_text_edit;
110+
use crate::formatter::{options::FormatOptions, tester::Tester};
110111

111112
#[test]
112113
#[should_panic(expected = "assertion failed")]
@@ -188,4 +189,10 @@ mod tests {
188189
let (start, end, replacement) = compute_minimal_text_edit(&src, &formatted);
189190
assert_eq!((start, end, replacement), (0, 0, "b"));
190191
}
192+
193+
#[test]
194+
fn test_formatter() {
195+
Tester::new("fixtures/formatter/basic", Some(FormatOptions { experimental: true }))
196+
.format_and_snapshot_single_file("basic.ts");
197+
}
191198
}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
use std::{fmt::Write, path::PathBuf};
2+
3+
use tower_lsp_server::{
4+
UriExt,
5+
lsp_types::{TextEdit, Uri},
6+
};
7+
8+
use crate::{formatter::options::FormatOptions, options::Options, worker::WorkspaceWorker};
9+
10+
/// Given a file path relative to the crate root directory, return the absolute path of the file.
11+
pub fn get_file_path(relative_file_path: &str) -> PathBuf {
12+
std::env::current_dir().expect("could not get current dir").join(relative_file_path)
13+
}
14+
15+
/// Given a file path relative to the crate root directory, return the URI of the file.
16+
pub fn get_file_uri(relative_file_path: &str) -> Uri {
17+
Uri::from_file_path(get_file_path(relative_file_path))
18+
.expect("failed to convert file path to URL")
19+
}
20+
21+
fn get_snapshot_from_text_edits(edits: &[TextEdit]) -> String {
22+
edits
23+
.iter()
24+
.map(|edit| format!("{:#?},\n\n{:?}", edit.range, edit.new_text))
25+
.collect::<Vec<_>>()
26+
.join("\n")
27+
}
28+
29+
/// Testing struct for the [formatter server][crate::formatter::server_formatter::ServerFormatter].
30+
pub struct Tester<'t> {
31+
relative_root_dir: &'t str,
32+
options: Option<FormatOptions>,
33+
}
34+
35+
impl Tester<'_> {
36+
pub fn new(relative_root_dir: &'static str, options: Option<FormatOptions>) -> Self {
37+
Self { relative_root_dir, options }
38+
}
39+
40+
async fn create_workspace_worker(&self) -> WorkspaceWorker {
41+
let absolute_path = std::env::current_dir()
42+
.expect("could not get current dir")
43+
.join(self.relative_root_dir);
44+
let uri = Uri::from_file_path(absolute_path).expect("could not convert current dir to uri");
45+
let worker = WorkspaceWorker::new(uri);
46+
let option =
47+
&Options { format: self.options.clone().unwrap_or_default(), ..Default::default() };
48+
worker.start_worker(option).await;
49+
50+
worker
51+
}
52+
53+
pub fn format_and_snapshot_single_file(&self, relative_file_path: &str) {
54+
self.format_and_snapshot_multiple_file(&[relative_file_path]);
55+
}
56+
57+
#[expect(clippy::disallowed_methods)]
58+
pub fn format_and_snapshot_multiple_file(&self, relative_file_paths: &[&str]) {
59+
let mut snapshot_result = String::new();
60+
for relative_file_path in relative_file_paths {
61+
let uri = get_file_uri(&format!("{}/{}", self.relative_root_dir, relative_file_path));
62+
let formatted = tokio::runtime::Runtime::new().unwrap().block_on(async {
63+
self.create_workspace_worker().await.format_file(&uri, None).await
64+
});
65+
66+
let snapshot = if let Some(formatted) = formatted {
67+
get_snapshot_from_text_edits(&formatted)
68+
} else {
69+
"File is ignored".to_string()
70+
};
71+
72+
let _ = write!(
73+
snapshot_result,
74+
"########## \nfile: {}/{relative_file_path}\n----------\n{snapshot}\n",
75+
self.relative_root_dir
76+
);
77+
}
78+
79+
let snapshot_name = self.relative_root_dir.replace('/', "_");
80+
let mut settings = insta::Settings::clone_current();
81+
settings.set_snapshot_path(
82+
std::env::current_dir().expect("could not get current dir").join("src/snapshots"),
83+
);
84+
settings.set_prepend_module_to_snapshot(false);
85+
settings.set_omit_expression(true);
86+
settings.set_snapshot_suffix(relative_file_paths.join("_").replace('\\', "/"));
87+
settings.bind(|| {
88+
insta::assert_snapshot!(snapshot_name, snapshot_result);
89+
});
90+
}
91+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
---
2+
source: crates/oxc_language_server/src/formatter/tester.rs
3+
---
4+
##########
5+
file: fixtures/formatter/basic/basic.ts
6+
----------
7+
Range {
8+
start: Position {
9+
line: 1,
10+
character: 2,
11+
},
12+
end: Position {
13+
line: 26,
14+
character: 0,
15+
},
16+
},
17+
18+
"#name: string;\n\n public get name() {\n return this.#name;\n }\n\n private set name(name: string) {\n this.#name = name;\n }\n}\n\nclass C2 {\n #name: string;\n\n private set name(name: string) {\n this.#name = name;\n }\n\n public get name() {\n return this.#name;\n }\n}\n\nconst c1 = new C1();\nconst c2 = new C2();"

0 commit comments

Comments
 (0)