swc/crates/swc_ecma_transforms_module/tests/amd.rs
Levi bfea322351
feat(es/testing): Parse test code as a Program instead of a Module (#9623)
**Description:**

This PR addresses the issue described in https://github.com/swc-project/swc/issues/8713

**BREAKING CHANGE:**
Will break unit tests that use `fold_module`/`visit_module`/`visit_mut_module` if the visitor is intended to work for both modules and scripts instead of using `fold_program`/`visit_program`/`visit_mut_program`.

When creating visitors, you should use `fold_program`/`visit_program`/`visit_mut_program` if you simply want to visit the top-level node.

When creating tests, the input source code will be parsed using `parse_program` by default. If you need to parse it as a `Module`, you can use `module: Some(true)` in `FixtureTestConfig` (or with `test!(module, ..)`), which will parse it as a `Program::Module`, or `Some(false)` for `Program::Script`. `None` will use `parse_program` (`parse_program` will auto-detect the underlying type).
2024-10-08 13:58:58 +09:00

94 lines
2.6 KiB
Rust

use std::{fs::File, path::PathBuf, rc::Rc};
use swc_common::{chain, comments::SingleThreadedComments, Mark};
use swc_ecma_parser::{Syntax, TsSyntax};
use swc_ecma_transforms_base::{feature::FeatureFlag, resolver};
use swc_ecma_transforms_compat::es2015::for_of;
use swc_ecma_transforms_module::amd::{self, amd};
use swc_ecma_transforms_testing::{test, test_fixture, FixtureTestConfig};
use swc_ecma_transforms_typescript::typescript;
use swc_ecma_visit::Fold;
fn syntax() -> Syntax {
Default::default()
}
fn ts_syntax() -> Syntax {
Syntax::Typescript(TsSyntax::default())
}
fn tr(config: amd::Config, is_ts: bool, comments: Rc<SingleThreadedComments>) -> impl Fold {
let unresolved_mark = Mark::new();
let top_level_mark = Mark::new();
let avalible_set = FeatureFlag::all();
chain!(
resolver(unresolved_mark, top_level_mark, is_ts),
typescript::typescript(Default::default(), unresolved_mark, top_level_mark),
amd(
Default::default(),
unresolved_mark,
config,
avalible_set,
Some(comments)
),
)
}
#[testing::fixture("tests/fixture/common/**/input.js")]
#[testing::fixture("tests/fixture/common/**/input.ts")]
#[testing::fixture("tests/fixture/common/**/input.cts")]
fn esm_to_amd(input: PathBuf) {
let is_ts = input
.file_name()
.map(|x| x.to_string_lossy())
.map(|x| x.ends_with(".ts") || x.ends_with(".mts") || x.ends_with(".cts"))
.unwrap_or_default();
let dir = input.parent().unwrap().to_path_buf();
let output = dir
.join("output.amd.js")
.with_extension(if is_ts { "ts" } else { "js" });
let amd_config_path = dir.join("module.amd.json");
let config_path = dir.join("module.json");
let config: amd::Config = match File::open(amd_config_path).or_else(|_| File::open(config_path))
{
Ok(file) => serde_json::from_reader(file).unwrap(),
Err(..) => Default::default(),
};
test_fixture(
if is_ts { ts_syntax() } else { syntax() },
&|t| tr(config.clone(), is_ts, t.comments.clone()),
&input,
&output,
FixtureTestConfig {
module: Some(true),
..Default::default()
},
);
}
test!(
module,
syntax(),
|t| chain!(
for_of(for_of::Config {
assume_array: true,
..Default::default()
}),
tr(Default::default(), false, t.comments.clone())
),
for_of_as_array_for_of_import_amd,
r#"
import { array } from "foo";
for (const elm of array) {
console.log(elm);
}
"#
);