From 98b58b505bebcbb7c8d80f88616abd28c015cb69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9ry=20Debongnie?= Date: Sun, 22 May 2022 11:15:57 +0200 Subject: [PATCH] [IMP] app: add setting to warn if no static props object This can be helpful to track components that miss a static prop description. closes #1191 --- doc/reference/app.md | 2 ++ src/app/app.ts | 5 ++++- src/app/template_helpers.ts | 3 +++ tests/app/__snapshots__/app.test.ts.snap | 14 ++++++++++++++ tests/app/app.test.ts | 19 ++++++++++++++++++- 5 files changed, 41 insertions(+), 2 deletions(-) diff --git a/doc/reference/app.md b/doc/reference/app.md index 0e189db1..31a4d059 100644 --- a/doc/reference/app.md +++ b/doc/reference/app.md @@ -61,6 +61,8 @@ The `config` object is an object with some of the following keys: templates (see [translations](translations.md)) - **`templates (string | xml document)`**: all the templates that will be used by the components created by the application. +- **`warnIfNoStaticProps (boolean, default=false)`**: if true, Owl will log a warning + whenever it encounters a component that does not provide a [static props description](props.md#props-validation). ## `mount` helper diff --git a/src/app/app.ts b/src/app/app.ts index cc5fcdff..b1a93777 100644 --- a/src/app/app.ts +++ b/src/app/app.ts @@ -16,6 +16,7 @@ export interface AppConfig extends TemplateSetConfig { props?: P; env?: E; test?: boolean; + warnIfNoStaticProps?: boolean; } let hasBeenLogged = false; @@ -41,6 +42,7 @@ export class App< env: E; scheduler = new Scheduler(); root: ComponentNode | null = null; + warnIfNoStaticProps: boolean; constructor(Root: ComponentConstructor, config: AppConfig = {}) { super(config); @@ -48,6 +50,7 @@ export class App< if (config.test) { this.dev = true; } + this.warnIfNoStaticProps = config.warnIfNoStaticProps || false; if (this.dev && !config.test && !hasBeenLogged) { console.info(DEV_MSG()); hasBeenLogged = true; @@ -61,7 +64,7 @@ export class App< mount(target: HTMLElement, options?: MountOptions): Promise & InstanceType> { App.validateTarget(target); if (this.dev) { - this.helpers.validateProps(this.Root, this.props); + this.helpers.validateProps(this.Root, this.props, { __owl__: { app: this } }); } const node = this.makeNode(this.Root, this.props); const prom = this.mountNode(node, target, options); diff --git a/src/app/template_helpers.ts b/src/app/template_helpers.ts index 6653d8a7..ddac172c 100644 --- a/src/app/template_helpers.ts +++ b/src/app/template_helpers.ts @@ -203,6 +203,9 @@ export function validateProps

(name: string | ComponentConstructor

, props: const schema = ComponentClass.props; if (!schema) { + if (parent.__owl__.app.warnIfNoStaticProps) { + console.warn(`Component '${ComponentClass.name}' does not have a static props description`); + } return; } const defaultProps = ComponentClass.defaultProps; diff --git a/tests/app/__snapshots__/app.test.ts.snap b/tests/app/__snapshots__/app.test.ts.snap index eb49badc..6945d47a 100644 --- a/tests/app/__snapshots__/app.test.ts.snap +++ b/tests/app/__snapshots__/app.test.ts.snap @@ -41,3 +41,17 @@ exports[`app destroy remove the widget from the DOM 1`] = ` } }" `; + +exports[`app warnIfNoStaticProps works as expected 1`] = ` +"function anonymous(bdom, helpers +) { + let { text, createBlock, list, multi, html, toggler, component, comment } = bdom; + + let block1 = createBlock(\`

\`); + + return function template(ctx, node, key = \\"\\") { + let txt1 = ctx['message']; + return block1([txt1]); + } +}" +`; diff --git a/tests/app/app.test.ts b/tests/app/app.test.ts index 70c69314..d7701e9c 100644 --- a/tests/app/app.test.ts +++ b/tests/app/app.test.ts @@ -1,4 +1,4 @@ -import { App, Component, xml } from "../../src"; +import { App, Component, mount, xml } from "../../src"; import { status } from "../../src/component/status"; import { makeTestFixture, snapshotEverything, nextTick, elem } from "../helpers"; @@ -59,4 +59,21 @@ describe("app", () => { await app.mount(fixture); expect(fixture.innerHTML).toBe("
333
"); }); + + test("warnIfNoStaticProps works as expected", async () => { + let originalconsoleWarn = console.warn; + let mockConsoleWarn = jest.fn(() => {}); + console.warn = mockConsoleWarn; + + class Root extends Component { + static template = xml`
`; + } + + await mount(Root, fixture, { dev: true, props: { messge: "hey" }, warnIfNoStaticProps: true }); + + console.warn = originalconsoleWarn; + expect(mockConsoleWarn).toBeCalledWith( + "Component 'Root' does not have a static props description" + ); + }); });