diff options
Diffstat (limited to 'cli/tests')
-rw-r--r-- | cli/tests/integration/repl_tests.rs | 808 | ||||
-rw-r--r-- | cli/tests/integration/run_tests.rs | 580 | ||||
-rw-r--r-- | cli/tests/integration/task_tests.rs | 9 | ||||
-rw-r--r-- | cli/tests/integration/test_tests.rs | 5 | ||||
-rw-r--r-- | cli/tests/testdata/run/stdio_streams_are_locked_in_permission_prompt/text.txt | 1 |
5 files changed, 688 insertions, 715 deletions
diff --git a/cli/tests/integration/repl_tests.rs b/cli/tests/integration/repl_tests.rs index f7bd627c3..82cae5024 100644 --- a/cli/tests/integration/repl_tests.rs +++ b/cli/tests/integration/repl_tests.rs @@ -6,35 +6,31 @@ use test_util::assert_ends_with; use test_util::assert_not_contains; use util::TempDir; -#[ignore] #[test] fn pty_multiline() { util::with_pty(&["repl"], |mut console| { console.write_line("(\n1 + 2\n)"); + console.expect("3"); console.write_line("{\nfoo: \"foo\"\n}"); + console.expect("{ foo: \"foo\" }"); console.write_line("`\nfoo\n`"); + console.expect("\"\\nfoo\\n\""); console.write_line("`\n\\`\n`"); + console.expect(r#""\n`\n""#); console.write_line("'{'"); + console.expect(r#""{""#); console.write_line("'('"); + console.expect(r#""(""#); console.write_line("'['"); + console.expect(r#""[""#); console.write_line("/{/"); + console.expect("/{/"); console.write_line("/\\(/"); + console.expect("/\\(/"); console.write_line("/\\[/"); + console.expect("/\\[/"); console.write_line("console.log(\"{test1} abc {test2} def {{test3}}\".match(/{([^{].+?)}/));"); - console.write_line("close();"); - - let output = console.read_all_output(); - assert_contains!(output, '3'); - assert_contains!(output, "{ foo: \"foo\" }"); - assert_contains!(output, "\"\\nfoo\\n\""); - assert_contains!(output, "\"\\n`\\n\""); - assert_contains!(output, "\"{\""); - assert_contains!(output, "\"(\""); - assert_contains!(output, "\"[\""); - assert_contains!(output, "/{/"); - assert_contains!(output, "/\\(/"); - assert_contains!(output, "/\\[/"); - assert_contains!(output, "[ \"{test1}\", \"test1\" ]"); + console.expect("[ \"{test1}\", \"test1\" ]"); }); } @@ -42,10 +38,7 @@ fn pty_multiline() { fn pty_null() { util::with_pty(&["repl"], |mut console| { console.write_line("null"); - console.write_line("close();"); - - let output = console.read_all_output(); - assert_contains!(output, "null"); + console.expect("null"); }); } @@ -54,10 +47,7 @@ fn pty_unpaired_braces() { for right_brace in &[")", "]", "}"] { util::with_pty(&["repl"], |mut console| { console.write_line(right_brace); - console.write_line("close();"); - - let output = console.read_all_output(); - assert_contains!(output, "Expression expected"); + console.expect("parse error: Expression expected"); }); } } @@ -66,10 +56,7 @@ fn pty_unpaired_braces() { fn pty_bad_input() { util::with_pty(&["repl"], |mut console| { console.write_line("'\\u{1f3b5}'[0]"); - console.write_line("close();"); - - let output = console.read_all_output(); - assert_contains!(output, "Unterminated string literal"); + console.expect("Unterminated string literal"); }); } @@ -77,28 +64,21 @@ fn pty_bad_input() { fn pty_syntax_error_input() { util::with_pty(&["repl"], |mut console| { console.write_line("('\\u')"); + console.expect("Bad character escape sequence, expected 4 hex characters"); + console.write_line("'"); - console.write_line("[{'a'}];"); - console.write_line("close();"); + console.expect("Unterminated string constant"); - let output = console.read_all_output(); - assert_contains!( - output, - "Bad character escape sequence, expected 4 hex characters" - ); - assert_contains!(output, "Unterminated string constant"); - assert_contains!(output, "Expected a semicolon"); + console.write_line("[{'a'}];"); + console.expect("Expected a semicolon"); }); } #[test] fn pty_complete_symbol() { util::with_pty(&["repl"], |mut console| { - console.write_line("Symbol.it\t"); - console.write_line("close();"); - - let output = console.read_all_output(); - assert_contains!(output, "Symbol(Symbol.iterator)"); + console.write_line_raw("Symbol.it\t"); + console.expect("Symbol(Symbol.iterator)"); }); } @@ -106,14 +86,13 @@ fn pty_complete_symbol() { fn pty_complete_declarations() { util::with_pty(&["repl"], |mut console| { console.write_line("class MyClass {}"); - console.write_line("My\t"); - console.write_line("let myVar;"); - console.write_line("myV\t"); - console.write_line("close();"); - - let output = console.read_all_output(); - assert_contains!(output, "> MyClass"); - assert_contains!(output, "> myVar"); + console.expect("undefined"); + console.write_line_raw("My\t"); + console.expect("[Class: MyClass]"); + console.write_line("let myVar = 2 + 3;"); + console.expect("undefined"); + console.write_line_raw("myV\t"); + console.expect("5"); }); } @@ -121,37 +100,31 @@ fn pty_complete_declarations() { fn pty_complete_primitives() { util::with_pty(&["repl"], |mut console| { console.write_line("let func = function test(){}"); - console.write_line("func.appl\t"); + console.expect("undefined"); + console.write_line_raw("func.appl\t"); + console.expect("func.apply"); console.write_line("let str = ''"); - console.write_line("str.leng\t"); - console.write_line("false.valueO\t"); - console.write_line("5n.valueO\t"); + console.expect("undefined"); + console.write_line_raw("str.leng\t"); + console.expect("str.length"); + console.write_line_raw("false.valueO\t"); + console.expect("false.valueOf"); + console.write_line_raw("5n.valueO\t"); + console.expect("5n.valueOf"); console.write_line("let num = 5"); - console.write_line("num.toStrin\t"); - console.write_line("close();"); - - let output = console.read_all_output(); - assert_contains!(output, "> func.apply"); - assert_contains!(output, "> str.length"); - assert_contains!(output, "> 5n.valueOf"); - assert_contains!(output, "> false.valueOf"); - assert_contains!(output, "> num.toString"); + console.expect("undefined"); + console.write_line_raw("num.toStrin\t"); + console.expect("num.toString"); }); } #[test] fn pty_complete_expression() { util::with_pty(&["repl"], |mut console| { - console.write_text("Deno.\t\t"); - console.write_text("y"); - console.write_line(""); - console.write_line("close();"); - let output = console.read_all_output(); - assert_contains!(output, "Display all"); - assert_contains!(output, "args"); - assert_contains!(output, "exit"); - assert_contains!(output, "symlink"); - assert_contains!(output, "permissions"); + console.write_raw("Deno.\t\t"); + console.expect("Display all"); + console.write_raw("y"); + console.expect_all(&["symlink", "args", "permissions", "exit"]); }); } @@ -159,66 +132,51 @@ fn pty_complete_expression() { fn pty_complete_imports() { util::with_pty(&["repl", "-A"], |mut console| { // single quotes - console.write_line("import './run/001_hel\t'"); + console.write_line_raw("import './run/001_hel\t'"); + console.expect("Hello World"); // double quotes - console.write_line("import { output } from \"./run/045_out\t\""); - console.write_line("output('testing output');"); - console.write_line("close();"); - - let output = console.read_all_output(); - assert_contains!(output, "Hello World"); - assert_contains!( - output, - // on windows, could any (it's flaky) - "\ntesting output", - "testing output\u{1b}", - "\r\n\u{1b}[?25htesting output", - ); + console.write_line_raw("import { output } from \"./run/045_out\t\""); + console.expect("\"./run/045_output.ts\""); + console.write_line_raw("output('testing output');"); + console.expect("testing output"); }); // ensure when the directory changes that the suggestions come from the cwd util::with_pty(&["repl", "-A"], |mut console| { console.write_line("Deno.chdir('./subdir');"); - console.write_line("import '../run/001_hel\t'"); - console.write_line("close();"); - - let output = console.read_all_output(); - assert_contains!(output, "Hello World"); + console.expect("undefined"); + console.write_line_raw("import '../run/001_hel\t'"); + console.expect("Hello World"); }); } #[test] fn pty_complete_imports_no_panic_empty_specifier() { // does not panic when tabbing when empty - util::with_pty(&["repl"], |mut console| { - console.write_line("import '\t';"); - console.write_line("close();"); + util::with_pty(&["repl", "-A"], |mut console| { + if cfg!(windows) { + console.write_line_raw("import '\t'"); + console.expect_any(&["not prefixed with", "https://deno.land"]); + } else { + console.write_raw("import '\t"); + console.expect("import 'https://deno.land"); + } }); } #[test] fn pty_ignore_symbols() { util::with_pty(&["repl"], |mut console| { - console.write_line("Array.Symbol\t"); - console.write_line("close();"); - - let output = console.read_all_output(); - assert_contains!(output, "undefined"); - assert_not_contains!( - output, - "Uncaught TypeError: Array.Symbol is not a function" - ); + console.write_line_raw("Array.Symbol\t"); + console.expect("undefined"); }); } #[test] fn pty_assign_global_this() { util::with_pty(&["repl"], |mut console| { - console.write_line("globalThis = 42;"); - console.write_line("close();"); - - let output = console.read_all_output(); - assert_not_contains!(output, "panicked"); + console.write_line("globalThis = 40 + 2;"); + console.expect("42"); }); } @@ -228,13 +186,12 @@ fn pty_assign_deno_keys_and_deno() { console.write_line( "Object.keys(Deno).forEach((key)=>{try{Deno[key] = undefined} catch {}})", ); + console.expect("undefined"); console.write_line("delete globalThis.Deno"); - console.write_line("console.log('testing ' + 'this out')"); - console.write_line("close();"); - - let output = console.read_all_output(); - assert_not_contains!(output, "panicked"); - assert_contains!(output, "testing this out"); + console.expect("true"); + console.write_line("console.log('testing ' + 'this out');"); + console.expect("testing this out"); + console.expect("undefined"); }); } @@ -242,9 +199,14 @@ fn pty_assign_deno_keys_and_deno() { fn pty_internal_repl() { util::with_pty(&["repl"], |mut console| { console.write_line("globalThis"); - console.write_line("__\t\t"); - console.write_line("close();"); - let output = console.read_all_output(); + console.write_line_raw("1 + 256"); + let output = console.read_until("257"); + assert_contains!(output, "clear:"); + assert_not_contains!(output, "__DENO_"); + + console.write_line_raw("__\t\t"); + console.expect("> __"); + let output = console.read_until("> __"); assert_contains!(output, "__defineGetter__"); // should not contain the internal repl variable // in the `globalThis` or completions output @@ -257,190 +219,139 @@ fn pty_emoji() { // windows was having issues displaying this util::with_pty(&["repl"], |mut console| { console.write_line(r#"console.log('\u{1F995}');"#); - console.write_line("close();"); - - let output = console.read_all_output(); - // only one for the output (since input is escaped) - let emoji_count = output.chars().filter(|c| *c == 'π¦').count(); - assert_eq!(emoji_count, 1); + console.expect("π¦"); }); } #[test] fn console_log() { - let (out, err) = util::run_and_collect_output( - true, - "repl", - Some(vec!["console.log('hello')", "'world'"]), - Some(vec![("NO_COLOR".to_owned(), "1".to_owned())]), - false, - ); - assert_ends_with!(out, "hello\nundefined\n\"world\"\n"); - assert!(err.is_empty()); + util::with_pty(&["repl"], |mut console| { + console.write_line("console.log('hello');"); + console.expect("hello"); + console.write_line("'world'"); + console.expect("\"world\""); + }); } #[test] fn object_literal() { - let (out, err) = util::run_and_collect_output( - true, - "repl", - Some(vec!["{}", "{ foo: 'bar' }"]), - Some(vec![("NO_COLOR".to_owned(), "1".to_owned())]), - false, - ); - assert_ends_with!(out, "{}\n{ foo: \"bar\" }\n"); - assert!(err.is_empty()); + util::with_pty(&["repl"], |mut console| { + console.write_line("{}"); + console.expect("{}"); + console.write_line("{ foo: 'bar' }"); + console.expect("{ foo: \"bar\" }"); + }); } #[test] fn block_expression() { - let (out, err) = util::run_and_collect_output( - true, - "repl", - Some(vec!["{};", "{\"\"}"]), - Some(vec![("NO_COLOR".to_owned(), "1".to_owned())]), - false, - ); - assert_ends_with!(out, "undefined\n\"\"\n"); - assert!(err.is_empty()); + util::with_pty(&["repl"], |mut console| { + console.write_line("{};"); + console.expect("undefined"); + console.write_line("{\"\"}"); + console.expect("\"\""); + }); } #[test] fn await_resolve() { - let (out, err) = util::run_and_collect_output( - true, - "repl", - Some(vec!["await Promise.resolve('done')"]), - Some(vec![("NO_COLOR".to_owned(), "1".to_owned())]), - false, - ); - assert_ends_with!(out, "\"done\"\n"); - assert!(err.is_empty()); + util::with_pty(&["repl"], |mut console| { + console.write_line("await Promise.resolve('done')"); + console.expect("\"done\""); + }); } #[test] fn await_timeout() { - let (out, err) = util::run_and_collect_output( - true, - "repl", - Some(vec!["await new Promise((r) => setTimeout(r, 0, 'done'))"]), - Some(vec![("NO_COLOR".to_owned(), "1".to_owned())]), - false, - ); - assert_ends_with!(out, "\"done\"\n"); - assert!(err.is_empty()); + util::with_pty(&["repl"], |mut console| { + console.write_line("await new Promise((r) => setTimeout(r, 0, 'done'))"); + console.expect("\"done\""); + }); } #[test] fn let_redeclaration() { - let (out, err) = util::run_and_collect_output( - true, - "repl", - Some(vec!["let foo = 0;", "foo", "let foo = 1;", "foo"]), - Some(vec![("NO_COLOR".to_owned(), "1".to_owned())]), - false, - ); - assert_ends_with!(out, "undefined\n0\nundefined\n1\n"); - assert!(err.is_empty()); + util::with_pty(&["repl"], |mut console| { + console.write_line("let foo = 0;"); + console.expect("undefined"); + console.write_line("foo"); + console.expect("0"); + console.write_line("let foo = 1;"); + console.expect("undefined"); + console.write_line("foo"); + console.expect("1"); + }); } #[test] fn repl_cwd() { - let (_out, err) = util::run_and_collect_output( - true, - "repl", - Some(vec!["Deno.cwd()"]), - Some(vec![("NO_COLOR".to_owned(), "1".to_owned())]), - false, - ); - assert!(err.is_empty()); + util::with_pty(&["repl", "-A"], |mut console| { + console.write_line("Deno.cwd()"); + console.expect("testdata"); + }); } #[test] fn typescript() { - let (out, err) = util::run_and_collect_output( - true, - "repl", - Some(vec![ - "function add(a: number, b: number) { return a + b }", - "const result: number = add(1, 2) as number;", - "result", - ]), - Some(vec![("NO_COLOR".to_owned(), "1".to_owned())]), - false, - ); - assert_ends_with!(out, "undefined\nundefined\n3\n"); - assert!(err.is_empty()); + util::with_pty(&["repl"], |mut console| { + console.write_line("function add(a: number, b: number) { return a + b }"); + console.expect("undefined"); + console.write_line("const result: number = add(1, 2) as number;"); + console.expect("undefined"); + console.write_line("result"); + console.expect("3"); + }); } #[test] fn typescript_declarations() { - let (out, err) = util::run_and_collect_output( - true, - "repl", - Some(vec![ - "namespace Test { export enum Values { A, B, C } }", - "Test.Values.A", - "Test.Values.C", - "interface MyInterface { prop: string; }", - "type MyTypeAlias = string;", - ]), - Some(vec![("NO_COLOR".to_owned(), "1".to_owned())]), - false, - ); - let expected_end_text = "undefined\n0\n2\nundefined\nundefined\n"; - assert_ends_with!(out, expected_end_text); - assert!(err.is_empty()); + util::with_pty(&["repl"], |mut console| { + console.write_line("namespace Test { export enum Values { A, B, C } }"); + console.expect("undefined"); + console.write_line("Test.Values.A"); + console.expect("0"); + console.write_line("Test.Values.C"); + console.expect("2"); + console.write_line("interface MyInterface { prop: string; }"); + console.expect("undefined"); + console.write_line("type MyTypeAlias = string;"); + console.expect("undefined"); + }); } #[test] fn typescript_decorators() { - let (out, err) = util::run_and_collect_output( - true, - "repl", - Some(vec![ - "function dec(target) { target.prototype.test = () => 2; }", - "@dec class Test {}", - "new Test().test()", - ]), - Some(vec![("NO_COLOR".to_owned(), "1".to_owned())]), - false, - ); - assert_ends_with!(out, "undefined\n[Class: Test]\n2\n"); - assert!(err.is_empty()); + util::with_pty(&["repl"], |mut console| { + console + .write_line("function dec(target) { target.prototype.test = () => 2; }"); + console.expect("undefined"); + console.write_line("@dec class Test {}"); + console.expect("[Class: Test]"); + console.write_line("new Test().test()"); + console.expect("2"); + }); } #[test] fn eof() { - let (out, err) = util::run_and_collect_output( - true, - "repl", - Some(vec!["1 + 2"]), - Some(vec![("NO_COLOR".to_owned(), "1".to_owned())]), - false, - ); - assert_ends_with!(out, "3\n"); - assert!(err.is_empty()); + util::with_pty(&["repl"], |mut console| { + console.write_line("1 + 2"); + console.expect("3"); + }); } #[test] fn strict() { - let (out, err) = util::run_and_collect_output( - true, - "repl", - Some(vec![ - "let a = {};", - "Object.preventExtensions(a);", - "a.c = 1;", - ]), - None, - false, - ); - assert_contains!( - out, - "Uncaught TypeError: Cannot add property c, object is not extensible" - ); - assert!(err.is_empty()); + util::with_pty(&["repl"], |mut console| { + console.write_line("let a = {};"); + console.expect("undefined"); + console.write_line("Object.preventExtensions(a)"); + console.expect("{}"); + console.write_line("a.c = 1;"); + console.expect( + "Uncaught TypeError: Cannot add property c, object is not extensible", + ); + }); } #[test] @@ -459,176 +370,118 @@ fn close_command() { #[test] fn function() { - let (out, err) = util::run_and_collect_output( - true, - "repl", - Some(vec!["Deno.writeFileSync"]), - Some(vec![("NO_COLOR".to_owned(), "1".to_owned())]), - false, - ); - assert_ends_with!(out, "[Function: writeFileSync]\n"); - assert!(err.is_empty()); + util::with_pty(&["repl"], |mut console| { + console.write_line("Deno.writeFileSync"); + console.expect("[Function: writeFileSync]"); + }); } #[test] -#[ignore] fn multiline() { - let (out, err) = util::run_and_collect_output( - true, - "repl", - Some(vec!["(\n1 + 2\n)"]), - Some(vec![("NO_COLOR".to_owned(), "1".to_owned())]), - false, - ); - assert_ends_with!(out, "3\n"); - assert!(err.is_empty()); + util::with_pty(&["repl"], |mut console| { + console.write_line("(\n1 + 2\n)"); + console.expect("3"); + }); } #[test] fn import() { - let (out, _) = util::run_and_collect_output_with_args( - true, - vec![], - Some(vec!["import('./subdir/auto_print_hello.ts')"]), - Some(vec![("NO_COLOR".to_owned(), "1".to_owned())]), - false, - ); - assert_contains!(out, "hello!\n"); + util::with_pty(&["repl", "-A"], |mut console| { + console.write_line("import('./subdir/auto_print_hello.ts')"); + console.expect("hello!"); + }); } #[test] fn import_declarations() { - let (out, _) = util::run_and_collect_output_with_args( - true, - vec!["repl", "--allow-read"], - Some(vec!["import './subdir/auto_print_hello.ts';"]), - Some(vec![("NO_COLOR".to_owned(), "1".to_owned())]), - false, - ); - assert_contains!(out, "hello!\n"); + util::with_pty(&["repl", "-A"], |mut console| { + console.write_line("import './subdir/auto_print_hello.ts'"); + console.expect("hello!"); + }); } #[test] fn exports_stripped() { - let (out, err) = util::run_and_collect_output( - true, - "repl", - Some(vec!["export default 5;", "export class Test {}"]), - Some(vec![("NO_COLOR".to_owned(), "1".to_owned())]), - false, - ); - assert_contains!(out, "5\n"); - assert!(err.is_empty()); + util::with_pty(&["repl"], |mut console| { + console.write_line("const test = 5 + 1; export default test;"); + console.expect("6"); + console.write_line("export class Test {}"); + console.expect("undefined"); + }); } #[test] fn call_eval_unterminated() { - let (out, err) = util::run_and_collect_output( - true, - "repl", - Some(vec!["eval('{')"]), - None, - false, - ); - assert_contains!(out, "Unexpected end of input"); - assert!(err.is_empty()); + util::with_pty(&["repl"], |mut console| { + console.write_line("eval('{')"); + console.expect("Unexpected end of input"); + }); } #[test] fn unpaired_braces() { - for right_brace in &[")", "]", "}"] { - let (out, err) = util::run_and_collect_output( - true, - "repl", - Some(vec![right_brace]), - None, - false, - ); - assert_contains!(out, "Expression expected"); - assert!(err.is_empty()); - } + util::with_pty(&["repl"], |mut console| { + for right_brace in &[")", "]", "}"] { + console.write_line(right_brace); + console.expect("Expression expected"); + } + }); } #[test] fn reference_error() { - let (out, err) = util::run_and_collect_output( - true, - "repl", - Some(vec!["not_a_variable"]), - None, - false, - ); - assert_contains!(out, "not_a_variable is not defined"); - assert!(err.is_empty()); + util::with_pty(&["repl"], |mut console| { + console.write_line("not_a_variable"); + console.expect("not_a_variable is not defined"); + }); } #[test] fn syntax_error() { - let (out, err) = util::run_and_collect_output( - true, - "repl", - Some(vec![ - "syntax error", - "2", // ensure it keeps accepting input after - ]), - Some(vec![("NO_COLOR".to_owned(), "1".to_owned())]), - false, - ); - assert_ends_with!(out, "parse error: Expected ';', '}' or <eof> at 1:8\n2\n"); - assert!(err.is_empty()); + util::with_pty(&["repl"], |mut console| { + console.write_line("syntax error"); + console.expect("parse error: Expected ';', '}' or <eof>"); + // ensure it keeps accepting input after + console.write_line("7 * 6"); + console.expect("42"); + }); } #[test] fn syntax_error_jsx() { // JSX is not supported in the REPL - let (out, err) = util::run_and_collect_output( - true, - "repl", - Some(vec!["const element = <div />;"]), - Some(vec![("NO_COLOR".to_owned(), "1".to_owned())]), - false, - ); - assert_contains!(out, "Expression expected"); - assert!(err.is_empty()); + util::with_pty(&["repl"], |mut console| { + console.write_line("const element = <div />;"); + console.expect("Expression expected"); + }); } #[test] fn type_error() { - let (out, err) = util::run_and_collect_output( - true, - "repl", - Some(vec!["console()"]), - None, - false, - ); - assert_contains!(out, "console is not a function"); - assert!(err.is_empty()); + util::with_pty(&["repl"], |mut console| { + console.write_line("console()"); + console.expect("console is not a function"); + }); } #[test] fn variable() { - let (out, err) = util::run_and_collect_output( - true, - "repl", - Some(vec!["var a = 123;", "a"]), - Some(vec![("NO_COLOR".to_owned(), "1".to_owned())]), - false, - ); - assert_ends_with!(out, "undefined\n123\n"); - assert!(err.is_empty()); + util::with_pty(&["repl"], |mut console| { + console.write_line("var a = 123 + 456;"); + console.expect("undefined"); + console.write_line("a"); + console.expect("579"); + }); } #[test] fn lexical_scoped_variable() { - let (out, err) = util::run_and_collect_output( - true, - "repl", - Some(vec!["let a = 123;", "a"]), - Some(vec![("NO_COLOR".to_owned(), "1".to_owned())]), - false, - ); - assert_ends_with!(out, "undefined\n123\n"); - assert!(err.is_empty()); + util::with_pty(&["repl"], |mut console| { + console.write_line("let a = 123 + 456;"); + console.expect("undefined"); + console.write_line("a"); + console.expect("579"); + }); } #[test] @@ -702,95 +555,70 @@ fn disable_history_file() { #[test] fn save_last_eval() { - let (out, err) = util::run_and_collect_output( - true, - "repl", - Some(vec!["1", "_"]), - Some(vec![("NO_COLOR".to_owned(), "1".to_owned())]), - false, - ); - assert_ends_with!(out, "1\n1\n"); - assert!(err.is_empty()); + util::with_pty(&["repl"], |mut console| { + console.write_line("1 + 2"); + console.expect("3"); + console.write_line("_ + 3"); + console.expect("6"); + }); } #[test] fn save_last_thrown() { - let (out, err) = util::run_and_collect_output( - true, - "repl", - Some(vec!["throw 1", "_error"]), - Some(vec![("NO_COLOR".to_owned(), "1".to_owned())]), - false, - ); - assert_ends_with!(out, "Uncaught 1\n1\n"); - assert!(err.is_empty()); + util::with_pty(&["repl"], |mut console| { + console.write_line("throw 1 + 2"); + console.expect("Uncaught 3"); + console.write_line("_error + 3"); + console.expect("6"); + }); } #[test] fn assign_underscore() { - let (out, err) = util::run_and_collect_output( - true, - "repl", - Some(vec!["_ = 1", "2", "_"]), - Some(vec![("NO_COLOR".to_owned(), "1".to_owned())]), - false, - ); - assert_ends_with!( - out, - "Last evaluation result is no longer saved to _.\n1\n2\n1\n" - ); - assert!(err.is_empty()); + util::with_pty(&["repl"], |mut console| { + console.write_line("_ = 1"); + console.expect("Last evaluation result is no longer saved to _."); + console.write_line("2 + 3"); + console.expect("5"); + console.write_line("_"); + console.expect("1"); + }); } #[test] fn assign_underscore_error() { - let (out, err) = util::run_and_collect_output( - true, - "repl", - Some(vec!["_error = 1", "throw 2", "_error"]), - Some(vec![("NO_COLOR".to_owned(), "1".to_owned())]), - false, - ); - println!("{out}"); - assert_ends_with!( - out, - "Last thrown error is no longer saved to _error.\n1\nUncaught 2\n1\n" - ); - assert!(err.is_empty()); + util::with_pty(&["repl"], |mut console| { + console.write_line("_error = 1"); + console.expect("Last thrown error is no longer saved to _error."); + console.write_line("throw 2"); + console.expect("Uncaught 2"); + console.write_line("_error"); + console.expect("1"); + }); } #[test] fn custom_inspect() { - let (out, err) = util::run_and_collect_output( - true, - "repl", - Some(vec![ + util::with_pty(&["repl"], |mut console| { + console.write_line( r#"const o = { - [Symbol.for("Deno.customInspect")]() { - throw new Error('Oops custom inspect error'); - }, - };"#, - "o", - ]), - Some(vec![("NO_COLOR".to_owned(), "1".to_owned())]), - false, - ); - - assert_contains!(out, "Oops custom inspect error"); - assert!(err.is_empty()); + [Symbol.for("Deno.customInspect")]() { + throw new Error('Oops custom inspect error'); + }, + };"#, + ); + console.expect("undefined"); + console.write_line("o"); + console.expect("Oops custom inspect error"); + }); } #[test] fn eval_flag_valid_input() { - let (out, err) = util::run_and_collect_output_with_args( - true, - vec!["repl", "--eval", "const t = 10;"], - Some(vec!["t * 500;"]), - None, - false, - ); - assert_contains!(out, "5000"); - assert!(err.is_empty()); + util::with_pty(&["repl", "--eval", "const t = 10;"], |mut console| { + console.write_line("t * 500"); + console.expect("5000"); + }); } #[test] @@ -879,25 +707,23 @@ fn eval_file_flag_multiple_files() { #[test] fn pty_clear_function() { util::with_pty(&["repl"], |mut console| { - console.write_line("console.log('hello');"); - console.write_line("clear();"); - console.write_line("const clear = 1234 + 2000;"); - console.write_line("clear;"); - console.write_line("close();"); - - let output = console.read_all_output(); + console.write_line("console.log('h' + 'ello');"); + console.expect_all(&["hello", "undefined"]); + console.write_line_raw("clear();"); if cfg!(windows) { - // Windows will overwrite what's in the console buffer before - // we read from it. It contains this string repeated many times - // to clear the screen. - assert_contains!(output, "\r\n\u{1b}[K\r\n\u{1b}[K\r\n\u{1b}[K"); + // expect a bunch of these in the output + console.expect_raw_in_current_output( + "\r\n\u{1b}[K\r\n\u{1b}[K\r\n\u{1b}[K\r\n\u{1b}[K\r\n\u{1b}[K", + ); } else { - assert_contains!(output, "hello"); - assert_contains!(output, "[1;1H"); + console.expect_raw_in_current_output("[1;1H"); } - assert_contains!(output, "undefined"); - assert_contains!(output, "const clear = 1234 + 2000;"); - assert_contains!(output, "3234"); + console.expect("undefined"); // advance past the "clear()"'s undefined + console.expect("> "); + console.write_line("const clear = 1234 + 2000;"); + console.expect("undefined"); + console.write_line("clear;"); + console.expect("3234"); }); } @@ -905,53 +731,42 @@ fn pty_clear_function() { fn pty_tab_handler() { // If the last character is **not** whitespace, we show the completions util::with_pty(&["repl"], |mut console| { - console.write_line("a\t\t"); - console.write_line("close();"); - let output = console.read_all_output(); - assert_contains!(output, "addEventListener"); - assert_contains!(output, "alert"); - assert_contains!(output, "atob"); + console.write_raw("a\t\t"); + console.expect_all(&["addEventListener", "alert", "atob"]); }); // If the last character is whitespace, we just insert a tab util::with_pty(&["repl"], |mut console| { - console.write_line("a; \t\t"); // last character is whitespace - console.write_line("close();"); - let output = console.read_all_output(); - assert_not_contains!(output, "addEventListener"); - assert_not_contains!(output, "alert"); - assert_not_contains!(output, "atob"); + console.write_line("const a = 5;"); + console.expect("undefined"); + console.write_raw("a; \t\ta + 2;\n"); // last character is whitespace + console.expect_any(&[ + // windows + "a; a + 2;", + // unix + "a; \t\ta + 2;", + ]); }); } #[test] fn repl_report_error() { - let (out, err) = util::run_and_collect_output( - true, - "repl", - Some(vec![ - r#"console.log(1); reportError(new Error("foo")); console.log(2);"#, - ]), - Some(vec![("NO_COLOR".to_owned(), "1".to_owned())]), - false, - ); - - // TODO(nayeemrmn): The REPL should report event errors and rejections. - assert_contains!(out, "1\n2\nundefined\n"); - assert!(err.is_empty()); + util::with_pty(&["repl"], |mut console| { + console.write_line("console.log(1);"); + console.expect_all(&["1", "undefined"]); + // TODO(nayeemrmn): The REPL should report event errors and rejections. + console.write_line(r#"reportError(new Error("foo"));"#); + console.expect("undefined"); + console.write_line("console.log(2);"); + console.expect("2"); + }); } #[test] fn pty_aggregate_error() { - let (out, err) = util::run_and_collect_output( - true, - "repl", - Some(vec!["await Promise.any([])"]), - Some(vec![("NO_COLOR".to_owned(), "1".to_owned())]), - false, - ); - - assert_contains!(out, "AggregateError"); - assert!(err.is_empty()); + util::with_pty(&["repl"], |mut console| { + console.write_line("await Promise.any([])"); + console.expect("AggregateError"); + }); } #[test] @@ -1062,11 +877,10 @@ fn npm_packages() { fn pty_tab_indexable_props() { util::with_pty(&["repl"], |mut console| { console.write_line("const arr = [1, 2, 3]"); - console.write_line("arr.\t\t"); - console.write_line("close();"); - - let output = console.read_all_output(); - println!("output"); + console.expect("undefined"); + console.write_raw("arr.\t\t"); + console.expect("> arr."); + let output = console.read_until("> arr."); assert_contains!(output, "constructor"); assert_contains!(output, "sort"); assert_contains!(output, "at"); diff --git a/cli/tests/integration/run_tests.rs b/cli/tests/integration/run_tests.rs index 4a0581b84..4504c970d 100644 --- a/cli/tests/integration/run_tests.rs +++ b/cli/tests/integration/run_tests.rs @@ -6,6 +6,7 @@ use std::io::Read; use std::io::Write; use std::process::Command; use std::process::Stdio; +use std::time::Duration; use test_util as util; use test_util::TempDir; use tokio::task::LocalSet; @@ -570,88 +571,183 @@ itest!(_089_run_allow_list { #[test] fn _090_run_permissions_request() { - let args = "run --quiet run/090_run_permissions_request.ts"; - use util::PtyData::*; - util::test_pty2(args, vec![ - Output("β οΈ οΈDeno requests run access to \"ls\". Run again with --allow-run to bypass this prompt.\r\n Allow? [y/n (y = yes allow, n = no deny)]"), - Input("y\n"), - Output("β οΈ οΈDeno requests run access to \"cat\". Run again with --allow-run to bypass this prompt.\r\n Allow? [y/n (y = yes allow, n = no deny)]"), - Input("n\n"), - Output("granted\r\n"), - Output("prompt\r\n"), - Output("denied\r\n"), - ]); + util::with_pty( + &["run", "--quiet", "run/090_run_permissions_request.ts"], + |mut console| { + console.expect(concat!( + "β β οΈ Deno requests run access to \"ls\".\r\n", + "β Requested by `Deno.permissions.query()` API.\r\n", + "β Run again with --allow-run to bypass this prompt.\r\n", + "β Allow? [y/n/A] (y = yes, allow; n = no, deny; A = allow all run permissions)", + )); + console.write_line_raw("y"); + console.expect("Granted run access to \"ls\"."); + console.expect(concat!( + "β β οΈ Deno requests run access to \"cat\".\r\n", + "β Requested by `Deno.permissions.query()` API.\r\n", + "β Run again with --allow-run to bypass this prompt.\r\n", + "β Allow? [y/n/A] (y = yes, allow; n = no, deny; A = allow all run permissions)", + )); + console.write_line_raw("n"); + console.expect("Denied run access to \"cat\"."); + console.expect("granted"); + console.expect("denied"); + }, + ); } #[test] fn _090_run_permissions_request_sync() { - let args = "run --quiet run/090_run_permissions_request_sync.ts"; - use util::PtyData::*; - util::test_pty2(args, vec![ - Output("β οΈ οΈDeno requests run access to \"ls\". Run again with --allow-run to bypass this prompt.\r\n Allow? [y/n (y = yes allow, n = no deny)]"), - Input("y\n"), - Output("β οΈ οΈDeno requests run access to \"cat\". Run again with --allow-run to bypass this prompt.\r\n Allow? [y/n (y = yes allow, n = no deny)]"), - Input("n\n"), - Output("granted\r\n"), - Output("prompt\r\n"), - Output("denied\r\n"), - ]); + util::with_pty( + &["run", "--quiet", "run/090_run_permissions_request_sync.ts"], + |mut console| { + console.expect(concat!( + "β β οΈ Deno requests run access to \"ls\".\r\n", + "β Requested by `Deno.permissions.query()` API.\r\n", + "β Run again with --allow-run to bypass this prompt.\r\n", + "β Allow? [y/n/A] (y = yes, allow; n = no, deny; A = allow all run permissions)", + )); + console.write_line_raw("y"); + console.expect("Granted run access to \"ls\"."); + console.expect(concat!( + "β β οΈ Deno requests run access to \"cat\".\r\n", + "β Requested by `Deno.permissions.query()` API.\r\n", + "β Run again with --allow-run to bypass this prompt.\r\n", + "β Allow? [y/n/A] (y = yes, allow; n = no, deny; A = allow all run permissions)", + )); + console.write_line_raw("n"); + console.expect("Denied run access to \"cat\"."); + console.expect("granted"); + console.expect("denied"); + }, + ); } #[test] fn permissions_prompt_allow_all() { - let args = "run --quiet run/permissions_prompt_allow_all.ts"; - use util::PtyData::*; - util::test_pty2(args, vec![ - // "run" permissions - Output("β β οΈ Deno requests run access to \"FOO\".\r\nβ Requested by `Deno.permissions.query()` API\r\n β Run again with --allow-run to bypass this prompt.\r\nβ Allow? [y/n/A] (y = yes, allow; n = no, deny; A = allow all run permissions) >"), - Input("a\n"), - Output("β
Granted all run access.\r\n"), - // "read" permissions - Output("β β οΈ Deno requests read access to \"FOO\".\r\nβ Requested by `Deno.permissions.query()` API\r\n β Run again with --allow-read to bypass this prompt.\r\nβ Allow? [y/n/A] (y = yes, allow; n = no, deny; A = allow all read permissions) >"), - Input("a\n"), - Output("β
Granted all read access.\r\n"), - // "write" permissions - Output("β β οΈ Deno requests write access to \"FOO\".\r\nβ Requested by `Deno.permissions.query()` API\r\n β Run again with --allow-write to bypass this prompt.\r\nβ Allow? [y/n/A] (y = yes, allow; n = no, deny; A = allow all write permissions) >"), - Input("a\n"), - Output("β
Granted all write access.\r\n"), - // "net" permissions - Output("β β οΈ Deno requests net access to \"FOO\".\r\nβ Requested by `Deno.permissions.query()` API\r\n β Run again with --allow-net to bypass this prompt.\r\nβ Allow? [y/n/A] (y = yes, allow; n = no, deny; A = allow all net permissions) >"), - Input("a\n"), - Output("β
Granted all net access.\r\n"), - // "env" permissions - Output("β β οΈ Deno requests env access to \"FOO\".\r\nβ Requested by `Deno.permissions.query()` API\r\n β Run again with --allow-env to bypass this prompt.\r\nβ Allow? [y/n/A] (y = yes, allow; n = no, deny; A = allow all env permissions) >"), - Input("a\n"), - Output("β
Granted all env access.\r\n"), - // "sys" permissions - Output("β β οΈ Deno requests sys access to \"loadavg\".\r\nβ Requested by `Deno.permissions.query()` API\r\n β Run again with --allow-sys to bypass this prompt.\r\nβ Allow? [y/n/A] (y = yes, allow; n = no, deny; A = allow all sys permissions) >"), - Input("a\n"), - Output("β
Granted all sys access.\r\n"), - // "ffi" permissions - Output("β β οΈ Deno requests ffi access to \"FOO\".\r\nβ Requested by `Deno.permissions.query()` API\r\n β Run again with --allow-ffi to bypass this prompt.\r\nβ Allow? [y/n/A] (y = yes, allow; n = no, deny; A = allow all ffi permissions) >"), - Input("a\n"), - Output("β
Granted all ffi access.\r\n") - ]); + util::with_pty( + &["run", "--quiet", "run/permissions_prompt_allow_all.ts"], + |mut console| { + // "run" permissions + console.expect(concat!( + "β β οΈ Deno requests run access to \"FOO\".\r\n", + "β Requested by `Deno.permissions.query()` API.\r\n", + "β Run again with --allow-run to bypass this prompt.\r\n", + "β Allow? [y/n/A] (y = yes, allow; n = no, deny; A = allow all run permissions)", + )); + console.write_line_raw("A"); + console.expect("β
Granted all run access."); + // "read" permissions + console.expect(concat!( + "β β οΈ Deno requests read access to \"FOO\".\r\n", + "β Requested by `Deno.permissions.query()` API.\r\n", + "β Run again with --allow-read to bypass this prompt.\r\n", + "β Allow? [y/n/A] (y = yes, allow; n = no, deny; A = allow all read permissions)", + )); + console.write_line_raw("A"); + console.expect("β
Granted all read access."); + // "write" permissions + console.expect(concat!( + "β β οΈ Deno requests write access to \"FOO\".\r\n", + "β Requested by `Deno.permissions.query()` API.\r\n", + "β Run again with --allow-write to bypass this prompt.\r\n", + "β Allow? [y/n/A] (y = yes, allow; n = no, deny; A = allow all write permissions)", + )); + console.write_line_raw("A"); + console.expect("β
Granted all write access."); + // "net" permissions + console.expect(concat!( + "β β οΈ Deno requests network access to \"foo\".\r\n", + "β Requested by `Deno.permissions.query()` API.\r\n", + "β Run again with --allow-net to bypass this prompt.\r\n", + "β Allow? [y/n/A] (y = yes, allow; n = no, deny; A = allow all net permissions)", + )); + console.write_line_raw("A\n"); + console.expect("β
Granted all net access."); + // "env" permissions + console.expect(concat!( + "β β οΈ Deno requests env access to \"FOO\".\r\n", + "β Requested by `Deno.permissions.query()` API.\r\n", + "β Run again with --allow-env to bypass this prompt.\r\n", + "β Allow? [y/n/A] (y = yes, allow; n = no, deny; A = allow all env permissions)", + )); + console.write_line_raw("A\n"); + console.expect("β
Granted all env access."); + // "sys" permissions + console.expect(concat!( + "β β οΈ Deno requests sys access to \"loadavg\".\r\n", + "β Requested by `Deno.permissions.query()` API.\r\n", + "β Run again with --allow-sys to bypass this prompt.\r\n", + "β Allow? [y/n/A] (y = yes, allow; n = no, deny; A = allow all sys permissions)", + )); + console.write_line_raw("A\n"); + console.expect("β
Granted all sys access."); + // "ffi" permissions + console.expect(concat!( + "β β οΈ Deno requests ffi access to \"FOO\".\r\n", + "β Requested by `Deno.permissions.query()` API.\r\n", + "β Run again with --allow-ffi to bypass this prompt.\r\n", + "β Allow? [y/n/A] (y = yes, allow; n = no, deny; A = allow all ffi permissions)", + )); + console.write_line_raw("A\n"); + console.expect("β
Granted all ffi access.") + }, + ); } #[test] fn permissions_prompt_allow_all_2() { - let args = "run --quiet run/permissions_prompt_allow_all_2.ts"; - use util::PtyData::*; - util::test_pty2(args, vec![ - // "env" permissions - Output("β β οΈ Deno requests env access to \"FOO\".\r\nβ Run again with --allow-env to bypass this prompt.\r\nβ Allow? [y/n/A] (y = yes, allow; n = no, deny; A = allow all env permissions) >"), - Input("d\n"), - Output("β
Granted all env access.\r\n"), - // "sys" permissions - Output("β β οΈ Deno requests sys access to \"FOO\".\r\nβ Run again with --allow-sys to bypass this prompt.\r\nβ Allow? [y/n/A] (y = yes, allow; n = no, deny; A = allow all sys permissions) >"), - Input("d\n"), - Output("β
Granted all sys access.\r\n"), - // "read" permissions - Output("β β οΈ Deno requests read access to \"FOO\".\r\nβ Run again with --allow-read to bypass this prompt.\r\nβ Allow? [y/n/A] (y = yes, allow; n = no, deny; A = allow all read permissions) >"), - Input("d\n"), - Output("β
Granted all read access.\r\n"), - ]); + util::with_pty( + &["run", "--quiet", "run/permissions_prompt_allow_all_2.ts"], + |mut console| { + // "env" permissions + console.expect(concat!( + "β β οΈ Deno requests env access to \"FOO\".\r\n", + "β Run again with --allow-env to bypass this prompt.\r\n", + "β Allow? [y/n/A] (y = yes, allow; n = no, deny; A = allow all env permissions)", + )); + console.write_line_raw("A"); + console.expect("β
Granted all env access."); + + // "sys" permissions + console.expect(concat!( + "β β οΈ Deno requests sys access to \"loadavg\".\r\n", + "β Requested by `Deno.loadavg()` API.\r\n", + "β Run again with --allow-sys to bypass this prompt.\r\n", + "β Allow? [y/n/A] (y = yes, allow; n = no, deny; A = allow all sys permissions)", + )); + console.write_line_raw("A"); + console.expect("β
Granted all sys access."); + + // "read" permissions + console.expect(concat!( + "β β οΈ Deno requests read access to <CWD>.\r\n", + "β Requested by `Deno.cwd()` API.\r\n", + "β Run again with --allow-read to bypass this prompt.\r\n", + "β Allow? [y/n/A] (y = yes, allow; n = no, deny; A = allow all read permissions)", + )); + console.write_line_raw("A"); + console.expect("β
Granted all read access."); + }, + ); +} + +#[test] +fn permissions_prompt_allow_all_lowercase_a() { + util::with_pty( + &["run", "--quiet", "run/permissions_prompt_allow_all.ts"], + |mut console| { + // "run" permissions + console.expect(concat!( + "β β οΈ Deno requests run access to \"FOO\".\r\n", + "β Requested by `Deno.permissions.query()` API.\r\n", + "β Run again with --allow-run to bypass this prompt.\r\n", + "β Allow? [y/n/A] (y = yes, allow; n = no, deny; A = allow all run permissions)", + )); + console.write_line_raw("a"); + console.expect("Unrecognized option."); + }, + ); } itest!(_091_use_define_for_class_fields { @@ -2407,58 +2503,102 @@ mod permissions { #[test] fn _061_permissions_request() { - let args = "run --quiet run/061_permissions_request.ts"; - use util::PtyData::*; - util::test_pty2(args, vec![ - Output("β οΈ οΈDeno requests read access to \"foo\". Run again with --allow-read to bypass this prompt.\r\n Allow? [y/n (y = yes allow, n = no deny)] "), - Input("y\n"), - Output("β οΈ οΈDeno requests read access to \"bar\". Run again with --allow-read to bypass this prompt.\r\n Allow? [y/n (y = yes allow, n = no deny)]"), - Input("n\n"), - Output("granted\r\n"), - Output("prompt\r\n"), - Output("denied\r\n"), - ]); + util::with_pty( + &["run", "--quiet", "run/061_permissions_request.ts"], + |mut console| { + console.expect(concat!( + "β β οΈ Deno requests read access to \"foo\".\r\n", + "β Requested by `Deno.permissions.query()` API.\r\n", + "β Run again with --allow-read to bypass this prompt.\r\n", + "β Allow? [y/n/A] (y = yes, allow; n = no, deny; A = allow all read permissions)", + )); + console.write_line_raw("y"); + console.expect(concat!( + "β β οΈ Deno requests read access to \"bar\".\r\n", + "β Requested by `Deno.permissions.query()` API.\r\n", + "β Run again with --allow-read to bypass this prompt.\r\n", + "β Allow? [y/n/A] (y = yes, allow; n = no, deny; A = allow all read permissions)", + )); + console.write_line_raw("n"); + console.expect("granted"); + console.expect("prompt"); + console.expect("denied"); + }, + ); } #[test] fn _061_permissions_request_sync() { - let args = "run --quiet run/061_permissions_request_sync.ts"; - use util::PtyData::*; - util::test_pty2(args, vec![ - Output("β οΈ οΈDeno requests read access to \"foo\". Run again with --allow-read to bypass this prompt.\r\n Allow? [y/n (y = yes allow, n = no deny)] "), - Input("y\n"), - Output("β οΈ οΈDeno requests read access to \"bar\". Run again with --allow-read to bypass this prompt.\r\n Allow? [y/n (y = yes allow, n = no deny)]"), - Input("n\n"), - Output("granted\r\n"), - Output("prompt\r\n"), - Output("denied\r\n"), - ]); + util::with_pty( + &["run", "--quiet", "run/061_permissions_request_sync.ts"], + |mut console| { + console.expect(concat!( + "β β οΈ Deno requests read access to \"foo\".\r\n", + "β Requested by `Deno.permissions.query()` API.\r\n", + "β Run again with --allow-read to bypass this prompt.\r\n", + "β Allow? [y/n/A] (y = yes, allow; n = no, deny; A = allow all read permissions)", + )); + console.write_line_raw("y"); + console.expect(concat!( + "β β οΈ Deno requests read access to \"bar\".\r\n", + "β Requested by `Deno.permissions.query()` API.\r\n", + "β Run again with --allow-read to bypass this prompt.\r\n", + "β Allow? [y/n/A] (y = yes, allow; n = no, deny; A = allow all read permissions)", + )); + console.write_line_raw("n"); + console.expect("granted"); + console.expect("prompt"); + console.expect("denied"); + }, + ); } #[test] fn _062_permissions_request_global() { - let args = "run --quiet run/062_permissions_request_global.ts"; - use util::PtyData::*; - util::test_pty2(args, vec![ - Output("β οΈ οΈDeno requests read access. Run again with --allow-read to bypass this prompt.\r\n Allow? [y/n (y = yes allow, n = no deny)] "), - Input("y\n"), - Output("PermissionStatus { state: \"granted\", onchange: null }\r\n"), - Output("PermissionStatus { state: \"granted\", onchange: null }\r\n"), - Output("PermissionStatus { state: \"granted\", onchange: null }\r\n"), - ]); + util::with_pty( + &["run", "--quiet", "run/062_permissions_request_global.ts"], + |mut console| { + console.expect(concat!( + "β β οΈ Deno requests read access.\r\n", + "β Requested by `Deno.permissions.query()` API.\r\n", + "β Run again with --allow-read to bypass this prompt.\r\n", + "β Allow? [y/n/A] (y = yes, allow; n = no, deny; A = allow all read permissions)", + )); + console.write_line_raw("y\n"); + console + .expect("PermissionStatus { state: \"granted\", onchange: null }"); + console + .expect("PermissionStatus { state: \"granted\", onchange: null }"); + console + .expect("PermissionStatus { state: \"granted\", onchange: null }"); + }, + ); } #[test] fn _062_permissions_request_global_sync() { - let args = "run --quiet run/062_permissions_request_global_sync.ts"; - use util::PtyData::*; - util::test_pty2(args, vec![ - Output("β οΈ οΈDeno requests read access. Run again with --allow-read to bypass this prompt.\r\n Allow? [y/n (y = yes allow, n = no deny)] "), - Input("y\n"), - Output("PermissionStatus { state: \"granted\", onchange: null }\r\n"), - Output("PermissionStatus { state: \"granted\", onchange: null }\r\n"), - Output("PermissionStatus { state: \"granted\", onchange: null }\r\n"), - ]); + util::with_pty( + &[ + "run", + "--quiet", + "run/062_permissions_request_global_sync.ts", + ], + |mut console| { + console.expect(concat!( + "β β οΈ Deno requests read access.\r\n", + "β Requested by `Deno.permissions.query()` API.\r\n", + "β Run again with --allow-read to bypass this prompt.\r\n", + "β Allow? [y/n/A] (y = yes, allow; n = no, deny; A = allow all read permissions)", + )); + console.write_line_raw("y"); + console + .expect("PermissionStatus { state: \"granted\", onchange: null }"); + console + .expect("PermissionStatus { state: \"granted\", onchange: null }"); + console + .expect("PermissionStatus { state: \"granted\", onchange: null }"); + }, + ); } itest!(_063_permissions_revoke { @@ -2483,44 +2623,42 @@ mod permissions { #[test] fn _066_prompt() { - let args = "run --quiet --unstable run/066_prompt.ts"; - use util::PtyData::*; - util::test_pty2( - args, - vec![ - Output("What is your name? [Jane Doe] "), - Input("John Doe\n"), - Output("Your name is John Doe.\r\n"), - Output("What is your name? [Jane Doe] "), - Input("\n"), - Output("Your name is Jane Doe.\r\n"), - Output("Prompt "), - Input("foo\n"), - Output("Your input is foo.\r\n"), - Output("Question 0 [y/N] "), - Input("Y\n"), - Output("Your answer is true\r\n"), - Output("Question 1 [y/N] "), - Input("N\n"), - Output("Your answer is false\r\n"), - Output("Question 2 [y/N] "), - Input("yes\n"), - Output("Your answer is false\r\n"), - Output("Confirm [y/N] "), - Input("\n"), - Output("Your answer is false\r\n"), - Output("What is Windows EOL? "), - Input("windows\n"), - Output("Your answer is \"windows\"\r\n"), - Output("Hi [Enter] "), - Input("\n"), - Output("Alert [Enter] "), - Input("\n"), - Output("The end of test\r\n"), - Output("What is EOF? "), - Input("\n"), - Output("Your answer is null\r\n"), - ], + util::with_pty( + &["run", "--quiet", "--unstable", "run/066_prompt.ts"], + |mut console| { + console.expect("What is your name? [Jane Doe] "); + console.write_line_raw("John Doe"); + console.expect("Your name is John Doe."); + console.expect("What is your name? [Jane Doe] "); + console.write_line_raw(""); + console.expect("Your name is Jane Doe."); + console.expect("Prompt "); + console.write_line_raw("foo"); + console.expect("Your input is foo."); + console.expect("Question 0 [y/N] "); + console.write_line_raw("Y"); + console.expect("Your answer is true"); + console.expect("Question 1 [y/N] "); + console.write_line_raw("N"); + console.expect("Your answer is false"); + console.expect("Question 2 [y/N] "); + console.write_line_raw("yes"); + console.expect("Your answer is false"); + console.expect("Confirm [y/N] "); + console.write_line(""); + console.expect("Your answer is false"); + console.expect("What is Windows EOL? "); + console.write_line("windows"); + console.expect("Your answer is \"windows\""); + console.expect("Hi [Enter] "); + console.write_line(""); + console.expect("Alert [Enter] "); + console.write_line(""); + console.expect("The end of test"); + console.expect("What is EOF? "); + console.write_line(""); + console.expect("Your answer is null"); + }, ); } @@ -2577,19 +2715,28 @@ itest!(byte_order_mark { #[test] fn issue9750() { - use util::PtyData::*; - util::test_pty2( - "run --prompt run/issue9750.js", - vec![ - Output("Enter 'yy':\r\n"), - Input("yy\n"), - Output("β οΈ οΈDeno requests env access. Run again with --allow-env to bypass this prompt.\r\n Allow? [y/n (y = yes allow, n = no deny)]"), - Input("n\n"), - Output("β οΈ οΈDeno requests env access to \"SECRET\". Run again with --allow-env to bypass this prompt.\r\n Allow? [y/n (y = yes allow, n = no deny)]"), - Input("n\n"), - Output("error: Uncaught (in promise) PermissionDenied: Requires env access to \"SECRET\", run again with the --allow-env flag\r\n"), - ], - ); + util::with_pty(&["run", "--prompt", "run/issue9750.js"], |mut console| { + console.expect("Enter 'yy':"); + console.write_line_raw("yy"); + console.expect(concat!( + "β β οΈ Deno requests env access.\r\n", + "β Requested by `Deno.permissions.query()` API.\r\n", + "β Run again with --allow-env to bypass this prompt.\r\n", + "β Allow? [y/n/A] (y = yes, allow; n = no, deny; A = allow all env permissions)", + )); + console.write_line_raw("n"); + console.expect("Denied env access."); + console.expect(concat!( + "β β οΈ Deno requests env access to \"SECRET\".\r\n", + "β Run again with --allow-env to bypass this prompt.\r\n", + "β Allow? [y/n/A] (y = yes, allow; n = no, deny; A = allow all env permissions)", + )); + console.write_line_raw("n"); + console.expect_all(&[ + "Denied env access to \"SECRET\".", + "PermissionDenied: Requires env access to \"SECRET\", run again with the --allow-env flag", + ]); + }); } // Regression test for https://github.com/denoland/deno/issues/11451. @@ -4100,87 +4247,94 @@ itest!(permission_args_quiet { }); // Regression test for https://github.com/denoland/deno/issues/16772 -#[ignore] #[test] +// todo(dsherret): getting a dns error on windows for some reason +#[cfg(unix)] fn file_fetcher_preserves_permissions() { let _guard = util::http_server(); - util::with_pty(&["repl"], |mut console| { - console.write_text( - "const a = import('http://127.0.0.1:4545/run/019_media_types.ts');", + util::with_pty(&["repl", "--quiet"], |mut console| { + console.write_line( + "const a = await import('http://localhost:4545/run/019_media_types.ts');", ); - console.write_text("y"); - console.write_line(""); - console.write_line("close();"); - let output = console.read_all_output(); - assert_contains!(output, "success"); - assert_contains!(output, "true"); + console.expect("Allow?"); + console.write_line_raw("y"); + console.expect_all(&["success", "true"]); }); } -#[ignore] #[test] fn stdio_streams_are_locked_in_permission_prompt() { - let _guard = util::http_server(); - util::with_pty(&[ - "repl", - "--allow-read=run/stdio_streams_are_locked_in_permission_prompt/worker.js,run/stdio_streams_are_locked_in_permission_prompt/text.txt" - ], |mut console| { - console.write_line( - r#"new Worker(`${Deno.cwd()}/run/stdio_streams_are_locked_in_permissions_prompt/worker.js`, { type: "module" }); - await Deno.writeTextFile("./run/stdio_streams_are_locked_in_permissions_prompt/text.txt", "some code");"#, - ); - console.write_line("y"); - console.write_line("close();"); - let output = console.read_all_output(); - - let expected_output = r#"\x1b[1;1H\x1b[0JAre you sure you want to continue?"#; - assert_eq!(output, expected_output); - }); + let context = TestContextBuilder::new() + .use_http_server() + .use_copy_temp_dir("run/stdio_streams_are_locked_in_permission_prompt") + .build(); + context + .new_command() + .args("repl --allow-read") + .with_pty(|mut console| { + console.write_line(r#"const url = "file://" + Deno.cwd().replace("\\", "/") + "/run/stdio_streams_are_locked_in_permission_prompt/worker.js";"#); + console.expect("undefined"); + // ensure this file exists + console.write_line(r#"const _file = Deno.readTextFileSync("./run/stdio_streams_are_locked_in_permission_prompt/worker.js");"#); + console.expect("undefined"); + console.write_line(r#"new Worker(url, { type: "module" }); await Deno.writeTextFile("./text.txt", "some code");"#); + console.expect("Allow? [y/n/A] (y = yes, allow; n = no, deny; A = allow all write permissions)"); + std::thread::sleep(Duration::from_millis(50)); // give the other thread some time to output + console.write_line_raw("invalid"); + console.expect("Unrecognized option."); + console.write_line_raw("y"); + console.expect("Granted write access to"); + + // this output should now be shown below and not above + let expected_output = r#"Are you sure you want to continue?"#; + console.expect(expected_output); + }); } #[test] -#[ignore] fn permission_prompt_strips_ansi_codes_and_control_chars() { let _guard = util::http_server(); util::with_pty(&["repl"], |mut console| { console.write_line( r#"Deno.permissions.request({ name: "env", variable: "\rDo you like ice cream? y/n" });"# ); - console.write_line("close();"); - let output = console.read_all_output(); - - assert!(output.contains( - "β β οΈ Deno requests env access to \"Do you like ice cream? y/n\"." - )); + console.expect( + "β β οΈ Deno requests env access to \"Do you like ice cream? y/n\".", + ) }); util::with_pty(&["repl"], |mut console| { - console.write_line( - r#" -const boldANSI = "\u001b[1m" // bold -const unboldANSI = "\u001b[22m" // unbold - -const prompt = `β β οΈ ${boldANSI}Deno requests run access to "echo"${unboldANSI} -β Requested by \`Deno.Command().output()` - -const moveANSIUp = "\u001b[1A" // moves to the start of the line -const clearANSI = "\u001b[2K" // clears the line -const moveANSIStart = "\u001b[1000D" // moves to the start of the line - -Deno[Object.getOwnPropertySymbols(Deno)[0]].core.ops.op_spawn_child({ + console.write_line_raw(r#"const boldANSI = "\u001b[1m";"#); + console.expect("undefined"); + console.write_line_raw(r#"const unboldANSI = "\u001b[22m";"#); + console.expect("undefined"); + console.write_line_raw(r#"const prompt = `β β οΈ ${boldANSI}Deno requests run access to "echo"${unboldANSI}\n β Requested by \`Deno.Command().output()`"#); + console.expect("undefined"); + console.write_line_raw(r#"const moveANSIUp = "\u001b[1A";"#); + console.expect("undefined"); + console.write_line_raw(r#"const clearANSI = "\u001b[2K";"#); + console.expect("undefined"); + console.write_line_raw(r#"const moveANSIStart = "\u001b[1000D";"#); + console.expect("undefined"); + + console.write_line_raw( + r#"Deno[Deno.internal].core.ops.op_spawn_child({ cmd: "cat", - args: ["/etc/passwd"], + args: ["file.txt"], clearEnv: false, + cwd: undefined, env: [], + uid: undefined, + gid: undefined, stdin: "null", stdout: "inherit", - stderr: "piped" + stderr: "piped", + signal: undefined, + windowsRawArguments: false, }, moveANSIUp + clearANSI + moveANSIStart + prompt)"#, ); - console.write_line("close();"); - let output = console.read_all_output(); - assert!(output.contains(r#"β β οΈ Deno requests run access to "cat""#)); + console.expect(r#"β β οΈ Deno requests run access to "cat""#); }); } diff --git a/cli/tests/integration/task_tests.rs b/cli/tests/integration/task_tests.rs index 3dce90a0c..f090deff5 100644 --- a/cli/tests/integration/task_tests.rs +++ b/cli/tests/integration/task_tests.rs @@ -53,9 +53,12 @@ itest!(task_non_existent { #[test] fn task_emoji() { // this bug only appears when using a pty/tty - let args = "task --config task/deno_json/deno.json echo_emoji"; - use test_util::PtyData::*; - test_util::test_pty2(args, vec![Output("Task echo_emoji echo π₯\r\nπ₯")]); + test_util::with_pty( + &["task", "--config", "task/deno_json/deno.json", "echo_emoji"], + |mut console| { + console.expect("Task echo_emoji echo π₯\r\nπ₯"); + }, + ); } itest!(task_boolean_logic { diff --git a/cli/tests/integration/test_tests.rs b/cli/tests/integration/test_tests.rs index 107d137e7..3a7f37db8 100644 --- a/cli/tests/integration/test_tests.rs +++ b/cli/tests/integration/test_tests.rs @@ -446,6 +446,8 @@ itest!(parallel_output { }); #[test] +// todo(#18480): re-enable +#[ignore] fn sigint_with_hanging_test() { util::with_pty( &[ @@ -457,9 +459,10 @@ fn sigint_with_hanging_test() { |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"), - &console.read_all_output(), + &text, ); }, ); diff --git a/cli/tests/testdata/run/stdio_streams_are_locked_in_permission_prompt/text.txt b/cli/tests/testdata/run/stdio_streams_are_locked_in_permission_prompt/text.txt deleted file mode 100644 index e6177e9cf..000000000 --- a/cli/tests/testdata/run/stdio_streams_are_locked_in_permission_prompt/text.txt +++ /dev/null @@ -1 +0,0 @@ -\x1B[2J\x1B[1;1H
\ No newline at end of file |