char/avril
(wip) why'd you have to go and make things so complicaaaaated?
git clone https://git.t4t.associates/char/avril
96879c9
main
1# [ path = "common/lsp.rs" ] 2# [ allow ( dead_code )] 3mod support; 4 5use std:: path:: Path ; 6use std:: process::{ Command , Output }; 7 8use support::{ avril, backend, files}; 9 10fn check ( root : & Path , backend : & Path , args : & [ & str ]) ->Output { 11Command :: new ( avril ()) 12. current_dir ( root) 13. args ([ 14"check" , 15& format! ( "--typescript={}" , backend. display ()), 16"--offline" , 17]) 18. args ( args) 19. output () 20. unwrap () 21} 22 23# [ test ] 24fn generated_fjson_declarations_are_available_to_check () { 25let Some ( backend) =backend () else { 26eprintln! ( "skipping: AVRIL_TEST_TYPESCRIPT is not set" ); 27return ; 28}; 29let dir = tempfile:: tempdir (). unwrap (); 30let root = dir. path (); 31files ( 32 root, 33& [ 34( "avril.conf" , "{}" ), 35( 36"main.ts" , 37r#" 38import {apply, parse, stringify} from 'avril:fjson'; 39const value: unknown = parse('answer: 42'); 40const source: string = stringify(value); 41const result: string = apply(source, {answer: 43}); 42"# , 43), 44], 45); 46let clean =check ( root, & backend, & [ "main.ts" ]); 47assert! ( 48 clean. status . success (), 49"{}{}" , 50String :: from_utf8_lossy ( & clean. stdout ), 51String :: from_utf8_lossy ( & clean. stderr ), 52); 53files ( 54 root, 55& [( 56"main.ts" , 57r#" 58import {apply, parse} from 'avril:fjson'; 59const value: string = parse('answer: 42'); 60parse(123); 61apply('', 123); 62"# , 63)], 64); 65let broken =check ( root, & backend, & [ "main.ts" ]); 66let stdout =String :: from_utf8 ( broken. stdout ). unwrap (); 67assert! ( !broken. status . success (), "{stdout}" ); 68assert! ( stdout. contains ( "error TS2322:" ), "{stdout}" ); 69assert! ( stdout. contains ( "error TS2345:" ), "{stdout}" ); 70} 71 72# [ test ] 73fn generated_test_declarations_are_available_to_check () { 74let Some ( backend) =backend () else { 75eprintln! ( "skipping: AVRIL_TEST_TYPESCRIPT is not set" ); 76return ; 77}; 78let dir = tempfile:: tempdir (). unwrap (); 79let root = dir. path (); 80files ( 81 root, 82& [ 83( "avril.conf" , "{}" ), 84( 85"main.ts" , 86r#" 87import { test, type TestContext, type TestOptions } from "avril:test"; 88const options: TestOptions = { name: "options", fn: () => {} }; 89test(options); 90test("named", async (t) => { 91const context: TestContext = t; 92const passed: boolean = await context.step("nested", (child) => { 93const name: string = child.name; 94}); 95}); 96test.only(options); 97test.only("focused", () => {}); 98test.ignore(options); 99test.ignore("ignored"); 100"# , 101), 102], 103); 104let clean =check ( root, & backend, & [ "main.ts" ]); 105assert! ( 106 clean. status . success (), 107"{}{}" , 108String :: from_utf8_lossy ( & clean. stdout ), 109String :: from_utf8_lossy ( & clean. stderr ), 110); 111 112files ( 113 root, 114& [( 115"main.ts" , 116r#" 117import { test, runTests } from "avril:test"; 118const result: string = test("name", () => {}); 119"# , 120)], 121); 122let broken =check ( root, & backend, & [ "main.ts" ]); 123let stdout =String :: from_utf8 ( broken. stdout ). unwrap (); 124assert! ( !broken. status . success (), "{stdout}" ); 125assert! ( stdout. contains ( "error TS2322:" ), "{stdout}" ); 126assert! ( stdout. contains ( "error TS2305:" ), "{stdout}" ); 127 128files ( 129 root, 130& [( 131"main.ts" , 132r#" 133// @ts-expect-error TypeScript suppression cannot grant private-module access. 134import { op_test_event } from "ext:core/ops"; 135"# , 136)], 137); 138let denied =check ( root, & backend, & [ "main.ts" ]); 139let output =format! ( 140"{}{}" , 141String :: from_utf8_lossy ( & denied. stdout ), 142String :: from_utf8_lossy ( & denied. stderr ), 143); 144assert! ( !denied. status . success (), "{output}" ); 145assert! ( output. contains ( "Extension modules are private" ), "{output}" ); 146} 147 148# [ test ] 149fn type_checks_the_module_graph_without_executing_it () { 150let Some ( backend) =backend () else { 151eprintln! ( "skipping: AVRIL_TEST_TYPESCRIPT is not set" ); 152return ; 153}; 154let dir = tempfile:: tempdir (). unwrap (); 155let root = dir. path (); 156files ( 157 root, 158& [ 159( "avril.conf" , "{}" ), 160( "dep.ts" , "export const value = 42 as const;" ), 161( 162"main.ts" , 163"import {value} from \"./dep.ts\";\nconst checked: number = value;\nchecked;\nthrow Error(\"must not execute\");" , 164), 165], 166); 167let clean =check ( root, & backend, & [ "main.ts" ]); 168assert! ( 169 clean. status . success (), 170"{}" , 171String :: from_utf8_lossy ( & clean. stderr ) 172); 173assert! ( clean. stdout . is_empty ()); 174 175files ( 176 root, 177& [( 178"main.ts" , 179"import {value} from \"./dep.ts\";\nconst checked: string = value;\nchecked;\nthrow Error(\"must not execute\");" , 180)], 181); 182// The separate-value form works like `avril lsp --typescript PATH`. 183let broken =Command :: new ( avril ()) 184. current_dir ( root) 185. args ([ 186"check" , 187"--typescript" , 188 backend. to_str (). unwrap (), 189"--offline" , 190"main.ts" , 191]) 192. output () 193. unwrap (); 194let stdout =String :: from_utf8 ( broken. stdout ). unwrap (); 195assert! ( !broken. status . success (), "{stdout}" ); 196assert! ( stdout. contains ( "main.ts:2:" ), "{stdout}" ); 197assert! ( stdout. contains ( "error TS2322:" ), "{stdout}" ); 198 199files ( root, & [( "main.ts" , "import \"./missing.ts\";" )]); 200let unresolved =check ( root, & backend, & [ "main.ts" ]); 201let stdout =String :: from_utf8 ( unresolved. stdout ). unwrap (); 202assert! ( !unresolved. status . success (), "{stdout}" ); 203assert! ( stdout. contains ( "./missing.ts" ), "{stdout}" ); 204 205// The entry grant does not extend to dependencies under `-0`: the 206// denied dependency has no source in the program, but its diagnostic 207// must still fail the check. 208files ( 209 root, 210& [( 211"main.ts" , 212"import {value} from \"./dep.ts\";\nconst checked: number = value;\nchecked;" , 213)], 214); 215let denied =check ( root, & backend, & [ "-0" , "main.ts" ]); 216let stdout =String :: from_utf8 ( denied. stdout ). unwrap (); 217assert! ( !denied. status . success (), "{stdout}" ); 218assert! ( stdout. contains ( "PermissionDenied" ), "{stdout}" ); 219}