From be58efe708f4bb406e4cedce6f6a1e9dfb8b2009 Mon Sep 17 00:00:00 2001 From: Romeo Fragomeli Date: Tue, 8 Oct 2024 10:00:17 +0200 Subject: [PATCH] [IMP] Bump support for Node 18+ This commit bump the support for Node 18+. Some tests was adapted due to some change in Error Handling in V8 (NodeJS v20+) --- .github/workflows/deploy.yml | 2 +- package.json | 2 +- tests/compiler/validation.test.ts | 28 ++++- tests/components/error_handling.test.ts | 145 ++++++++++++++++++------ tests/helpers.ts | 11 ++ 5 files changed, 151 insertions(+), 37 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 70843f37b..fd60db9ff 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -14,7 +14,7 @@ jobs: strategy: matrix: - node-version: [12.x, 14.x, 16.x] + node-version: [18.x, 20.x, 22.x] steps: - uses: actions/checkout@v2 diff --git a/package.json b/package.json index 3a4bc45f4..5c3ad4a2b 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "dist" ], "engines": { - "node": ">=12.18.3" + "node": ">=18.0.0" }, "scripts": { "build:bundle": "rollup -c --failAfterWarnings", diff --git a/tests/compiler/validation.test.ts b/tests/compiler/validation.test.ts index 01ded3569..9dbcf8773 100644 --- a/tests/compiler/validation.test.ts +++ b/tests/compiler/validation.test.ts @@ -1,5 +1,12 @@ import { TemplateSet } from "../../src/runtime/template_set"; -import { renderToString, snapshotTemplate, TestContext } from "../helpers"; +import { + isNode20Plus, + isNotNode20Plus, + renderToString, + snapshotTemplate, + TestContext, + testIf, +} from "../helpers"; // ----------------------------------------------------------------------------- // basic validation @@ -45,11 +52,28 @@ describe("basic validation", () => { expect(() => renderToString(template)).toThrow("Unknown QWeb directive: 't-best-beer'"); }); - test("compilation error", () => { + testIf(isNotNode20Plus, "compilation error (NodeJS < 20)", () => { const template = `
test
`; expect(() => renderToString(template)) .toThrow(`Failed to compile anonymous template: Unexpected identifier +generated code: +function(app, bdom, helpers) { + let { text, createBlock, list, multi, html, toggler, comment } = bdom; + + let block1 = createBlock(\`
test
\`); + + return function template(ctx, node, key = "") { + let attr1 = ctx['a']ctx['b']; + return block1([attr1]); + } +}`); + }); + testIf(isNode20Plus, "compilation error (NodeJS 20+)", () => { + const template = `
test
`; + expect(() => renderToString(template)) + .toThrow(`Failed to compile anonymous template: Unexpected identifier 'ctx' + generated code: function(app, bdom, helpers) { let { text, createBlock, list, multi, html, toggler, comment } = bdom; diff --git a/tests/components/error_handling.test.ts b/tests/components/error_handling.test.ts index 24a178f88..ef524c560 100644 --- a/tests/components/error_handling.test.ts +++ b/tests/components/error_handling.test.ts @@ -20,6 +20,9 @@ import { useLogLifecycle, nextAppError, steps, + testIf, + isNotNode20Plus, + isNode20Plus, } from "../helpers"; import { OwlError } from "../../src/common/owl_error"; @@ -144,20 +147,23 @@ describe("basics", () => { ); }); - test("display a nice error if the root component template fails to compile", async () => { - // This is a special case: mount throws synchronously and we don't have any - // node which can handle the error, hence the different structure of this test - class Comp extends Component { - static template = xml`
test
`; - } - const app = new App(Comp); - let error: Error; - try { - await app.mount(fixture); - } catch (e) { - error = e as Error; - } - const expectedErrorMessage = `Failed to compile anonymous template: Unexpected identifier + testIf( + isNotNode20Plus, + "display a nice error if the root component template fails to compile", + async () => { + // This is a special case: mount throws synchronously and we don't have any + // node which can handle the error, hence the different structure of this test + class Comp extends Component { + static template = xml`
test
`; + } + const app = new App(Comp); + let error: Error; + try { + await app.mount(fixture); + } catch (e) { + error = e as Error; + } + const expectedErrorMessage = `Failed to compile anonymous template: Unexpected identifier generated code: function(app, bdom, helpers) { @@ -170,19 +176,57 @@ function(app, bdom, helpers) { return block1([attr1]); } }`; - expect(error!).toBeDefined(); - expect(error!.message).toBe(expectedErrorMessage); - }); + expect(error!).toBeDefined(); + expect(error!.message).toBe(expectedErrorMessage); + } + ); + + testIf( + isNode20Plus, + "display a nice error if the root component template fails to compile", + async () => { + // This is a special case: mount throws synchronously and we don't have any + // node which can handle the error, hence the different structure of this test + class Comp extends Component { + static template = xml`
test
`; + } + const app = new App(Comp); + let error: Error; + try { + await app.mount(fixture); + } catch (e) { + error = e as Error; + } + const expectedErrorMessage = `Failed to compile anonymous template: Unexpected identifier 'ctx' - test("display a nice error if a non-root component template fails to compile", async () => { - class Child extends Component { - static template = xml`
test
`; - } - class Parent extends Component { - static components = { Child }; - static template = xml``; +generated code: +function(app, bdom, helpers) { + let { text, createBlock, list, multi, html, toggler, comment } = bdom; + + let block1 = createBlock(\`
test
\`); + + return function template(ctx, node, key = "") { + let attr1 = ctx['a']ctx['b']; + return block1([attr1]); + } +}`; + expect(error!).toBeDefined(); + expect(error!.message).toBe(expectedErrorMessage); } - const expectedErrorMessage = `Failed to compile anonymous template: Unexpected identifier + ); + + testIf( + isNotNode20Plus, + "display a nice error if a non-root component template fails to compile", + async () => { + class Child extends Component { + static template = xml`
test
`; + } + class Parent extends Component { + static components = { Child }; + static template = xml``; + } + const expectedErrorMessage = `Failed to compile anonymous template: Unexpected identifier generated code: function(app, bdom, helpers) { @@ -195,14 +239,49 @@ function(app, bdom, helpers) { return block1([attr1]); } }`; - const app = new App(Parent as typeof Component); - let error: Error; - const mountProm = app.mount(fixture).catch((e: Error) => (error = e)); - await expect(nextAppError(app)).resolves.toThrow(expectedErrorMessage); - await mountProm; - expect(error!).toBeDefined(); - expect(error!.message).toBe(expectedErrorMessage); - }); + const app = new App(Parent as typeof Component); + let error: Error; + const mountProm = app.mount(fixture).catch((e: Error) => (error = e)); + await expect(nextAppError(app)).resolves.toThrow(expectedErrorMessage); + await mountProm; + expect(error!).toBeDefined(); + expect(error!.message).toBe(expectedErrorMessage); + } + ); + + testIf( + isNode20Plus, + "display a nice error if a non-root component template fails to compile", + async () => { + class Child extends Component { + static template = xml`
test
`; + } + class Parent extends Component { + static components = { Child }; + static template = xml``; + } + const expectedErrorMessage = `Failed to compile anonymous template: Unexpected identifier 'ctx' + +generated code: +function(app, bdom, helpers) { + let { text, createBlock, list, multi, html, toggler, comment } = bdom; + + let block1 = createBlock(\`
test
\`); + + return function template(ctx, node, key = "") { + let attr1 = ctx['a']ctx['b']; + return block1([attr1]); + } +}`; + const app = new App(Parent as typeof Component); + let error: Error; + const mountProm = app.mount(fixture).catch((e: Error) => (error = e)); + await expect(nextAppError(app)).resolves.toThrow(expectedErrorMessage); + await mountProm; + expect(error!).toBeDefined(); + expect(error!.message).toBe(expectedErrorMessage); + } + ); test("simple catchError", async () => { class Boom extends Component { diff --git a/tests/helpers.ts b/tests/helpers.ts index 377d99531..ec9d7326d 100644 --- a/tests/helpers.ts +++ b/tests/helpers.ts @@ -275,6 +275,17 @@ export function nextAppError(app: any) { }); } +export function testIf(predicate: Function, testName: string, testFn?: jest.ProvidesCallback) { + if (predicate()) { + test(testName, testFn); + } else { + test.skip(testName, testFn); + } +} + +export const isNode20Plus = () => Number(process.versions.node.split(".")[0]) >= 20; +export const isNotNode20Plus = () => !isNode20Plus(); + declare global { namespace jest { interface Matchers {