oj_server 0.2.36

Dev server: on-demand compile over HTTP, WebSocket HMR channel, file watcher
// SPDX-License-Identifier: MIT
// Copyright (c) 2026 Raphael Amorim

//! A dep in a node_modules above the root is served however the request
//! arrives: a browser reloading into a restarted server fetches the imports it
//! remembers before their importer, so the allow list cannot wait for that
//! compile. Anything else outside the root stays forbidden.

use crate::{App, INDEX_HTML};

#[tokio::test(flavor = "multi_thread")]
async fn a_dep_above_the_root_is_served_before_its_importer_compiles() {
    let app = App::new(&[
        (
            "node_modules/sched/package.json",
            r#"{"name":"sched","main":"index.js"}"#,
        ),
        ("node_modules/sched/index.js", "export const tick = 1;\n"),
        ("secret.js", "export const key = \"no\";\n"),
        ("web/package.json", r#"{"name":"web","version":"1.0.0"}"#),
        (
            // Nothing has compiled an importer of the dep yet, as after a
            // restart before the browser's remembered imports reach theirs.
            "web/src/main.js",
            "window.__t = 1;\n",
        ),
        ("web/index.html", INDEX_HTML),
    ]);
    let mut dev = app.dev();
    dev.root = app.root.join("web");
    let server = crate::serve(dev).await;
    let root = std::fs::canonicalize(&app.root).unwrap();

    let dep = server
        .get(&format!(
            "/@fs{}/node_modules/sched/index.js",
            root.display()
        ))
        .await;
    assert_eq!(dep.status, 200, "{}", dep.body);

    let secret = server
        .get(&format!("/@fs{}/secret.js", root.display()))
        .await;
    assert_eq!(
        secret.status, 403,
        "outside node_modules stays forbidden: {}",
        secret.body
    );
}