0
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-10-30 09:08:00 -04:00
denoland-deno/cli/tests/integration/test_tests.rs
Bartek Iwańczuk 5874fc3d0a
feat: add support for globs in the config file and CLI arguments for files (#19102)
Follow up to https://github.com/denoland/deno/pull/19084.

This commit adds support for globs in the configuration file as well 
as CLI arguments for files. 

With this change users can now use glob syntax for "include" and 
"exclude" fields, like so:

```json
{
  "lint": {
    "include": [
      "directory/test*.ts",
      "other_dir/"
    ],
    "exclude": [
      "other_dir/foo*.ts",
      "nested/nested2/*"
    ]
  },
  "test": {
    "include": [
      "data/test*.ts",
      "nested/",
      "tests/test[1-9].ts"
    ],
    "exclude": [
      "nested/foo?.ts",
      "nested/nested2/*"
    ]
  }
}
```

Or in CLI args like so:
```
// notice quotes here; these values will be passed to Deno verbatim
// and deno will perform glob expansion

$ deno fmt --ignore="data/*.ts"
$ deno lint "data/**/*.ts"
```

Closes https://github.com/denoland/deno/issues/17971
Closes https://github.com/denoland/deno/issues/6365
2023-05-23 03:39:59 +02:00

568 lines
14 KiB
Rust

// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
use deno_core::url::Url;
use test_util as util;
use util::assert_contains;
use util::env_vars_for_npm_tests;
use util::wildcard_match;
use util::TestContext;
use util::TestContextBuilder;
#[test]
fn no_color() {
let (out, _) = util::run_and_collect_output(
false,
"test test/no_color.ts",
None,
Some(vec![("NO_COLOR".to_owned(), "true".to_owned())]),
false,
);
// ANSI escape codes should be stripped.
assert!(out.contains("success ... ok"));
assert!(out.contains("fail ... FAILED"));
assert!(out.contains("ignored ... ignored"));
assert!(out.contains("FAILED | 1 passed | 1 failed | 1 ignored"));
}
itest!(overloads {
args: "test test/overloads.ts",
exit_code: 0,
output: "test/overloads.out",
});
itest!(meta {
args: "test test/meta.ts",
exit_code: 0,
output: "test/meta.out",
});
itest!(pass {
args: "test test/pass.ts",
exit_code: 0,
output: "test/pass.out",
});
itest!(ignore {
args: "test test/ignore.ts",
exit_code: 0,
output: "test/ignore.out",
});
itest!(ignore_permissions {
args: "test --unstable test/ignore_permissions.ts",
exit_code: 0,
output: "test/ignore_permissions.out",
});
itest!(fail {
args: "test test/fail.ts",
exit_code: 1,
output: "test/fail.out",
});
itest!(collect {
args: "test --ignore=test/collect/ignore test/collect",
exit_code: 0,
output: "test/collect.out",
});
itest!(test_with_config {
args: "test --config test/collect/deno.jsonc test/collect",
exit_code: 0,
output: "test/collect.out",
});
itest!(test_with_config2 {
args: "test --config test/collect/deno2.jsonc test/collect",
exit_code: 0,
output: "test/collect2.out",
});
itest!(test_with_deprecated_config {
args: "test --config test/collect/deno.deprecated.jsonc test/collect",
exit_code: 0,
output: "test/collect.deprecated.out",
});
itest!(test_with_malformed_config {
args: "test --config test/collect/deno.malformed.jsonc",
exit_code: 1,
output: "test/collect_with_malformed_config.out",
});
itest!(parallel_flag {
args: "test test/short-pass.ts --parallel",
exit_code: 0,
output: "test/short-pass.out",
});
itest!(parallel_flag_with_env_variable {
args: "test test/short-pass.ts --parallel",
envs: vec![("DENO_JOBS".to_owned(), "2".to_owned())],
exit_code: 0,
output: "test/short-pass.out",
});
itest!(jobs_flag {
args: "test test/short-pass.ts --jobs",
exit_code: 0,
output: "test/short-pass-jobs-flag-warning.out",
});
itest!(jobs_flag_with_numeric_value {
args: "test test/short-pass.ts --jobs=2",
exit_code: 0,
output: "test/short-pass-jobs-flag-warning.out",
});
itest!(load_unload {
args: "test test/load_unload.ts",
exit_code: 0,
output: "test/load_unload.out",
});
itest!(interval {
args: "test test/interval.ts",
exit_code: 0,
output: "test/interval.out",
});
itest!(doc {
args: "test --doc --allow-all test/doc.ts",
exit_code: 1,
output: "test/doc.out",
});
itest!(doc_only {
args: "test --doc --allow-all test/doc_only",
exit_code: 0,
output: "test/doc_only.out",
});
itest!(markdown {
args: "test --doc --allow-all test/markdown.md",
exit_code: 1,
output: "test/markdown.out",
});
itest!(markdown_windows {
args: "test --doc --allow-all test/markdown_windows.md",
exit_code: 1,
output: "test/markdown_windows.out",
});
itest!(markdown_full_block_names {
args: "test --doc --allow-all test/markdown_full_block_names.md",
exit_code: 1,
output: "test/markdown_full_block_names.out",
});
itest!(markdown_ignore_html_comment {
args: "test --doc --allow-all test/markdown_with_comment.md",
exit_code: 1,
output: "test/markdown_with_comment.out",
});
itest!(text {
args: "test --doc --allow-all test/text.md",
exit_code: 0,
output: "test/text.out",
});
itest!(quiet {
args: "test --quiet test/quiet.ts",
exit_code: 0,
output: "test/quiet.out",
});
itest!(fail_fast {
args: "test --fail-fast test/fail_fast.ts",
exit_code: 1,
output: "test/fail_fast.out",
});
itest!(only {
args: "test test/only.ts",
exit_code: 1,
output: "test/only.out",
});
itest!(no_check {
args: "test --no-check test/no_check.ts",
exit_code: 1,
output: "test/no_check.out",
});
itest!(no_run {
args: "test --unstable --no-run test/no_run.ts",
output: "test/no_run.out",
exit_code: 1,
});
itest!(allow_all {
args: "test --unstable --allow-all test/allow_all.ts",
exit_code: 0,
output: "test/allow_all.out",
});
itest!(allow_none {
args: "test --unstable test/allow_none.ts",
exit_code: 1,
output: "test/allow_none.out",
});
itest!(ops_sanitizer_unstable {
args: "test --unstable --trace-ops test/ops_sanitizer_unstable.ts",
exit_code: 1,
output: "test/ops_sanitizer_unstable.out",
});
itest!(ops_sanitizer_timeout_failure {
args: "test test/ops_sanitizer_timeout_failure.ts",
output: "test/ops_sanitizer_timeout_failure.out",
});
itest!(ops_sanitizer_multiple_timeout_tests {
args: "test --trace-ops test/ops_sanitizer_multiple_timeout_tests.ts",
exit_code: 1,
output: "test/ops_sanitizer_multiple_timeout_tests.out",
});
itest!(ops_sanitizer_multiple_timeout_tests_no_trace {
args: "test test/ops_sanitizer_multiple_timeout_tests.ts",
exit_code: 1,
output: "test/ops_sanitizer_multiple_timeout_tests_no_trace.out",
});
itest!(trace_ops_catch_error {
args: "test -A --trace-ops test/trace_ops_caught_error/main.ts",
exit_code: 0,
output: "test/trace_ops_caught_error/main.out",
});
// TODO(@littledivy): re-enable this test, recent optimizations made output non deterministic.
// https://github.com/denoland/deno/issues/14268
//
// itest!(ops_sanitizer_missing_details {
// args: "test --allow-write --allow-read test/ops_sanitizer_missing_details.ts",
// exit_code: 1,
// output: "test/ops_sanitizer_missing_details.out",
// });
itest!(ops_sanitizer_nexttick {
args: "test --no-check test/ops_sanitizer_nexttick.ts",
output: "test/ops_sanitizer_nexttick.out",
});
itest!(resource_sanitizer {
args: "test --allow-read test/resource_sanitizer.ts",
exit_code: 1,
output: "test/resource_sanitizer.out",
});
itest!(exit_sanitizer {
args: "test test/exit_sanitizer.ts",
output: "test/exit_sanitizer.out",
exit_code: 1,
});
itest!(clear_timeout {
args: "test test/clear_timeout.ts",
exit_code: 0,
output: "test/clear_timeout.out",
});
itest!(finally_timeout {
args: "test test/finally_timeout.ts",
exit_code: 1,
output: "test/finally_timeout.out",
});
itest!(unresolved_promise {
args: "test test/unresolved_promise.ts",
exit_code: 1,
output: "test/unresolved_promise.out",
});
itest!(unhandled_rejection {
args: "test test/unhandled_rejection.ts",
exit_code: 1,
output: "test/unhandled_rejection.out",
});
itest!(filter {
args: "test --filter=foo test/filter",
exit_code: 0,
output: "test/filter.out",
});
itest!(shuffle {
args: "test --shuffle test/shuffle",
exit_code: 0,
output_str: Some("[WILDCARD]"),
});
itest!(shuffle_with_seed {
args: "test --shuffle=42 test/shuffle",
exit_code: 0,
output: "test/shuffle.out",
});
itest!(aggregate_error {
args: "test --quiet test/aggregate_error.ts",
exit_code: 1,
output: "test/aggregate_error.out",
});
itest!(steps_passing_steps {
args: "test test/steps/passing_steps.ts",
exit_code: 0,
output: "test/steps/passing_steps.out",
});
itest!(steps_failing_steps {
args: "test test/steps/failing_steps.ts",
exit_code: 1,
output: "test/steps/failing_steps.out",
});
itest!(steps_ignored_steps {
args: "test test/steps/ignored_steps.ts",
exit_code: 0,
output: "test/steps/ignored_steps.out",
});
itest!(steps_invalid_usage {
args: "test test/steps/invalid_usage.ts",
exit_code: 1,
output: "test/steps/invalid_usage.out",
});
itest!(steps_output_within {
args: "test test/steps/output_within.ts",
exit_code: 0,
output: "test/steps/output_within.out",
});
itest!(no_prompt_by_default {
args: "test --quiet test/no_prompt_by_default.ts",
exit_code: 1,
output: "test/no_prompt_by_default.out",
});
itest!(no_prompt_with_denied_perms {
args: "test --quiet --allow-read test/no_prompt_with_denied_perms.ts",
exit_code: 1,
output: "test/no_prompt_with_denied_perms.out",
});
itest!(test_with_custom_jsx {
args: "test --quiet --allow-read test/hello_world.ts --config=test/deno_custom_jsx.json",
exit_code: 0,
output: "test/hello_world.out",
});
itest!(before_unload_prevent_default {
args: "test --quiet test/before_unload_prevent_default.ts",
output: "test/before_unload_prevent_default.out",
});
#[test]
fn captured_output() {
let context = TestContext::default();
let output = context
.new_command()
.args("test --allow-run --allow-read --unstable test/captured_output.ts")
.env("NO_COLOR", "1")
.run();
let output_start = "------- output -------";
let output_end = "----- output end -----";
output.assert_exit_code(0);
let output_text = output.combined_output();
let start = output_text.find(output_start).unwrap() + output_start.len();
let end = output_text.find(output_end).unwrap();
// replace zero width space that may appear in test output due
// to test runner output flusher
let output_text = output_text[start..end]
.replace('\u{200B}', "")
.trim()
.to_string();
let mut lines = output_text.lines().collect::<Vec<_>>();
// the output is racy on either stdout or stderr being flushed
// from the runtime into the rust code, so sort it... the main
// thing here to ensure is that we're capturing the output in
// this block on stdout
lines.sort_unstable();
assert_eq!(lines.join(" "), "0 1 2 3 4 5 6 7 8 9");
}
#[test]
fn recursive_permissions_pledge() {
let context = TestContext::default();
let output = context
.new_command()
.args("test test/recursive_permissions_pledge.js")
.run();
output.assert_exit_code(1);
assert_contains!(
output.combined_output(),
"pledge test permissions called before restoring previous pledge"
);
}
#[test]
fn file_protocol() {
let file_url =
Url::from_file_path(util::testdata_path().join("test/file_protocol.ts"))
.unwrap()
.to_string();
TestContext::default()
.new_command()
.args_vec(["test", file_url.as_str()])
.run()
.assert_matches_file("test/file_protocol.out");
}
itest!(uncaught_errors {
args: "test --quiet test/uncaught_errors_1.ts test/uncaught_errors_2.ts test/uncaught_errors_3.ts",
output: "test/uncaught_errors.out",
exit_code: 1,
});
itest!(report_error {
args: "test --quiet test/report_error.ts",
output: "test/report_error.out",
exit_code: 1,
});
itest!(check_local_by_default {
args: "test --quiet test/check_local_by_default.ts",
output: "test/check_local_by_default.out",
http_server: true,
});
itest!(check_local_by_default2 {
args: "test --quiet test/check_local_by_default2.ts",
output: "test/check_local_by_default2.out",
http_server: true,
exit_code: 1,
});
itest!(non_error_thrown {
args: "test --quiet test/non_error_thrown.ts",
output: "test/non_error_thrown.out",
exit_code: 1,
});
itest!(parallel_output {
args: "test --parallel --reload test/parallel_output.ts",
output: "test/parallel_output.out",
exit_code: 1,
});
#[test]
// todo(#18480): re-enable
#[ignore]
fn sigint_with_hanging_test() {
util::with_pty(
&[
"test",
"--quiet",
"--no-check",
"test/sigint_with_hanging_test.ts",
],
|mut console| {
std::thread::sleep(std::time::Duration::from_secs(1));
console.write_line("\x03");
let text = console.read_until("hanging_test.ts:10:15");
wildcard_match(
include_str!("../testdata/test/sigint_with_hanging_test.out"),
&text,
);
},
);
}
itest!(package_json_basic {
args: "test",
output: "package_json/basic/lib.test.out",
envs: env_vars_for_npm_tests(),
http_server: true,
cwd: Some("package_json/basic"),
copy_temp_dir: Some("package_json/basic"),
exit_code: 0,
});
itest!(test_lock {
args: "test",
http_server: true,
cwd: Some("lockfile/basic"),
exit_code: 10,
output: "lockfile/basic/fail.out",
});
itest!(test_no_lock {
args: "test --no-lock",
http_server: true,
cwd: Some("lockfile/basic"),
output: "lockfile/basic/test.nolock.out",
});
#[test]
fn test_with_glob_config() {
let context = TestContextBuilder::new().cwd("test").build();
let cmd_output = context
.new_command()
.args("test --config deno.glob.json")
.run();
cmd_output.assert_exit_code(0);
let output = cmd_output.combined_output();
assert_contains!(output, "glob/nested/fizz/fizz.ts");
assert_contains!(output, "glob/pages/[id].ts");
assert_contains!(output, "glob/nested/fizz/bar.ts");
assert_contains!(output, "glob/nested/foo/foo.ts");
assert_contains!(output, "glob/data/test1.js");
assert_contains!(output, "glob/nested/foo/bar.ts");
assert_contains!(output, "glob/nested/foo/fizz.ts");
assert_contains!(output, "glob/nested/fizz/foo.ts");
assert_contains!(output, "glob/data/test1.ts");
}
#[test]
fn test_with_glob_config_and_flags() {
let context = TestContextBuilder::new().cwd("test").build();
let cmd_output = context
.new_command()
.args("test --config deno.glob.json --ignore=glob/nested/**/bar.ts")
.run();
cmd_output.assert_exit_code(0);
let output = cmd_output.combined_output();
assert_contains!(output, "glob/nested/fizz/fizz.ts");
assert_contains!(output, "glob/pages/[id].ts");
assert_contains!(output, "glob/nested/fizz/bazz.ts");
assert_contains!(output, "glob/nested/foo/foo.ts");
assert_contains!(output, "glob/data/test1.js");
assert_contains!(output, "glob/nested/foo/bazz.ts");
assert_contains!(output, "glob/nested/foo/fizz.ts");
assert_contains!(output, "glob/nested/fizz/foo.ts");
assert_contains!(output, "glob/data/test1.ts");
let cmd_output = context
.new_command()
.args("test --config deno.glob.json glob/data/test1.?s")
.run();
cmd_output.assert_exit_code(0);
let output = cmd_output.combined_output();
assert_contains!(output, "glob/data/test1.js");
assert_contains!(output, "glob/data/test1.ts");
}