Skip to content

Commit

Permalink
test(format/html): set up test infrastructure (#3798)
Browse files Browse the repository at this point in the history
  • Loading branch information
dyc3 authored Sep 10, 2024
1 parent d7070f1 commit 7f02581
Show file tree
Hide file tree
Showing 15 changed files with 258 additions and 5 deletions.
4 changes: 4 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions crates/biome_configuration/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ biome_flags = { workspace = true }
biome_formatter = { workspace = true, features = ["serde"] }
biome_graphql_analyze = { workspace = true }
biome_graphql_syntax = { workspace = true }
biome_html_syntax = { workspace = true }
biome_js_analyze = { workspace = true }
biome_js_formatter = { workspace = true, features = ["serde"] }
biome_js_syntax = { workspace = true, features = ["schema"] }
Expand All @@ -50,10 +51,15 @@ schema = [
"biome_json_syntax/schema",
"biome_css_syntax/schema",
"biome_graphql_syntax/schema",
"biome_html_syntax/schema",
]

[dev-dependencies]
insta = { workspace = true }

[lints]
workspace = true

[package.metadata.cargo-udeps.ignore]
# currently technically not used, but needed in order to compile because of the `schema` feature
normal = ["biome_html_syntax"]
2 changes: 2 additions & 0 deletions crates/biome_html_formatter/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ biome_fs = { workspace = true }
biome_html_parser = { workspace = true }
biome_parser = { workspace = true }
biome_service = { workspace = true }
countme = { workspace = true, features = ["enable"] }
tests_macros = { workspace = true }

[lints]
workspace = true
33 changes: 33 additions & 0 deletions crates/biome_html_formatter/tests/prettier_tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
use std::{env, path::Path};

use biome_formatter::{IndentStyle, IndentWidth};
use biome_formatter_test::test_prettier_snapshot::{PrettierSnapshot, PrettierTestFile};
use biome_html_formatter::{context::HtmlFormatOptions, HtmlFormatLanguage};
use biome_html_syntax::HtmlFileSource;

mod language;

tests_macros::gen_tests! {"tests/specs/prettier/**/*.html", crate::test_snapshot, "script"}

#[allow(dead_code)]
fn test_snapshot(input: &'static str, _: &str, _: &str, _: &str) {
countme::enable(true);

let root_path = Path::new(concat!(
env!("CARGO_MANIFEST_DIR"),
"/tests/specs/prettier/"
));

let test_file = PrettierTestFile::new(input, root_path);
let source_type = HtmlFileSource::html();

let options = HtmlFormatOptions::new()
.with_indent_style(IndentStyle::Space)
.with_indent_width(IndentWidth::default());

let language = language::HtmlTestFormatLanguage::new(source_type);

let snapshot = PrettierSnapshot::new(test_file, language, HtmlFormatLanguage::new(options));

snapshot.test()
}
47 changes: 47 additions & 0 deletions crates/biome_html_formatter/tests/spec_test.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
use biome_formatter_test::spec::{SpecSnapshot, SpecTestFile};
use biome_html_formatter::{context::HtmlFormatOptions, HtmlFormatLanguage};
use biome_html_syntax::HtmlFileSource;
use std::path::Path;

mod language {
include!("language.rs");
}

/// [insta.rs](https://insta.rs/docs) snapshot testing
///
/// For better development workflow, run
/// `cargo watch -i '*.new' -x 'test -p biome_js_formatter formatter'`
///
/// To review and commit the snapshots, `cargo install cargo-insta`, and run
/// `cargo insta review` or `cargo insta accept`
///
/// The input and the expected output are stored as dedicated files in the `tests/specs` directory where
/// the input file name is `{spec_name}.json` and the output file name is `{spec_name}.json.snap`.
///
/// Specs can be grouped in directories by specifying the directory name in the spec name. Examples:
///
/// # Examples
///
/// * `json/null` -> input: `tests/specs/json/null.json`, expected output: `tests/specs/json/null.json.snap`
/// * `null` -> input: `tests/specs/null.json`, expected output: `tests/specs/null.json.snap`
pub fn run(spec_input_file: &str, _expected_file: &str, test_directory: &str, _file_type: &str) {
let root_path = Path::new(concat!(env!("CARGO_MANIFEST_DIR"), "/tests/specs/"));

let Some(test_file) = SpecTestFile::try_from_file(spec_input_file, root_path, None) else {
return;
};

let source_type: HtmlFileSource = test_file.input_file().as_path().try_into().unwrap();

let options = HtmlFormatOptions::new();
let language = language::HtmlTestFormatLanguage::new(source_type);

let snapshot = SpecSnapshot::new(
test_file,
test_directory,
language,
HtmlFormatLanguage::new(options),
);

snapshot.test()
}
9 changes: 9 additions & 0 deletions crates/biome_html_formatter/tests/spec_tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
mod quick_test;
mod spec_test;

mod formatter {

mod html {
tests_macros::gen_tests! {"tests/specs/**/*.html", crate::spec_test::run, "unknown"}
}
}
1 change: 1 addition & 0 deletions crates/biome_html_formatter/tests/specs/example.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<!DOCTYPE html>
29 changes: 29 additions & 0 deletions crates/biome_html_formatter/tests/specs/example.html.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
source: crates/biome_formatter_test/src/snapshot_builder.rs
info: example.html
---
# Input

```html
<!DOCTYPE html>
```


=============================

# Outputs

## Output 1

-----
Indent style: Tab
Indent width: 2
Line ending: LF
Line width: 80
Attribute Position: Auto
-----

```html
<!DOCTYPE html>
```
12 changes: 12 additions & 0 deletions crates/biome_html_formatter/tests/specs/prettier/prepare_tests.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
const {extractPrettierTests} = require("../../../../biome_formatter_test/src/prettier/prepare_tests");

async function main() {
await extractPrettierTests("html", {
parser: "html",
});
}

main().catch((err) => {
console.error(err);
process.exit(1);
});
10 changes: 8 additions & 2 deletions crates/biome_html_syntax/src/file_source.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
use biome_rowan::FileSourceError;
use std::{ffi::OsStr, path::Path};

#[derive(Debug, Default, Clone)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[derive(
Debug, Clone, Default, Copy, Eq, PartialEq, Hash, serde::Serialize, serde::Deserialize,
)]
pub struct HtmlFileSource {
#[allow(unused)]
variant: HtmlVariant,
}

