use axum::body::Body;
use axum::http::Request;
use regex::Regex;
use crate::{App, Response, Server, INDEX_HTML};
async fn get_dest(server: &Server, path: &str, dest: &str) -> Response {
server
.request(
Request::get(path)
.header("sec-fetch-dest", dest)
.body(Body::empty())
.unwrap(),
)
.await
}
fn content_type(res: &Response) -> &str {
res.headers
.get("content-type")
.and_then(|v| v.to_str().ok())
.unwrap_or("")
}
#[tokio::test(flavor = "multi_thread")]
async fn stylesheet_imports_serve_compiled_css_and_svg_is_a_url_module() {
let app = App::new(&[
("package.json", r#"{"name":"cssurl-app","version":"1.0.0"}"#),
("src/a.scss", "$c: red;\n.a { color: $c; }\n"),
("src/b.css", ".b {\n color: blue;\n}\n"),
(
"src/assets/logo.svg",
r#"<svg xmlns="http://www.w3.org/2000/svg" width="4" height="4"><rect width="4" height="4"/></svg>"#,
),
(
"src/main.js",
"import aUrl from \"./a.scss?url\";\nimport bInline from \"./b.css?inline\";\nimport logo from \"@/assets/logo.svg\";\nwindow.__A = aUrl; window.__B = bInline; window.__LOGO = logo;\n",
),
("index.html", INDEX_HTML),
]);
let src = serde_json::to_string(&app.root.join("src").to_string_lossy()).unwrap();
let config = format!("export default {{ resolve: {{ alias: {{ \"@\": {src} }} }} }};\n");
app.write(&[("vite.config.js", config.as_str())]);
let server = app.serve().await;
let has = |re: &str, s: &str| Regex::new(re).unwrap().is_match(s);
let main = server.text("/src/main.js").await;
assert!(
main.contains(r#""/src/assets/logo.svg?url""#),
"aliased svg not marked as an asset:\n{main}"
);
let a_url_mod = server.text("/src/a.scss?url").await;
assert!(
a_url_mod.contains(r#"export default "/src/a.scss?direct""#),
"scss ?url module:\n{a_url_mod}"
);
let direct = server.get("/src/a.scss?direct").await;
assert_eq!(direct.status, 200, "?direct:\n{}", direct.body);
assert!(
content_type(&direct).contains("text/css"),
"?direct is css text: {}",
content_type(&direct)
);
assert!(
has(r"color:\s*red", &direct.body),
"?direct is compiled sass:\n{}",
direct.body
);
assert!(
!direct.body.contains("$c"),
"sass variable left in ?direct output:\n{}",
direct.body
);
let linked = get_dest(&server, "/src/a.scss", "style").await;
assert_eq!(linked.status, 200, "link request:\n{}", linked.body);
assert!(
has(r"color:\s*red", &linked.body),
"link request not compiled:\n{}",
linked.body
);
let b_inline = server.text("/src/b.css?inline").await;
assert!(
has(
r#"export default "\.b\{color:blue\}|export default ".b \{"#,
&b_inline
),
"css ?inline in dev:\n{b_inline}"
);
let logo_mod = get_dest(&server, "/src/assets/logo.svg", "script").await;
assert_eq!(logo_mod.status, 200, "svg import:\n{}", logo_mod.body);
assert!(
logo_mod
.body
.contains(r#"export default "/src/assets/logo.svg""#),
"svg import is not a URL module:\n{}",
logo_mod.body
);
let img = get_dest(&server, "/src/assets/logo.svg", "image").await;
assert_eq!(img.status, 200, "img request");
assert!(
content_type(&img).contains("image/svg+xml"),
"img request still serves the svg: {}",
content_type(&img)
);
}