use std::collections::BTreeMap;
use std::path::PathBuf;
use cli::add_action::{AddActionRequest, create_add_action_plan};
use cli::build_action::{BuildActionPlanRequest, create_build_action_plan};
use cli::commands::load_command_invocation;
use cli::configuration::{
Builder, CompilerOptions, Configuration, GenerateOptions, GenerateSpec, ProjectConfiguration,
SwcBuilderOptions, parse_configuration,
};
use cli::generate_action::{GenerateActionPlanOptions, build_generate_action_plan};
use cli::info_action::{
PackageJsonDependency, PackageManagerInformation, SystemInformation, create_info_action_plan,
};
use cli::new_action::build_new_action_plan;
use cli::package_managers::{PackageManager, PackageManagerFactory};
use cli::schematics::{CollectionFactory, CollectionInstance, NestCollection, SchematicOption};
use cli::start_action::{DebugFlag, StartActionPlanRequest, create_start_action_plan};
#[test]
fn representative_new_and_generate_outputs_match_upstream_shape() {
let new_invocation = load_command_invocation([
"new",
"Cats API",
"--package-manager",
"pnpm",
"--strict",
"--skip-git",
])
.expect("new command");
let new_plan =
build_new_action_plan(&new_invocation.inputs, &new_invocation.options, "workspace")
.expect("new plan");
assert_eq!(new_plan.collection, "@nestrs/schematics");
assert_eq!(new_plan.schematic, "application");
assert_eq!(new_plan.project_directory, PathBuf::from("cats-api"));
assert_eq!(
new_plan.schematic_command,
"@nestrs/schematics:application --name=cats-api --no-dry-run --skip-git --strict --package-manager=\"pnpm\" --collection=\"@nestrs/schematics\" --language=\"rs\""
);
assert_eq!(
new_plan
.install_command
.as_ref()
.map(|command| command.raw_full_command()),
Some("pnpm install --strict-peer-dependencies=false --reporter=silent".to_string())
);
assert!(new_plan.initialize_git_command.is_none());
let configuration = Configuration {
generate_options: GenerateOptions {
spec: Some(GenerateSpec::BySchematic(BTreeMap::from([(
"service".to_string(),
false,
)]))),
flat: Some(true),
spec_file_suffix: Some("test".to_string()),
base_dir: Some("features".to_string()),
},
..Configuration::default()
};
let generate_invocation =
load_command_invocation(["generate", "service", "Cats", "domain/cats"])
.expect("generate command");
let mut generate_inputs = generate_invocation.inputs;
generate_inputs.extend(generate_invocation.options);
let generate_plan = build_generate_action_plan(
&generate_inputs,
&configuration,
GenerateActionPlanOptions::default(),
)
.expect("generate plan");
assert_eq!(generate_plan.source_root, PathBuf::from("src/features"));
assert_eq!(generate_plan.spec, false);
assert_eq!(generate_plan.flat, true);
assert_eq!(
generate_plan.schematic_command,
"@nestrs/schematics:service --name=cats --path=domain/cats --no-dry-run --no-skip-import --language=\"rs\" --source-root=\"src\\features\" --no-spec --flat --spec-file-suffix=\"test\""
);
}
#[test]
fn representative_build_and_start_plans_match_upstream_shape() {
let mut projects = BTreeMap::new();
projects.insert(
"api".to_string(),
ProjectConfiguration {
source_root: Some("apps/api/src".to_string()),
entry_file: Some("server".to_string()),
compiler_options: Some(CompilerOptions {
builder: Builder::Swc(SwcBuilderOptions {
out_dir: Some("build/api".to_string()),
..SwcBuilderOptions::default()
}),
manual_restart: true,
..CompilerOptions::default()
}),
..ProjectConfiguration::default()
},
);
let build_invocation =
load_command_invocation(["build", "api", "--watch", "--builder", "cargo"])
.expect("build command");
let build_plan = create_build_action_plan(BuildActionPlanRequest {
cwd: PathBuf::from("workspace"),
configuration: Configuration {
projects: projects.clone(),
..Configuration::default()
},
command_inputs: build_invocation.inputs,
command_options: build_invocation.options,
ts_build_info_file: Some(PathBuf::from("build/.tsbuildinfo")),
})
.expect("build plan");
assert_eq!(build_plan.app_names, vec![Some("api".to_string())]);
assert!(build_plan.watch_mode);
assert_eq!(
build_plan.project_plans[0].build_plan.inputs.output_dir,
PathBuf::from("build/api")
);
let start_invocation = load_command_invocation([
"start",
"api",
"--watch",
"--debug",
"127.0.0.1:9229",
"--env-file",
".env",
"--no-shell",
"--",
"--trace-warnings",
])
.expect("start command");
let start_plan = create_start_action_plan(StartActionPlanRequest {
cwd: PathBuf::from("workspace"),
configuration: Configuration {
projects,
..Configuration::default()
},
command_inputs: start_invocation.inputs,
command_options: start_invocation.options,
extra_flags: start_invocation.extra_flags,
ts_build_info_file: None,
})
.expect("start plan");
assert_eq!(start_plan.app_name, Some("api".to_string()));
assert_eq!(
start_plan.process_plan.debug_flag,
Some(DebugFlag::InspectAddress("127.0.0.1:9229".to_string()))
);
assert!(!start_plan.process_plan.shell);
assert_eq!(
start_plan.process_plan.manifest_path,
Some(PathBuf::from("apps").join("api").join("Cargo.toml"))
);
assert_eq!(
start_plan.process_plan.source_root_command.command,
"run --manifest-path apps\\api\\Cargo.toml -- --trace-warnings"
);
}
#[test]
fn representative_add_and_info_outputs_match_upstream_shape() {
let configuration = Configuration {
projects: BTreeMap::from([(
"api".to_string(),
ProjectConfiguration {
source_root: Some("apps/api/src".to_string()),
..ProjectConfiguration::default()
},
)]),
..Configuration::default()
};
let add_plan = create_add_action_plan(AddActionRequest {
library: "@nestrs/swagger@next".to_string(),
skip_install: false,
dry_run: false,
project: Some("api".to_string()),
source_root: None,
extra_flags: vec!["--document-builder=true".to_string()],
package_manager: PackageManager::Npm,
configuration,
});
assert_eq!(add_plan.package_name, "@nestrs/swagger");
assert_eq!(add_plan.collection_name, "@nestrs/swagger");
assert_eq!(add_plan.tag_name, "next");
assert_eq!(
add_plan
.install_command
.as_ref()
.map(|command| command.raw_full_command()),
None
);
assert_eq!(
add_plan.schematic_command,
"@nestrs/swagger:nest-add --source-root=\"apps/api/src\" --document-builder=true"
);
let info_plan = create_info_action_plan(
SystemInformation {
os_version: "Windows 10.0".to_string(),
node_version: "v20.11.0".to_string(),
},
PackageManagerInformation {
name: "NPM".to_string(),
version: Some("10.0.0".to_string()),
},
"11.0.21",
&[
PackageJsonDependency {
package_name: "@nestrs/core".to_string(),
declared_version: "^11.0.0".to_string(),
resolved_version: Some("11.0.1".to_string()),
},
PackageJsonDependency {
package_name: "@nestrs/common".to_string(),
declared_version: "~10.0.0".to_string(),
resolved_version: None,
},
],
);
assert_eq!(info_plan.cli_version, "11.0.21");
assert_eq!(
info_plan
.nest_dependencies
.iter()
.map(|dependency| dependency.package_name.as_str())
.collect::<Vec<_>>(),
vec!["@nestrs/common", "@nestrs/core"]
);
assert!(info_plan.warnings.contains_key("10"));
assert!(info_plan.warnings.contains_key("11"));
}
#[test]
fn representative_configuration_package_manager_and_schematic_outputs_match_upstream_shape() {
let configuration = parse_configuration(
r#"{
"language": "ts",
"sourceRoot": "apps/api/src",
"compilerOptions": {
"builder": {
"type": "swc",
"options": { "outDir": "build" }
}
}
}"#,
)
.expect("configuration");
assert_eq!(configuration.language, "ts");
assert_eq!(configuration.source_root, "apps/api/src");
assert_eq!(
configuration.compiler_options.builder,
Builder::Swc(SwcBuilderOptions {
out_dir: Some("build".to_string()),
..SwcBuilderOptions::default()
})
);
let pnpm = PackageManagerFactory::create_manager(PackageManager::Pnpm);
assert_eq!(
pnpm.add_production_command(&["@nestrs/swagger"], "latest")
.raw_full_command(),
"pnpm install --strict-peer-dependencies=false --save @nestrs/swagger@latest"
);
assert!(matches!(
CollectionFactory::create("@nestrs/schematics"),
CollectionInstance::Nest(_)
));
assert_eq!(
NestCollection::new().execute_command(
"co",
&[
SchematicOption::new("name", "CatsController"),
SchematicOption::new("sourceRoot", "apps/api/src"),
SchematicOption::new("spec", false),
],
),
Ok("@nestrs/schematics:controller --name=cats-controller --source-root=\"apps/api/src\" --no-spec".to_string())
);
}