#[derive(Debug, Default, Clone)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[derive(
Debug, Clone, Default, Copy, Eq, PartialEq, Hash, serde::Serialize, serde::Deserialize,
)]
enum HtmlVariant {
#[default]
Standard,
Expand Down
1 change: 1 addition & 0 deletions crates/biome_service/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ biome_graphql_parser = { workspace = true }
biome_graphql_syntax = { workspace = true }
biome_grit_patterns = { workspace = true }
biome_html_formatter = { workspace = true }
biome_html_parser = { workspace = true }
biome_html_syntax = { workspace = true }
biome_js_analyze = { workspace = true }
biome_js_factory = { workspace = true, optional = true }
Expand Down
81 changes: 79 additions & 2 deletions crates/biome_service/src/file_handlers/html.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,20 @@
use biome_html_formatter::HtmlFormatOptions;
use biome_formatter::Printed;
use biome_fs::BiomePath;
use biome_html_formatter::{format_node, HtmlFormatOptions};
use biome_html_parser::parse_html_with_cache;
use biome_html_syntax::HtmlLanguage;
use biome_parser::AnyParse;
use biome_rowan::NodeCache;

use crate::settings::ServiceLanguage;
use crate::{
settings::{ServiceLanguage, Settings, WorkspaceSettingsHandle},
WorkspaceError,
};

use super::{
AnalyzerCapabilities, Capabilities, DebugCapabilities, DocumentFileSource, ExtensionHandler,
FormatterCapabilities, ParseResult, ParserCapabilities, SearchCapabilities,
};

impl ServiceLanguage for HtmlLanguage {
type FormatterSettings = ();
Expand Down Expand Up @@ -39,3 +52,67 @@ impl ServiceLanguage for HtmlLanguage {
todo!()
}
}

#[derive(Debug, Default, PartialEq, Eq)]
pub(crate) struct HtmlFileHandler;

impl ExtensionHandler for HtmlFileHandler {
fn capabilities(&self) -> Capabilities {
Capabilities {
parser: ParserCapabilities { parse: Some(parse) },
debug: DebugCapabilities {
debug_syntax_tree: None,
debug_control_flow: None,
debug_formatter_ir: None,
},
analyzer: AnalyzerCapabilities {
lint: None,
code_actions: None,
rename: None,
fix_all: None,
organize_imports: None,
},
formatter: FormatterCapabilities {
format: Some(format),
format_range: None,
format_on_type: None,
},
search: SearchCapabilities { search: None },
}
}
}

fn parse(
_biome_path: &BiomePath,
file_source: DocumentFileSource,
text: &str,
_settings: Option<&Settings>,
cache: &mut NodeCache,
) -> ParseResult {
let parse = parse_html_with_cache(text, cache);

ParseResult {
any_parse: parse.into(),
language: Some(file_source),
}
}

#[tracing::instrument(level = "debug", skip(parse, settings))]
fn format(
biome_path: &BiomePath,
document_file_source: &DocumentFileSource,
parse: AnyParse,
settings: WorkspaceSettingsHandle,
) -> Result<Printed, WorkspaceError> {
let options = settings.format_options::<HtmlLanguage>(biome_path, document_file_source);

tracing::debug!("Format with the following options: \n{}", options);

let tree = parse.syntax();
let formatted = format_node(options, &tree)?;

match formatted.print() {
Ok(printed) => Ok(printed),
Err(error) => Err(WorkspaceError::FormatError(error.into())),
}
}
Loading

0 comments on commit 7f02581

Please sign in to comment.