diff --git a/src/runtime/app.ts b/src/runtime/app.ts index 736f221d..b499dd40 100644 --- a/src/runtime/app.ts +++ b/src/runtime/app.ts @@ -151,7 +151,13 @@ export class App< } else { // new component if (isStatic) { - C = parent.constructor.components[name as any]; + const components = parent.constructor.components; + if (!components) { + throw new OwlError( + `Cannot find the definition of component "${name}", missing static components key in parent` + ); + } + C = components[name as any]; if (!C) { throw new OwlError(`Cannot find the definition of component "${name}"`); } else if (!(C.prototype instanceof Component)) { diff --git a/tests/components/__snapshots__/error_handling.test.ts.snap b/tests/components/__snapshots__/error_handling.test.ts.snap index 92fc7779..0716d793 100644 --- a/tests/components/__snapshots__/error_handling.test.ts.snap +++ b/tests/components/__snapshots__/error_handling.test.ts.snap @@ -38,6 +38,21 @@ exports[`basics display a nice error if it cannot find component 1`] = ` }" `; +exports[`basics display a nice error if the components key is missing with subcomponents 1`] = ` +"function anonymous(app, bdom, helpers +) { + let { text, createBlock, list, multi, html, toggler, comment } = bdom; + const comp1 = app.createComponent(\`MissingChild\`, true, false, false, true); + + let block1 = createBlock(\`
\`); + + return function template(ctx, node, key = \\"\\") { + const b2 = comp1({}, key + \`__1\`, node, this, null); + return block1([], [b2]); + } +}" +`; + exports[`basics no component catching error lead to full app destruction 1`] = ` "function anonymous(app, bdom, helpers ) { diff --git a/tests/components/error_handling.test.ts b/tests/components/error_handling.test.ts index 8a7e0d07..e78230e3 100644 --- a/tests/components/error_handling.test.ts +++ b/tests/components/error_handling.test.ts @@ -126,6 +126,23 @@ describe("basics", () => { ); }); + test("display a nice error if the components key is missing with subcomponents", async () => { + class Parent extends Component { + static template = xml`
`; + } + 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( + 'Cannot find the definition of component "MissingChild", missing static components key in parent' + ); + await mountProm; + expect(error!).toBeDefined(); + expect(error!.message).toBe( + 'Cannot find the definition of component "MissingChild", missing static components key in parent' + ); + }); + test("simple catchError", async () => { class Boom extends Component { static template = xml`
`;