[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
This commit is contained in:
Géry Debongnie
2022-05-22 11:15:57 +02:00
parent 586033fd95
commit 98b58b505b
5 changed files with 41 additions and 2 deletions
+2
View File
@@ -61,6 +61,8 @@ The `config` object is an object with some of the following keys:
templates (see [translations](translations.md)) templates (see [translations](translations.md))
- **`templates (string | xml document)`**: all the templates that will be used by - **`templates (string | xml document)`**: all the templates that will be used by
the components created by the application. 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 ## `mount` helper
+4 -1
View File
@@ -16,6 +16,7 @@ export interface AppConfig<P, E> extends TemplateSetConfig {
props?: P; props?: P;
env?: E; env?: E;
test?: boolean; test?: boolean;
warnIfNoStaticProps?: boolean;
} }
let hasBeenLogged = false; let hasBeenLogged = false;
@@ -41,6 +42,7 @@ export class App<
env: E; env: E;
scheduler = new Scheduler(); scheduler = new Scheduler();
root: ComponentNode<P, E> | null = null; root: ComponentNode<P, E> | null = null;
warnIfNoStaticProps: boolean;
constructor(Root: ComponentConstructor<P, E>, config: AppConfig<P, E> = {}) { constructor(Root: ComponentConstructor<P, E>, config: AppConfig<P, E> = {}) {
super(config); super(config);
@@ -48,6 +50,7 @@ export class App<
if (config.test) { if (config.test) {
this.dev = true; this.dev = true;
} }
this.warnIfNoStaticProps = config.warnIfNoStaticProps || false;
if (this.dev && !config.test && !hasBeenLogged) { if (this.dev && !config.test && !hasBeenLogged) {
console.info(DEV_MSG()); console.info(DEV_MSG());
hasBeenLogged = true; hasBeenLogged = true;
@@ -61,7 +64,7 @@ export class App<
mount(target: HTMLElement, options?: MountOptions): Promise<Component<P, E> & InstanceType<T>> { mount(target: HTMLElement, options?: MountOptions): Promise<Component<P, E> & InstanceType<T>> {
App.validateTarget(target); App.validateTarget(target);
if (this.dev) { 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 node = this.makeNode(this.Root, this.props);
const prom = this.mountNode(node, target, options); const prom = this.mountNode(node, target, options);
+3
View File
@@ -203,6 +203,9 @@ export function validateProps<P>(name: string | ComponentConstructor<P>, props:
const schema = ComponentClass.props; const schema = ComponentClass.props;
if (!schema) { if (!schema) {
if (parent.__owl__.app.warnIfNoStaticProps) {
console.warn(`Component '${ComponentClass.name}' does not have a static props description`);
}
return; return;
} }
const defaultProps = ComponentClass.defaultProps; const defaultProps = ComponentClass.defaultProps;
+14
View File
@@ -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(\`<div><block-text-0/></div>\`);
return function template(ctx, node, key = \\"\\") {
let txt1 = ctx['message'];
return block1([txt1]);
}
}"
`;
+18 -1
View File
@@ -1,4 +1,4 @@
import { App, Component, xml } from "../../src"; import { App, Component, mount, xml } from "../../src";
import { status } from "../../src/component/status"; import { status } from "../../src/component/status";
import { makeTestFixture, snapshotEverything, nextTick, elem } from "../helpers"; import { makeTestFixture, snapshotEverything, nextTick, elem } from "../helpers";
@@ -59,4 +59,21 @@ describe("app", () => {
await app.mount(fixture); await app.mount(fixture);
expect(fixture.innerHTML).toBe("<div>333</div>"); expect(fixture.innerHTML).toBe("<div>333</div>");
}); });
test("warnIfNoStaticProps works as expected", async () => {
let originalconsoleWarn = console.warn;
let mockConsoleWarn = jest.fn(() => {});
console.warn = mockConsoleWarn;
class Root extends Component {
static template = xml`<div t-esc="message"/>`;
}
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"
);
});
}); });