use std::sync::Arc;
use enhanced_magic_string::{
bundle::BundleOptions,
magic_string::{MagicString, MagicStringOptions},
types::{MappingsOptionHires, SourceMapOptions},
};
use farmfe_utils::relative;
use parking_lot::Mutex;
use crate::common::normalize_newlines;
mod common;
#[test]
fn bundle() {
fixture!("tests/fixtures/bundle/**/input.js", |file, _| {
println!("[bundle test] file: {:?}", file);
let mut modules = vec![];
let dir = file.parent().unwrap();
let modules_dir = dir.join("modules");
if modules_dir.exists() {
let paths = glob::glob(&modules_dir.join("**/*.js").to_string_lossy()).unwrap();
for path in paths {
let path = path.unwrap();
let content = std::fs::read_to_string(&path).unwrap();
let mut m = MagicString::new(
&content,
Some(MagicStringOptions {
filename: Some(relative(
dir.to_string_lossy().to_string().as_str(),
path.to_str().unwrap(),
)),
..Default::default()
}),
);
m.prepend("/* module */");
m.append("/* end of module */");
modules.push(m);
}
}
let file_content = std::fs::read_to_string(&file).unwrap();
let magic_string = MagicString::new(
&file_content,
Some(MagicStringOptions {
filename: Some(relative(
dir.to_string_lossy().to_string().as_str(),
file.to_str().unwrap(),
)),
..Default::default()
}),
);
let mut bundle = enhanced_magic_string::bundle::Bundle::new(BundleOptions::default());
bundle.add_source(magic_string, None).unwrap();
modules.into_iter().for_each(|module| {
bundle.add_source(module, None).unwrap();
});
bundle.prepend("/* header */\n");
bundle.append("//# sourceMappingURL=output.js.map", None);
let code = bundle.to_string();
let map = bundle
.generate_map(SourceMapOptions {
include_content: Some(true),
..Default::default()
})
.unwrap();
let mut src_buf = vec![];
map.to_writer(&mut src_buf).unwrap();
let map_str = String::from_utf8(src_buf).unwrap();
let expected = std::fs::read_to_string(dir.join("output.js")).unwrap();
assert_eq!(normalize_newlines(&code), normalize_newlines(&expected));
let expected_map = std::fs::read_to_string(dir.join("output.js.map")).unwrap();
assert_eq!(
normalize_newlines(&map_str),
normalize_newlines(&expected_map.replace(";\"}", "\"}"))
);
});
}
#[test]
fn bundle_multi_thread() {
let bundle = Mutex::new(enhanced_magic_string::bundle::Bundle::new(
BundleOptions::default(),
));
std::thread::scope(|s| {
s.spawn(|| {
let mut a = MagicString::new("a", None);
a.prepend("/* ");
a.append(" */");
bundle.lock().add_source(a, None).unwrap();
});
});
std::thread::scope(|s| {
s.spawn(|| {
let mut b = MagicString::new("b", None);
b.prepend("/* ");
b.append(" */");
bundle.lock().add_source(b, None).unwrap();
});
});
let code = bundle.lock().to_string();
assert_eq!(code, "/* a */\n/* b */");
}
#[test]
fn combine_string_with_original_sourcemap() {
fixture!("tests/fixtures/combine-string/**/input.js", |file, _| {
println!("[combine string test] file: {:?}", file);
let mut modules = vec![];
let dir = file.parent().unwrap();
let modules_dir = dir.join("modules");
if modules_dir.exists() {
let paths = glob::glob(&modules_dir.join("**/*.js").to_string_lossy()).unwrap();
for path in paths {
let path = path.unwrap();
let content = std::fs::read_to_string(&path).unwrap();
let sourcemap_content = std::fs::read_to_string(&path.with_extension("js.map")).unwrap();
let mut m = MagicString::new(
&content,
Some(MagicStringOptions {
filename: Some(relative(
dir.to_string_lossy().to_string().as_str(),
path.to_str().unwrap(),
)),
source_map_chain: vec![Arc::new(sourcemap_content)],
..Default::default()
}),
);
m.prepend("/* module */");
m.append("/* end of module */");
modules.push(m);
}
}
let file_content = std::fs::read_to_string(&file).unwrap();
let sourcemap_content = std::fs::read_to_string(&file.with_extension("js.map")).unwrap();
let magic_string = MagicString::new(
&file_content,
Some(MagicStringOptions {
filename: Some(relative(
dir.to_string_lossy().to_string().as_str(),
file.to_str().unwrap(),
)),
source_map_chain: vec![Arc::new(sourcemap_content)],
..Default::default()
}),
);
let mut bundle = enhanced_magic_string::bundle::Bundle::new(BundleOptions {
trace_source_map_chain: Some(true),
..Default::default()
});
bundle.add_source(magic_string, None).unwrap();
modules.into_iter().for_each(|module| {
bundle.add_source(module, None).unwrap();
});
bundle.prepend("/* header */\n");
bundle.append("//# sourceMappingURL=output.js.map", None);
let code = bundle.to_string();
let map = bundle
.generate_map(SourceMapOptions {
include_content: Some(true),
hires: Some(MappingsOptionHires::Boundary),
..Default::default()
})
.unwrap();
let mut src_buf = vec![];
map.to_writer(&mut src_buf).unwrap();
let map_str = String::from_utf8(src_buf).unwrap();
std::fs::write(dir.join("output.js"), &code).unwrap();
let expected = std::fs::read_to_string(dir.join("output.js")).unwrap();
assert_eq!(normalize_newlines(&code), normalize_newlines(&expected));
std::fs::write(dir.join("output.js.map"), &map_str).unwrap();
let expected_map = std::fs::read_to_string(dir.join("output.js.map")).unwrap();
assert_eq!(
normalize_newlines(&map_str),
normalize_newlines(&expected_map.replace(";\"}", "\"}"))
);
});
}