From 84f3bf2f976d09b494df4512917fb72aab8b06f5 Mon Sep 17 00:00:00 2001 From: Boshen <1430279+Boshen@users.noreply.github.com> Date: Tue, 19 Nov 2024 12:22:42 +0000 Subject: [PATCH] refactor(transform_conformance): clean up test execution code (#7357) --- .../snapshots/babel.snap.md | 209 +----------------- .../snapshots/babel_exec.snap.md | 96 +++----- .../snapshots/oxc_exec.snap.md | 10 +- tasks/transform_conformance/src/constants.rs | 3 + tasks/transform_conformance/src/lib.rs | 75 +++---- tasks/transform_conformance/src/test_case.rs | 138 ++++++------ 6 files changed, 151 insertions(+), 380 deletions(-) diff --git a/tasks/transform_conformance/snapshots/babel.snap.md b/tasks/transform_conformance/snapshots/babel.snap.md index 19eea87d11d7f..4068272f73e7b 100644 --- a/tasks/transform_conformance/snapshots/babel.snap.md +++ b/tasks/transform_conformance/snapshots/babel.snap.md @@ -1,6 +1,6 @@ commit: d20b314c -Passed: 319/633 +Passed: 327/574 # All Passed: * babel-plugin-transform-class-static-block @@ -296,170 +296,6 @@ x Output mismatch x Output mismatch -# babel-plugin-transform-object-rest-spread (5/59) -* assumption-ignoreFunctionLength/parameters-object-rest-used-in-default/input.js -x Output mismatch - -* assumption-objectRestNoSymbols/rest-assignment-expression/input.js -x Output mismatch - -* assumption-objectRestNoSymbols/rest-computed/input.js -x Output mismatch - -* assumption-objectRestNoSymbols/rest-nested/input.js -x Output mismatch - -* assumption-objectRestNoSymbols/rest-var-declaration/input.js -x Output mismatch - -* assumption-pureGetters/rest-remove-unused-excluded-keys/input.js -x Output mismatch - -* assumption-pureGetters/spread-single-call/input.js -x Output mismatch - -* assumption-setSpreadProperties/assignment/input.js -x Output mismatch - -* assumption-setSpreadProperties/expression/input.js -x Output mismatch - -* assumption-setSpreadProperties/targets-support-object-assign/input.js -x Output mismatch - -* assumption-setSpreadProperties-with-useBuiltIns/assignment/input.js -x Output mismatch - -* assumption-setSpreadProperties-with-useBuiltIns/expression/input.js -x Output mismatch - -* object-rest/assignment-expression/input.js -x Output mismatch - -* object-rest/catch-clause/input.js -x Output mismatch - -* object-rest/duplicate-decl-bug/input.js -x Output mismatch - -* object-rest/export/input.mjs -x Output mismatch - -* object-rest/for-x/input.js -x Output mismatch - -* object-rest/for-x-array-pattern/input.js -x Output mismatch - -* object-rest/for-x-completion-record/input.js -x Output mismatch - -* object-rest/impure-computed/input.js -x Output mismatch - -* object-rest/nested/input.js -x Output mismatch - -* object-rest/nested-2/input.js -x Output mismatch - -* object-rest/nested-array/input.js -x Output mismatch - -* object-rest/nested-array-2/input.js -x Output mismatch - -* object-rest/nested-computed-key/input.js -x Output mismatch - -* object-rest/nested-default-value/input.js -x Output mismatch - -* object-rest/nested-literal-property/input.js -x Output mismatch - -* object-rest/nested-order/input.js -x Output mismatch - -* object-rest/non-string-computed/input.js -x Output mismatch - -* object-rest/null-destructuring/input.js -x Output mismatch - -* object-rest/object-ref-computed/input.js -x Output mismatch - -* object-rest/parameters/input.js -x Output mismatch - -* object-rest/parameters-object-rest-used-in-default/input.js -x Output mismatch - -* object-rest/remove-unused-excluded-keys-loose/input.js -x Output mismatch - -* object-rest/symbol/input.js -x Output mismatch - -* object-rest/template-literal-allLiterals-true-no-hoisting/input.js -x Output mismatch - -* object-rest/template-literal-property-allLiterals-false/input.js -x Output mismatch - -* object-rest/template-literal-property-allLiterals-true/input.js -x Output mismatch - -* object-rest/variable-destructuring/input.js -x Output mismatch - -* object-rest/with-array-rest/input.js -x Output mismatch - -* object-spread/expression/input.js -x Output mismatch - -* object-spread/side-effect/input.js -x Output mismatch - -* object-spread-loose/assignment/input.js -x Output mismatch - -* object-spread-loose/expression/input.js -x Output mismatch - -* object-spread-loose/parameters-object-rest-used-in-default/input.js -x Output mismatch - -* object-spread-loose/side-effect/input.js -x Output mismatch - -* object-spread-loose/variable-declaration/input.js -x Output mismatch - -* object-spread-loose-builtins/expression/input.js -x Output mismatch - -* object-spread-loose-builtins/side-effect/input.js -x Output mismatch - -* regression/gh-4904/input.js -x Output mismatch - -* regression/gh-5151/input.js -x Output mismatch - -* regression/gh-7304/input.mjs -x Output mismatch - -* regression/gh-7388/input.js -x Output mismatch - -* regression/gh-8323/input.js -x Output mismatch - - # babel-plugin-transform-async-to-generator (11/28) * assumption-ignoreFunctionLength-true/basic/input.mjs x Output mismatch @@ -572,7 +408,7 @@ rebuilt : ScopeId(1): [] x Output mismatch -# babel-plugin-transform-typescript (43/155) +# babel-plugin-transform-typescript (45/155) * cast/as-expression/input.ts Unresolved references mismatch: after transform: ["T", "x"] @@ -1206,12 +1042,6 @@ Unresolved reference IDs mismatch for "LongNameModule": after transform: [ReferenceId(1), ReferenceId(5)] rebuilt : [ReferenceId(1)] -* namespace/ambient-module-nested/input.ts -Ambient modules cannot be nested in other modules or namespaces. - -* namespace/ambient-module-nested-exported/input.ts -Ambient modules cannot be nested in other modules or namespaces. - * namespace/clobber-class/input.ts Missing SymbolId: "_A" Missing ReferenceId: "_A" @@ -2167,31 +1997,10 @@ after transform: ["T", "f"] rebuilt : ["f"] -# babel-plugin-transform-react-jsx (124/145) +# babel-plugin-transform-react-jsx (135/145) * autoImport/after-polyfills-compiled-to-cjs/input.mjs x Output mismatch -* pure/false-pragma-comment-automatic-runtime/input.js -pragma and pragmaFrag cannot be set when runtime is automatic. - -* pure/false-pragma-option-automatic-runtime/input.js -pragma and pragmaFrag cannot be set when runtime is automatic. - -* pure/true-pragma-comment-automatic-runtime/input.js -pragma and pragmaFrag cannot be set when runtime is automatic. - -* pure/true-pragma-option-automatic-runtime/input.js -pragma and pragmaFrag cannot be set when runtime is automatic. - -* pure/unset-pragma-comment-automatic-runtime/input.js -pragma and pragmaFrag cannot be set when runtime is automatic. - -* pure/unset-pragma-option-automatic-runtime/input.js -pragma and pragmaFrag cannot be set when runtime is automatic. - -* react/should-disallow-spread-children/input.js -Spread children are not supported in React. - * react/should-disallow-valueless-key/input.js ! Please provide an explicit key value. Using "key" as a shorthand for @@ -2225,18 +2034,9 @@ Spread children are not supported in React. `---- -* react/should-warn-when-importSource-is-set/input.js -importSource cannot be set when runtime is classic. - -* react/should-warn-when-importSource-pragma-is-set/input.js -importSource cannot be set when runtime is classic. - * react-automatic/does-not-add-source-self-automatic/input.mjs transform-react-jsx: unknown field `autoImport`, expected one of `runtime`, `development`, `throwIfNamespace`, `pure`, `importSource`, `pragma`, `pragmaFrag`, `useBuiltIns`, `useSpread`, `refresh` -* react-automatic/should-disallow-spread-children/input.js -Spread children are not supported in React. - * react-automatic/should-disallow-valueless-key/input.js ! Please provide an explicit key value. Using "key" as a shorthand for @@ -2270,9 +2070,6 @@ Spread children are not supported in React. `---- -* react-automatic/should-warn-when-pragma-or-pragmaFrag-is-set/input.js -pragma and pragmaFrag cannot be set when runtime is automatic. - * spread-transform/transform-to-babel-extend/input.js x Output mismatch diff --git a/tasks/transform_conformance/snapshots/babel_exec.snap.md b/tasks/transform_conformance/snapshots/babel_exec.snap.md index 293b58bda7efc..2509860738acc 100644 --- a/tasks/transform_conformance/snapshots/babel_exec.snap.md +++ b/tasks/transform_conformance/snapshots/babel_exec.snap.md @@ -11,9 +11,9 @@ Error: 'eval' and 'arguments' cannot be used as a binding identifier in strict m ❯ ssrTransformScript ../../node_modules/.pnpm/vite@5.4.8_@types+node@22.9.0/node_modules/vite/dist/node/chunks/dep-CDnG8rE7.js:52319:11 ❯ loadAndTransform ../../node_modules/.pnpm/vite@5.4.8_@types+node@22.9.0/node_modules/vite/dist/node/chunks/dep-CDnG8rE7.js:51917:72 -⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/14]⎯ +⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/12]⎯ -⎯⎯⎯⎯⎯⎯ Failed Tests 13 ⎯⎯⎯⎯⎯⎯⎯ +⎯⎯⎯⎯⎯⎯ Failed Tests 11 ⎯⎯⎯⎯⎯⎯⎯ FAIL fixtures/babel-plugin-transform-object-rest-spread-test-fixtures-assumption-objectRestNoSymbols-rest-ignore-symbols-exec.test.js > exec AssertionError: expected true to be false // Object.is equality @@ -31,7 +31,7 @@ AssertionError: expected true to be false // Object.is equality | ^ 13| }) -⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[2/14]⎯ +⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[2/12]⎯ FAIL fixtures/babel-plugin-transform-object-rest-spread-test-fixtures-assumption-pureGetters-rest-remove-unused-excluded-keys-exec.test.js > exec AssertionError: expected true to be false // Object.is equality @@ -49,7 +49,7 @@ AssertionError: expected true to be false // Object.is equality | ^ 11| }) -⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[3/14]⎯ +⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[3/12]⎯ FAIL fixtures/babel-plugin-transform-object-rest-spread-test-fixtures-assumption-pureGetters-spread-single-call-exec.test.js > exec AssertionError: expected { foo: +0, middle: 1, bar: 1 } to deeply equal { foo: +0, middle: +0, bar: 1 } @@ -64,39 +64,39 @@ AssertionError: expected { foo: +0, middle: 1, bar: 1 } to deeply equal { foo: + + "middle": 1, } - ❯ fixtures/babel-plugin-transform-object-rest-spread-test-fixtures-assumption-pureGetters-spread-single-call-exec.test.js:12:14 - 10| } }; - 11| let res = _objectSpread(_objectSpread(_objectSpread({}, withFoo), { m… - 12| expect(res).toEqual({ + ❯ fixtures/babel-plugin-transform-object-rest-spread-test-fixtures-assumption-pureGetters-spread-single-call-exec.test.js:13:14 + 11| } }; + 12| let res = _objectSpread(_objectSpread(_objectSpread({}, withFoo), { m… + 13| expect(res).toEqual({ | ^ - 13| foo: 0, - 14| middle: 0, + 14| foo: 0, + 15| middle: 0, -⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[4/14]⎯ +⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[4/12]⎯ FAIL fixtures/babel-plugin-transform-object-rest-spread-test-fixtures-assumption-setSpreadProperties-no-object-assign-exec-exec.test.js > exec AssertionError: expected [Function] to throw an error - ❯ fixtures/babel-plugin-transform-object-rest-spread-test-fixtures-assumption-setSpreadProperties-no-object-assign-exec-exec.test.js:13:5 - 11| expect(() => { - 12| const objSpread = _objectSpread({}, obj); - 13| }).toThrow(); + ❯ fixtures/babel-plugin-transform-object-rest-spread-test-fixtures-assumption-setSpreadProperties-no-object-assign-exec-exec.test.js:14:5 + 12| expect(() => { + 13| const objSpread = _objectSpread({}, obj); + 14| }).toThrow(); | ^ - 14| const obj2 = { "NOWRITE": 456 }; - 15| expect(() => { + 15| const obj2 = { "NOWRITE": 456 }; + 16| expect(() => { -⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[5/14]⎯ +⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[5/12]⎯ FAIL fixtures/babel-plugin-transform-object-rest-spread-test-fixtures-assumption-setSpreadProperties-with-useBuiltIns-no-object-assign-exec-exec.test.js > exec AssertionError: expected [Function] to throw an error - ❯ fixtures/babel-plugin-transform-object-rest-spread-test-fixtures-assumption-setSpreadProperties-with-useBuiltIns-no-object-assign-exec-exec.test.js:13:5 - 11| expect(() => { - 12| const objSpread = _objectSpread({}, obj); - 13| }).toThrow(); + ❯ fixtures/babel-plugin-transform-object-rest-spread-test-fixtures-assumption-setSpreadProperties-with-useBuiltIns-no-object-assign-exec-exec.test.js:14:5 + 12| expect(() => { + 13| const objSpread = _objectSpread({}, obj); + 14| }).toThrow(); | ^ - 14| const obj2 = { "NOWRITE": 456 }; - 15| expect(() => { + 15| const obj2 = { "NOWRITE": 456 }; + 16| expect(() => { -⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[6/14]⎯ +⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[6/12]⎯ FAIL fixtures/babel-plugin-transform-object-rest-spread-test-fixtures-object-spread-expression-exec.test.js > exec AssertionError: expected [ 1, 2 ] to deeply equal [ 1 ] @@ -109,14 +109,14 @@ AssertionError: expected [ 1, 2 ] to deeply equal [ 1 ] + 2, ] - ❯ fixtures/babel-plugin-transform-object-rest-spread-test-fixtures-object-spread-expression-exec.test.js:10:14 - 8| log.push(2); - 9| } }); - 10| expect(log).toEqual([1]); + ❯ fixtures/babel-plugin-transform-object-rest-spread-test-fixtures-object-spread-expression-exec.test.js:11:14 + 9| log.push(2); + 10| } }); + 11| expect(log).toEqual([1]); | ^ - 11| }) + 12| }) -⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[7/14]⎯ +⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[7/12]⎯ FAIL fixtures/babel-plugin-transform-object-rest-spread-test-fixtures-object-spread-loose-builtins-side-effect-exec.test.js > exec AssertionError: expected { a: 1, b: 1 } to deeply equal { a: 2, b: 1 } @@ -138,7 +138,7 @@ AssertionError: expected { a: 1, b: 1 } to deeply equal { a: 2, b: 1 } 10| a: 2, 11| b: 1 -⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[8/14]⎯ +⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[8/12]⎯ FAIL fixtures/babel-plugin-transform-object-rest-spread-test-fixtures-object-spread-loose-side-effect-exec.test.js > exec AssertionError: expected { a: 1, b: 1 } to deeply equal { a: 2, b: 1 } @@ -160,31 +160,7 @@ AssertionError: expected { a: 1, b: 1 } to deeply equal { a: 2, b: 1 } 10| a: 2, 11| b: 1 -⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[9/14]⎯ - - FAIL fixtures/babel-plugin-transform-react-jsx-source-test-fixtures-react-source-basic-sample-exec.test.js > exec -ReferenceError: transformAsync is not defined - ❯ fixtures/babel-plugin-transform-react-jsx-source-test-fixtures-react-source-basic-sample-exec.test.js:4:16 - 2| - 3| test("exec", () => { - 4| var actualP = transformAsync("var x = ", Object.assign({},… - | ^ - 5| var expected = ` - 6| var _jsxFileName = "/fake/path/mock.js"; - -⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[10/14]⎯ - - FAIL fixtures/babel-plugin-transform-react-jsx-source-test-fixtures-react-source-with-source-exec.test.js > exec -ReferenceError: transformAsync is not defined - ❯ fixtures/babel-plugin-transform-react-jsx-source-test-fixtures-react-source-with-source-exec.test.js:4:16 - 2| - 3| test("exec", () => { - 4| var actualP = transformAsync("var x = … - | ^ - 5| var expected = "var x = ;"; - 6| return actualP.then((actual) => { - -⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[11/14]⎯ +⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[9/12]⎯ FAIL fixtures/babel-preset-env-test-fixtures-plugins-integration-issue-15170-exec.test.js > exec AssertionError: expected [Function] to not throw an error but 'ReferenceError: x is not defined' was thrown @@ -202,7 +178,7 @@ undefined | ^ 7| }) -⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[12/14]⎯ +⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[10/12]⎯ FAIL fixtures/babel-preset-env-test-fixtures-sanity-check-es2015-constants-exec.test.js > exec TypeError: Assignment to constant variable. @@ -213,7 +189,7 @@ TypeError: Assignment to constant variable. | ^ 6| }) -⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[13/14]⎯ +⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[11/12]⎯ FAIL fixtures/babel-preset-env-test-fixtures-sanity-regex-dot-all-exec.test.js > exec AssertionError: expected false to be true // Object.is equality @@ -232,5 +208,5 @@ AssertionError: expected false to be true // Object.is equality 11| expect(/hello.world/su.test(input)).toBe(true); 12| }) -⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[14/14]⎯ +⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[12/12]⎯ diff --git a/tasks/transform_conformance/snapshots/oxc_exec.snap.md b/tasks/transform_conformance/snapshots/oxc_exec.snap.md index 3c698c22b6527..292cdaf7be6a0 100644 --- a/tasks/transform_conformance/snapshots/oxc_exec.snap.md +++ b/tasks/transform_conformance/snapshots/oxc_exec.snap.md @@ -1,8 +1,8 @@ commit: d20b314c -Passed: 0/0 - -# All Passed: - - +node: v22.11.0 +filter: fixtures +include: **/*.{test,spec}.?(c|m)[jt]s?(x) +exclude: **/node_modules/**, **/dist/**, **/cypress/**, **/.{idea,git,cache,output,temp}/**, **/{karma,rollup,webpack,vite,vitest,jest,ava,babel,nyc,cypress,tsup,build,eslint,prettier}.config.*, "" +No test files found, exiting with code 1 diff --git a/tasks/transform_conformance/src/constants.rs b/tasks/transform_conformance/src/constants.rs index 3eaf32940804f..d88637b422ad9 100644 --- a/tasks/transform_conformance/src/constants.rs +++ b/tasks/transform_conformance/src/constants.rs @@ -102,3 +102,6 @@ pub const SKIP_TESTS: &[&str] = &[ "babel-preset-env/test/fixtures/debug", "babel-preset-env/test/fixtures/debug-babel-7", ]; + +pub const SNAPSHOT_TESTS: &[&str] = + &["babel-plugin-transform-object-rest-spread", "babel-plugin-transform-optional-chaining"]; diff --git a/tasks/transform_conformance/src/lib.rs b/tasks/transform_conformance/src/lib.rs index 7d5a1160f3bfc..0453232095c9b 100644 --- a/tasks/transform_conformance/src/lib.rs +++ b/tasks/transform_conformance/src/lib.rs @@ -75,59 +75,61 @@ impl TestRunner { (packages_root(), CONFORMANCE_SNAPSHOT, EXEC_SNAPSHOT), (oxc_test_root(), OXC_CONFORMANCE_SNAPSHOT, OXC_EXEC_SNAPSHOT), ] { - let (transform_paths, exec_files) = - Self::glob_files(root, self.options.filter.as_ref()); - self.generate_snapshot(root, &snap_root().join(snapshot), transform_paths); - - if self.options.exec && !exec_files.is_empty() { + if self.options.exec { let fixture_root = fixture_root(); let _ = fs::remove_dir_all(&fixture_root); let _ = fs::create_dir(&fixture_root); - let dest = snap_root().join(exec_snapshot); - self.generate_snapshot(root, &dest, exec_files); - self.run_vitest(&dest); + } + let transform_paths = Self::generate_test_cases(root, self.options.filter.as_ref()); + self.generate_snapshot(root, &snap_root().join(snapshot), transform_paths); + if self.options.exec { + self.run_vitest(&snap_root().join(exec_snapshot)); } } } - fn glob_files( + fn generate_test_cases( root: &Path, filter: Option<&String>, - ) -> (IndexMap>, IndexMap>) { + ) -> IndexMap> { let cwd = root.parent().unwrap_or(root); // use `IndexMap` to keep the order of the test cases the same in insert order. let mut transform_files = IndexMap::>::new(); - let mut exec_files = IndexMap::>::new(); for case in PLUGINS { let root = root.join(case).join("test/fixtures"); - let (mut transform_paths, mut exec_paths): (Vec, Vec) = - WalkDir::new(root) - .into_iter() - .filter_map(Result::ok) - .filter_map(|e| { - let path = e.path(); - if let Some(filter) = filter { - if !path.to_string_lossy().contains(filter) { - return None; - } + + let mut cases = WalkDir::new(root) + .into_iter() + .filter_map(Result::ok) + .filter(|e| { + if let Some(filter) = filter { + if !e.path().to_string_lossy().contains(filter) { + return false; } - TestCase::new(cwd, path).filter(|test_case| !test_case.skip_test_case()) - }) - .partition(|case| case.kind == TestCaseKind::Conformance); + } + true + }) + .filter_map(|e| TestCase::new(cwd, e.path())) + .filter(|test_case| !test_case.skip_test_case()) + .map(|mut case| { + case.test(filter.is_some()); + case + }) + .collect::>(); - transform_paths.sort_unstable_by(|a, b| a.path.cmp(&b.path)); - exec_paths.sort_unstable_by(|a, b| a.path.cmp(&b.path)); + cases.sort_unstable_by(|a, b| a.path.cmp(&b.path)); - if !transform_paths.is_empty() { - transform_files.insert((*case).to_string(), transform_paths); - } - if !exec_paths.is_empty() { - exec_files.insert((*case).to_string(), exec_paths); + let transform_cases = cases + .into_iter() + .filter(|case| case.kind == TestCaseKind::Conformance) + .collect::>(); + if !transform_cases.is_empty() { + transform_files.insert((*case).to_string(), transform_cases); } } - (transform_files, exec_files) + transform_files } fn generate_snapshot(&self, root: &Path, dest: &Path, paths: IndexMap>) { @@ -142,13 +144,8 @@ impl TestRunner { total += num_of_tests; // Run the test - let (passed, failed): (Vec, Vec) = test_cases - .into_iter() - .map(|mut test_case| { - test_case.test(self.options.filter.is_some()); - test_case - }) - .partition(|test_case| test_case.errors.is_empty()); + let (passed, failed): (Vec, Vec) = + test_cases.into_iter().partition(|test_case| test_case.errors.is_empty()); all_passed_count += passed.len(); // Snapshot diff --git a/tasks/transform_conformance/src/test_case.rs b/tasks/transform_conformance/src/test_case.rs index 3b8063826c28c..8307faf9ae9c3 100644 --- a/tasks/transform_conformance/src/test_case.rs +++ b/tasks/transform_conformance/src/test_case.rs @@ -16,7 +16,7 @@ use oxc::{ use oxc_tasks_common::{normalize_path, print_diff_in_terminal, project_root}; use crate::{ - constants::{PLUGINS_NOT_SUPPORTED_YET, SKIP_TESTS}, + constants::{PLUGINS_NOT_SUPPORTED_YET, SKIP_TESTS, SNAPSHOT_TESTS}, driver::Driver, fixture_root, oxc_test_root, packages_root, }; @@ -25,8 +25,9 @@ use crate::{ pub struct TestCase { pub kind: TestCaseKind, pub path: PathBuf, - pub options: BabelOptions, - pub transform_options: Result>, + options: BabelOptions, + source_type: SourceType, + transform_options: Result>, pub errors: Vec, } @@ -34,6 +35,7 @@ pub struct TestCase { pub enum TestCaseKind { Conformance, Exec, + Snapshot, } impl TestCase { @@ -54,18 +56,44 @@ impl TestCase { TestCaseKind::Exec } // named `input.[ext]` or `input.d.ts` - else if (path.file_stem().is_some_and(|name| name == "input") - && path - .extension() - .is_some_and(|ext| VALID_EXTENSIONS.contains(&ext.to_str().unwrap()))) - || path.file_name().is_some_and(|name| name == "input.d.ts") + else if path.file_stem().is_some_and(|name| name == "input" || name == "input.d") + && path.extension().is_some_and(|ext| VALID_EXTENSIONS.contains(&ext.to_str().unwrap())) { - TestCaseKind::Conformance + if path + .strip_prefix(packages_root()) + .is_ok_and(|p| SNAPSHOT_TESTS.iter().any(|t| p.to_string_lossy().starts_with(t))) + { + TestCaseKind::Snapshot + } else { + TestCaseKind::Conformance + } } else { return None; }; - Some(Self { kind, path, options, transform_options, errors }) + let source_type = Self::source_type(&path, &options); + + Some(Self { kind, path, options, source_type, transform_options, errors }) + } + + fn source_type(path: &Path, options: &BabelOptions) -> SourceType { + // Some babel test cases have a js extension, but contain typescript code. + // Therefore, if the typescript plugin exists, enable typescript. + let mut source_type = SourceType::from_path(path) + .unwrap() + .with_script(true) + .with_jsx(options.plugins.syntax_jsx); + source_type = match options.source_type.as_deref() { + Some("unambiguous") => source_type.with_unambiguous(true), + Some("script") => source_type.with_script(true), + Some("module") => source_type.with_module(true), + Some(s) => panic!("Unexpected source type {s}"), + None => source_type, + }; + source_type = source_type.with_typescript( + options.plugins.typescript.is_some() || options.plugins.syntax_typescript.is_some(), + ); + source_type } pub fn skip_test_case(&self) -> bool { @@ -131,33 +159,42 @@ impl TestCase { false } - fn transform(&self, path: &Path) -> Result { + fn transform(&self, mode: HelperLoaderMode) -> Result { + let path = &self.path; let transform_options = match &self.transform_options { Ok(transform_options) => transform_options, Err(json_err) => { - return Err(OxcDiagnostic::error(format!("{json_err:?}"))); + let error = json_err.iter().map(ToString::to_string).collect::>().join("\n"); + return Err(error); } }; let source_text = fs::read_to_string(path).unwrap(); - // Some babel test cases have a js extension, but contain typescript code. - // Therefore, if the typescript plugin exists, enable typescript. - let source_type = SourceType::from_path(path).unwrap().with_typescript( - self.options.plugins.syntax_typescript.is_some() - || self.options.plugins.typescript.is_some(), - ); - + let project_root = project_root(); let mut options = transform_options.clone(); - options.helper_loader.mode = HelperLoaderMode::Runtime; - let driver = Driver::new(false, options).execute(&source_text, source_type, path); - Ok(driver) + options.helper_loader.mode = mode; + let mut driver = Driver::new(false, options).execute(&source_text, self.source_type, path); + let errors = driver.errors(); + if !errors.is_empty() { + let source = NamedSource::new( + path.strip_prefix(project_root).unwrap().to_string_lossy(), + source_text.to_string(), + ); + return Err(errors + .into_iter() + .map(|err| format!("{:?}", err.with_source_code(source.clone()))) + .collect::>() + .join("\n")); + } + Ok(driver.printed()) } pub fn test(&mut self, filtered: bool) { match self.kind { TestCaseKind::Conformance => self.test_conformance(filtered), TestCaseKind::Exec => self.test_exec(filtered), + TestCaseKind::Snapshot => {} } } @@ -172,61 +209,22 @@ impl TestCase { let allocator = Allocator::default(); let input = fs::read_to_string(&self.path).unwrap(); - let source_type = { - let mut source_type = SourceType::from_path(&self.path) - .unwrap() - .with_script(true) - .with_jsx(self.options.plugins.syntax_jsx); - - source_type = match self.options.source_type.as_deref() { - Some("unambiguous") => source_type.with_unambiguous(true), - Some("script") => source_type.with_script(true), - Some("module") => source_type.with_module(true), - Some(s) => panic!("Unexpected source type {s}"), - None => source_type, - }; - - source_type = source_type.with_typescript( - self.options.plugins.typescript.is_some() - || self.options.plugins.syntax_typescript.is_some(), - ); - - source_type - }; - if filtered { println!("input_path: {:?}", &self.path); println!("output_path: {output_path:?}"); } - let project_root = project_root(); let mut transformed_code = String::new(); let mut actual_errors = None; let mut transform_options = None; - match &self.transform_options { - Err(json_err) => { - let error = json_err.iter().map(ToString::to_string).collect::>().join("\n"); + match self.transform(HelperLoaderMode::External) { + Err(error) => { actual_errors.replace(get_babel_error(&error)); } - Ok(options) => { - transform_options.replace(options.clone()); - let mut driver = - Driver::new(false, options.clone()).execute(&input, source_type, &self.path); - transformed_code = driver.printed(); - let errors = driver.errors(); - if !errors.is_empty() { - let source = NamedSource::new( - self.path.strip_prefix(project_root).unwrap().to_string_lossy(), - input.to_string(), - ); - let error = errors - .into_iter() - .map(|err| format!("{:?}", err.with_source_code(source.clone()))) - .collect::>() - .join("\n"); - actual_errors.replace(get_babel_error(&error)); - } + Ok(code) => { + transform_options.replace(self.transform_options.as_ref().unwrap().clone()); + transformed_code = code; } } @@ -243,7 +241,7 @@ impl TestCase { String::default, |output| { // Get expected code by parsing the source text, so we can get the same code generated result. - let ret = Parser::new(&allocator, &output, source_type) + let ret = Parser::new(&allocator, &output, self.source_type) .with_options(ParseOptions { // Related: async to generator, regression allow_return_outside_function: true, @@ -309,7 +307,7 @@ impl TestCase { if let Some(options) = transform_options { let mismatch_errors = Driver::new(/* check transform mismatch */ true, options) - .execute(&input, source_type, &self.path) + .execute(&input, self.source_type, &self.path) .errors(); self.errors.extend(mismatch_errors); } @@ -324,8 +322,8 @@ impl TestCase { println!("Input:\n{}\n", fs::read_to_string(&self.path).unwrap()); } - let result = match self.transform(&self.path) { - Ok(mut driver) => driver.printed(), + let result = match self.transform(HelperLoaderMode::Runtime) { + Ok(code) => code, Err(error) => { if filtered { println!("Transform Errors:\n{error:?}\n",);