mirror of
https://github.com/zhom/banderole.git
synced 2026-04-22 11:56:16 +02:00
476 lines
14 KiB
Rust
476 lines
14 KiB
Rust
mod common;
|
|
|
|
use anyhow::Result;
|
|
use common::{
|
|
BundlerTestHelper, TestAssertions, TestCacheManager, TestProject, TestProjectManager,
|
|
};
|
|
use serial_test::serial;
|
|
|
|
#[tokio::test(flavor = "multi_thread")]
|
|
#[serial]
|
|
async fn test_npm_workspace_dependency_bundling() -> Result<()> {
|
|
println!("Testing npm workspace dependency bundling...");
|
|
|
|
// Create a workspace project with dependencies
|
|
let project = TestProject::new("workspace-test-app")
|
|
.workspace()
|
|
.with_dependency("adm-zip", "^0.5.10")
|
|
.with_dependency("commander", "^11.0.0");
|
|
|
|
let manager = TestProjectManager::create(project)?;
|
|
|
|
// Install dependencies in the workspace root
|
|
manager.install_workspace_dependencies()?;
|
|
|
|
// Verify that dependencies are installed in workspace root
|
|
let workspace_node_modules = manager.workspace_root().unwrap().join("node_modules");
|
|
assert!(
|
|
workspace_node_modules.join("adm-zip").exists(),
|
|
"adm-zip should be installed in workspace root"
|
|
);
|
|
assert!(
|
|
workspace_node_modules.join("commander").exists(),
|
|
"commander should be installed in workspace root"
|
|
);
|
|
|
|
// Bundle the workspace project)
|
|
let executable_path = BundlerTestHelper::bundle_project_with_compression(
|
|
manager.project_path(),
|
|
manager.temp_dir(),
|
|
Some("workspace-test"),
|
|
false,
|
|
)?;
|
|
|
|
// Test the bundled executable
|
|
TestAssertions::assert_executable_works(
|
|
&executable_path,
|
|
&[
|
|
"Hello from workspace project!",
|
|
"Dependencies:",
|
|
"adm-zip",
|
|
"commander",
|
|
"Successfully loaded adm-zip from workspace:",
|
|
"WORKSPACE_DEPENDENCY_TEST_PASSED",
|
|
],
|
|
&[],
|
|
&[],
|
|
)?;
|
|
|
|
println!("✅ npm workspace dependency bundling test passed!");
|
|
Ok(())
|
|
}
|
|
|
|
#[tokio::test(flavor = "multi_thread")]
|
|
#[serial]
|
|
async fn test_pnpm_workspace_dependency_bundling() -> Result<()> {
|
|
println!("Testing pnpm workspace dependency bundling...");
|
|
|
|
// Create a pnpm workspace project with dependencies
|
|
let project = TestProject::new("pnpm-workspace-test-app")
|
|
.pnpm_workspace()
|
|
.with_dependency("adm-zip", "^0.5.10")
|
|
.with_dependency("js-yaml", "^4.1.0");
|
|
|
|
let manager = TestProjectManager::create(project)?;
|
|
|
|
// Try to install dependencies using pnpm, fall back to npm if pnpm is not available
|
|
match manager.install_pnpm_dependencies() {
|
|
Ok(_) => {
|
|
println!("Successfully installed pnpm workspace dependencies");
|
|
}
|
|
Err(e) => {
|
|
println!("Pnpm installation failed, falling back to npm: {e}");
|
|
manager.install_workspace_dependencies()?;
|
|
}
|
|
}
|
|
|
|
// Bundle the pnpm workspace project)
|
|
let executable_path = BundlerTestHelper::bundle_project_with_compression(
|
|
manager.project_path(),
|
|
manager.temp_dir(),
|
|
Some("pnpm-workspace-test"),
|
|
false,
|
|
)?;
|
|
|
|
// Test the bundled executable
|
|
TestAssertions::assert_executable_works(
|
|
&executable_path,
|
|
&[
|
|
"Hello from pnpm workspace project!",
|
|
"Dependencies:",
|
|
"Successfully loaded adm-zip from pnpm workspace:",
|
|
"PNPM_WORKSPACE_DEPENDENCY_TEST_PASSED",
|
|
],
|
|
&[],
|
|
&[],
|
|
)?;
|
|
|
|
println!("✅ pnpm workspace dependency bundling test passed!");
|
|
Ok(())
|
|
}
|
|
|
|
#[tokio::test(flavor = "multi_thread")]
|
|
#[serial]
|
|
async fn test_workspace_with_typescript_project() -> Result<()> {
|
|
println!("Testing workspace with TypeScript project...");
|
|
|
|
// Create a workspace TypeScript project
|
|
let project = TestProject::new("workspace-ts-app")
|
|
.workspace()
|
|
.typescript("dist")
|
|
.with_dependency("lodash", "^4.17.21")
|
|
.with_dependency("@types/lodash", "^4.14.195");
|
|
|
|
let manager = TestProjectManager::create(project)?;
|
|
|
|
// Install dependencies
|
|
manager.install_workspace_dependencies()?;
|
|
|
|
// Bundle the TypeScript workspace project)
|
|
let executable_path = BundlerTestHelper::bundle_project_with_compression(
|
|
manager.project_path(),
|
|
manager.temp_dir(),
|
|
Some("workspace-ts-test"),
|
|
false,
|
|
)?;
|
|
|
|
// Test the bundled executable
|
|
TestAssertions::assert_executable_works(
|
|
&executable_path,
|
|
&[
|
|
"Hello from TypeScript project!",
|
|
"This should come from the compiled output directory",
|
|
"Marker file found: dist",
|
|
],
|
|
&[],
|
|
&[],
|
|
)?;
|
|
|
|
println!("✅ workspace TypeScript project bundling test passed!");
|
|
Ok(())
|
|
}
|
|
|
|
#[tokio::test(flavor = "multi_thread")]
|
|
#[serial]
|
|
async fn test_workspace_nested_dependencies() -> Result<()> {
|
|
println!("Testing workspace with nested dependencies...");
|
|
|
|
// Create a workspace project that tests transitive dependency resolution
|
|
let project = TestProject::new("nested-deps-app")
|
|
.workspace()
|
|
.with_dependency("express", "^4.18.2") // Has many transitive dependencies
|
|
.with_dependency("axios", "^1.6.0"); // Also has transitive dependencies
|
|
|
|
let manager = TestProjectManager::create(project)?;
|
|
|
|
// Install dependencies
|
|
manager.install_workspace_dependencies()?;
|
|
|
|
// Create a more complex index.js that tests nested dependencies
|
|
let complex_index_js = r#"console.log("Hello from nested dependencies test!");
|
|
|
|
try {
|
|
const express = require('express');
|
|
const axios = require('axios');
|
|
|
|
console.log("Successfully loaded express:", typeof express);
|
|
console.log("Successfully loaded axios:", typeof axios);
|
|
|
|
// Test that transitive dependencies are available
|
|
const app = express();
|
|
console.log("Express app created successfully");
|
|
|
|
// Test axios functionality
|
|
console.log("Axios version:", axios.VERSION || "unknown");
|
|
|
|
console.log("NESTED_DEPENDENCIES_TEST_PASSED");
|
|
} catch (e) {
|
|
console.error("Nested dependencies test failed:", e.message);
|
|
console.log("NESTED_DEPENDENCIES_TEST_FAILED");
|
|
process.exit(1);
|
|
}
|
|
|
|
console.log("Nested dependencies test completed!");
|
|
process.exit(0);"#;
|
|
|
|
std::fs::write(manager.project_path().join("index.js"), complex_index_js)?;
|
|
|
|
// Bundle the project)
|
|
let executable_path = BundlerTestHelper::bundle_project_with_compression(
|
|
manager.project_path(),
|
|
manager.temp_dir(),
|
|
Some("nested-deps-test"),
|
|
false,
|
|
)?;
|
|
|
|
// Test the bundled executable
|
|
TestAssertions::assert_dependency_test_passes(
|
|
&executable_path,
|
|
"NESTED_DEPENDENCIES_TEST_PASSED",
|
|
)?;
|
|
|
|
println!("✅ workspace nested dependencies test passed!");
|
|
Ok(())
|
|
}
|
|
|
|
#[tokio::test(flavor = "multi_thread")]
|
|
#[serial]
|
|
async fn test_workspace_with_bin_scripts() -> Result<()> {
|
|
println!("Testing workspace with bin scripts...");
|
|
|
|
// Create a workspace project with dependencies that have bin scripts
|
|
let project = TestProject::new("bin-scripts-app")
|
|
.workspace()
|
|
.with_dependency("semver", "^7.5.4") // Has a bin script
|
|
.with_dependency("rimraf", "^5.0.5"); // Has a bin script
|
|
|
|
let manager = TestProjectManager::create(project)?;
|
|
|
|
// Install dependencies
|
|
manager.install_workspace_dependencies()?;
|
|
|
|
// Verify that .bin directory exists in workspace
|
|
let workspace_bin = manager.workspace_root().unwrap().join("node_modules/.bin");
|
|
assert!(
|
|
workspace_bin.exists(),
|
|
".bin directory should exist in workspace node_modules"
|
|
);
|
|
|
|
// Bundle the project)
|
|
let executable_path = BundlerTestHelper::bundle_project_with_compression(
|
|
manager.project_path(),
|
|
manager.temp_dir(),
|
|
Some("bin-scripts-test"),
|
|
false,
|
|
)?;
|
|
|
|
// Test the bundled executable
|
|
TestAssertions::assert_executable_works(
|
|
&executable_path,
|
|
&[
|
|
"Hello from workspace project!",
|
|
"Dependencies:",
|
|
"Workspace project test completed!",
|
|
],
|
|
&[],
|
|
&[],
|
|
)?;
|
|
|
|
println!("✅ workspace bin scripts test passed!");
|
|
Ok(())
|
|
}
|
|
|
|
#[tokio::test(flavor = "multi_thread")]
|
|
#[serial]
|
|
async fn test_workspace_project_without_own_node_modules() -> Result<()> {
|
|
println!("Testing workspace project without its own node_modules...");
|
|
|
|
// Create a workspace project where dependencies are only in workspace root
|
|
let project = TestProject::new("no-local-deps-app")
|
|
.workspace()
|
|
.with_dependency("minimist", "^1.2.8")
|
|
.with_dependency("chalk", "^5.3.0");
|
|
|
|
let manager = TestProjectManager::create(project)?;
|
|
|
|
// Install dependencies only in workspace root
|
|
manager.install_workspace_dependencies()?;
|
|
|
|
// Ensure the project itself has no node_modules
|
|
let project_node_modules = manager.project_path().join("node_modules");
|
|
if project_node_modules.exists() {
|
|
std::fs::remove_dir_all(&project_node_modules)?;
|
|
}
|
|
|
|
// Verify workspace has the dependencies
|
|
let workspace_node_modules = manager.workspace_root().unwrap().join("node_modules");
|
|
assert!(
|
|
workspace_node_modules.join("minimist").exists(),
|
|
"minimist should be in workspace node_modules"
|
|
);
|
|
|
|
// Bundle the project)
|
|
let executable_path = BundlerTestHelper::bundle_project_with_compression(
|
|
manager.project_path(),
|
|
manager.temp_dir(),
|
|
Some("no-local-deps-test"),
|
|
false,
|
|
)?;
|
|
|
|
// Test the bundled executable
|
|
TestAssertions::assert_executable_works(
|
|
&executable_path,
|
|
&[
|
|
"Hello from workspace project!",
|
|
"Dependencies:",
|
|
"Workspace project test completed!",
|
|
],
|
|
&[],
|
|
&[],
|
|
)?;
|
|
|
|
println!("✅ workspace project without local node_modules test passed!");
|
|
Ok(())
|
|
}
|
|
|
|
#[tokio::test(flavor = "multi_thread")]
|
|
#[serial]
|
|
async fn test_workspace_with_peer_dependencies() -> Result<()> {
|
|
println!("Testing workspace with peer dependencies...");
|
|
|
|
// Create a project that has peer dependencies
|
|
let project = TestProject::new("peer-deps-app")
|
|
.workspace()
|
|
.with_dependency("react", "^18.2.0")
|
|
.with_dependency("prop-types", "^15.8.1"); // Has react as peer dependency
|
|
|
|
let manager = TestProjectManager::create(project)?;
|
|
|
|
// Create a custom package.json that includes peerDependencies
|
|
let package_json_with_peers = r#"{
|
|
"name": "peer-deps-app",
|
|
"version": "1.0.0",
|
|
"main": "index.js",
|
|
"scripts": {
|
|
"start": "node index.js"
|
|
},
|
|
"dependencies": {
|
|
"react": "^18.2.0",
|
|
"prop-types": "^15.8.1"
|
|
},
|
|
"peerDependencies": {
|
|
"react": "^18.0.0"
|
|
}
|
|
}"#;
|
|
|
|
std::fs::write(
|
|
manager.project_path().join("package.json"),
|
|
package_json_with_peers,
|
|
)?;
|
|
|
|
// Install dependencies
|
|
manager.install_workspace_dependencies()?;
|
|
|
|
// Bundle the project)
|
|
let executable_path = BundlerTestHelper::bundle_project_with_compression(
|
|
manager.project_path(),
|
|
manager.temp_dir(),
|
|
Some("peer-deps-test"),
|
|
false,
|
|
)?;
|
|
|
|
// Test the bundled executable
|
|
TestAssertions::assert_executable_works(
|
|
&executable_path,
|
|
&[
|
|
"Hello from workspace project!",
|
|
"Dependencies:",
|
|
"Workspace project test completed!",
|
|
],
|
|
&[],
|
|
&[],
|
|
)?;
|
|
|
|
println!("✅ workspace peer dependencies test passed!");
|
|
Ok(())
|
|
}
|
|
|
|
#[tokio::test(flavor = "multi_thread")]
|
|
#[serial]
|
|
async fn test_deep_workspace_nesting() -> Result<()> {
|
|
println!("Testing deep workspace nesting...");
|
|
|
|
// Create a deeply nested workspace structure
|
|
let project = TestProject::new("deep-nested-client")
|
|
.workspace()
|
|
.with_dependency("uuid", "^9.0.1")
|
|
.with_dependency("date-fns", "^2.30.0");
|
|
|
|
let manager = TestProjectManager::create(project)?;
|
|
|
|
// Install dependencies in workspace root
|
|
manager.install_workspace_dependencies()?;
|
|
|
|
// Bundle the deeply nested project)
|
|
let executable_path = BundlerTestHelper::bundle_project_with_compression(
|
|
manager.project_path(),
|
|
manager.temp_dir(),
|
|
Some("deep-nested-test"),
|
|
false,
|
|
)?;
|
|
|
|
// Test the bundled executable
|
|
TestAssertions::assert_executable_works(
|
|
&executable_path,
|
|
&[
|
|
"Hello from workspace project!",
|
|
"Dependencies:",
|
|
"Workspace project test completed!",
|
|
],
|
|
&[],
|
|
&[],
|
|
)?;
|
|
|
|
println!("✅ deep workspace nesting test passed!");
|
|
Ok(())
|
|
}
|
|
|
|
#[tokio::test(flavor = "multi_thread")]
|
|
#[serial]
|
|
async fn test_workspace_collision_handling() -> Result<()> {
|
|
println!("Testing workspace collision handling...");
|
|
|
|
// Create a workspace project where the executable name might collide
|
|
let project = TestProject::new("collision-test")
|
|
.workspace()
|
|
.with_dependency("fs-extra", "^11.1.1");
|
|
|
|
let manager = TestProjectManager::create(project)?;
|
|
|
|
// Create a directory with the same name as the expected executable
|
|
std::fs::create_dir_all(manager.temp_dir().join("collision-test"))?;
|
|
|
|
// Install dependencies
|
|
manager.install_workspace_dependencies()?;
|
|
|
|
// Bundle the project (should handle collision automatically, no compression for speed)
|
|
let executable_path = BundlerTestHelper::bundle_project_with_compression(
|
|
manager.project_path(),
|
|
manager.temp_dir(),
|
|
Some("collision-test"),
|
|
false,
|
|
)?;
|
|
|
|
// The executable should exist with collision avoidance
|
|
assert!(
|
|
executable_path.exists(),
|
|
"Executable should exist with collision avoidance: {}",
|
|
executable_path.display()
|
|
);
|
|
|
|
// Test the bundled executable
|
|
TestAssertions::assert_executable_works(
|
|
&executable_path,
|
|
&[
|
|
"Hello from workspace project!",
|
|
"Workspace project test completed!",
|
|
],
|
|
&[],
|
|
&[],
|
|
)?;
|
|
|
|
println!("✅ workspace collision handling test passed!");
|
|
Ok(())
|
|
}
|
|
/// Cleanup function to be called after all workspace tests
|
|
#[tokio::test(flavor = "multi_thread")]
|
|
#[serial]
|
|
async fn test_zzz_cleanup_workspace_cache() -> Result<()> {
|
|
println!("Cleaning up application cache after workspace tests...");
|
|
|
|
TestCacheManager::clear_application_cache()?;
|
|
|
|
println!("✅ Workspace cache cleanup completed!");
|
|
Ok(())
|
|
}
|