From 1d2ac44f6f83bbc13e4343b099b90b16babb0db4 Mon Sep 17 00:00:00 2001 From: Yoriiis <2563298+yoriiis@users.noreply.github.com> Date: Wed, 18 Sep 2024 21:28:39 +0200 Subject: [PATCH 1/6] Add async on before render function --- src/app.ts | 61 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 36 insertions(+), 25 deletions(-) diff --git a/src/app.ts b/src/app.ts index b17094b..ef7c6d3 100644 --- a/src/app.ts +++ b/src/app.ts @@ -251,24 +251,30 @@ export default class App { * Create the current component */ createComponent() { - if (this.currentRoute) { - if (this.currentRoute.isComponentClass && !this.currentRoute.isComponentClassReady) { + const currentRoute = this.currentRoute + if (currentRoute) { + if (currentRoute.isComponentClass && !currentRoute.isComponentClassReady) { this.initComponentInCache() } - let componentView = this.getComponentView() - if (componentView) { - if (!this.currentRoute.interfaceType) { - this.currentRoute.interfaceType = this.getInterfaceTypeFromView(componentView) - this.routes.set(this.currentRoute.path, this.currentRoute) - } + const responseComponentView = this.getComponentView() - if (this.currentRoute.interfaceType === 'STRING') { - componentView = this.transformLinksInStringComponent(componentView) - } - this.target.appendChild(componentView) - this.currentRoute.isComponentClass && this.currentRoute.component.afterRender() - } + responseComponentView && + responseComponentView.then((componentView: any) => { + if (componentView) { + if (!currentRoute.interfaceType) { + currentRoute.interfaceType = + this.getInterfaceTypeFromView(componentView) + this.routes.set(currentRoute.path, currentRoute) + } + + if (currentRoute.interfaceType === 'STRING') { + componentView = this.transformLinksInStringComponent(componentView) + } + this.target.appendChild(componentView) + currentRoute.isComponentClass && currentRoute.component.afterRender() + } + }) } } @@ -302,17 +308,22 @@ export default class App { * @returns The component view */ getComponentView() { - if (this.currentRoute) { - if (this.currentRoute.isComponentClass) { - this.updateComponentRouteData() - this.currentRoute.component.beforeRender() - return this.currentRoute.component.render() - } else { - return this.currentRoute.component.call( - this.currentRoute.component, - this.currentRoute.props - ) - } + const currentRoute = this.currentRoute + if (currentRoute) { + return new Promise((resolve) => { + if (currentRoute.isComponentClass) { + this.updateComponentRouteData() + const beforeRenderFn = currentRoute.component.beforeRender() + + if (beforeRenderFn instanceof Promise) { + beforeRenderFn.then(() => resolve(currentRoute.component.render())) + } else { + resolve(currentRoute.component.render()) + } + } else { + resolve(currentRoute.component.call(currentRoute.component, currentRoute.props)) + } + }) } } From 61223729bed2c4e0e83e4e0c067d4f7ef9d3c27d Mon Sep 17 00:00:00 2001 From: Yoriiis <2563298+yoriiis@users.noreply.github.com> Date: Fri, 20 Sep 2024 16:51:08 +0200 Subject: [PATCH 2/6] Update --- src/app.ts | 74 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 43 insertions(+), 31 deletions(-) diff --git a/src/app.ts b/src/app.ts index ef7c6d3..3a20478 100644 --- a/src/app.ts +++ b/src/app.ts @@ -247,34 +247,40 @@ export default class App { } } + updateView() { + if (typeof Element.prototype.replaceChildren === 'function') { + this.target.replaceChildren() + } else { + this.target.innerHTML = '' + } + } + /** * Create the current component */ createComponent() { - const currentRoute = this.currentRoute - if (currentRoute) { - if (currentRoute.isComponentClass && !currentRoute.isComponentClassReady) { + if (this.currentRoute) { + if (this.currentRoute.isComponentClass && !this.currentRoute.isComponentClassReady) { this.initComponentInCache() } const responseComponentView = this.getComponentView() - responseComponentView && - responseComponentView.then((componentView: any) => { - if (componentView) { - if (!currentRoute.interfaceType) { - currentRoute.interfaceType = - this.getInterfaceTypeFromView(componentView) - this.routes.set(currentRoute.path, currentRoute) - } + responseComponentView.then((componentView: any) => { + if (componentView && this.currentRoute) { + if (!this.currentRoute.interfaceType) { + this.currentRoute.interfaceType = + this.getInterfaceTypeFromView(componentView) + this.routes.set(this.currentRoute.path, this.currentRoute) + } - if (currentRoute.interfaceType === 'STRING') { - componentView = this.transformLinksInStringComponent(componentView) - } - this.target.appendChild(componentView) - currentRoute.isComponentClass && currentRoute.component.afterRender() + if (this.currentRoute.interfaceType === 'STRING') { + componentView = this.transformLinksInStringComponent(componentView) } - }) + this.target.appendChild(componentView) + this.currentRoute.isComponentClass && this.currentRoute.component.afterRender() + } + }) } } @@ -308,23 +314,29 @@ export default class App { * @returns The component view */ getComponentView() { - const currentRoute = this.currentRoute - if (currentRoute) { - return new Promise((resolve) => { - if (currentRoute.isComponentClass) { - this.updateComponentRouteData() - const beforeRenderFn = currentRoute.component.beforeRender() - - if (beforeRenderFn instanceof Promise) { - beforeRenderFn.then(() => resolve(currentRoute.component.render())) - } else { - resolve(currentRoute.component.render()) - } + if (this.currentRoute) { + if (this.currentRoute.isComponentClass) { + this.updateComponentRouteData() + const beforeRenderFn = this.currentRoute.component.beforeRender() + + if (beforeRenderFn instanceof Promise) { + return Promise.resolve(beforeRenderFn).then( + () => this.currentRoute && this.currentRoute.component.render() + ) } else { - resolve(currentRoute.component.call(currentRoute.component, currentRoute.props)) + return Promise.resolve(this.currentRoute.component.render()) } - }) + } else { + return Promise.resolve( + this.currentRoute.component.call( + this.currentRoute.component, + this.currentRoute.props + ) + ) + } } + + return Promise.reject() } /** From a1abaabb5eb9b0c0f2eb87d9038a0f9724c01bac Mon Sep 17 00:00:00 2001 From: Yoriiis <2563298+yoriiis@users.noreply.github.com> Date: Fri, 20 Sep 2024 17:36:31 +0200 Subject: [PATCH 3/6] Update unit test --- src/app.ts | 8 ---- tests/unit/app.test.js | 97 ++++++++++++++++++++++++++---------------- 2 files changed, 60 insertions(+), 45 deletions(-) diff --git a/src/app.ts b/src/app.ts index 3a20478..e9da64b 100644 --- a/src/app.ts +++ b/src/app.ts @@ -247,14 +247,6 @@ export default class App { } } - updateView() { - if (typeof Element.prototype.replaceChildren === 'function') { - this.target.replaceChildren() - } else { - this.target.innerHTML = '' - } - } - /** * Create the current component */ diff --git a/tests/unit/app.test.js b/tests/unit/app.test.js index 6b86beb..3ac590d 100644 --- a/tests/unit/app.test.js +++ b/tests/unit/app.test.js @@ -687,7 +687,7 @@ describe('App', () => { app = getInstance() }) - it('should call the createComponent function with a component and HTMLElement', () => { + it('should call the createComponent function with a component and HTMLElement', async () => { app.currentRoute = { component: { afterRender: jest.fn() @@ -698,12 +698,12 @@ describe('App', () => { } app.initComponentInCache = jest.fn() - app.getComponentView = jest.fn().mockReturnValue(
Component
) + app.getComponentView = jest.fn().mockResolvedValue(
Component
) app.getInterfaceTypeFromView = jest.fn().mockReturnValue('ELEMENT_NODE') app.transformLinksInStringComponent = jest.fn() app.target.appendChild = jest.fn() - app.createComponent() + await app.createComponent() expect(app.initComponentInCache).toHaveBeenCalled() expect(app.getComponentView).toHaveBeenCalled() @@ -714,7 +714,7 @@ describe('App', () => { expect(app.currentRoute.component.afterRender).toHaveBeenCalled() }) - it('should call the createComponent function with a component and String', () => { + it('should call the createComponent function with a component and String', async () => { app.currentRoute = { component: { afterRender: jest.fn() @@ -727,12 +727,12 @@ describe('App', () => { app.initComponentInCache = jest.fn() app.getComponentView = jest .fn() - .mockReturnValue('
Link
') + .mockResolvedValue('
Link
') app.getInterfaceTypeFromView = jest.fn().mockReturnValue('STRING') app.transformLinksInStringComponent = jest.fn().mockReturnValue(
) app.target.appendChild = jest.fn() - app.createComponent() + await app.createComponent() expect(app.initComponentInCache).toHaveBeenCalled() expect(app.getComponentView).toHaveBeenCalled() @@ -808,44 +808,67 @@ describe('App', () => { app.updateComponentRouteData = jest.fn() }) - it('should call the getComponentView function with a component class', () => { - app.currentRoute = { - component: { - afterRender: jest.fn(), - beforeRender: jest.fn(), - render: jest.fn().mockReturnValue(
Component
) - }, - isComponentClass: true - } + describe('Component', () => { + it('should call the getComponentView function with a component class with before render not asynchrone', async () => { + app.currentRoute = { + component: { + afterRender: jest.fn(), + beforeRender: jest.fn(), + render: jest.fn().mockReturnValue(
Component
) + }, + isComponentClass: true + } - const result = app.getComponentView() + const result = await app.getComponentView() - expect(app.updateComponentRouteData).toHaveBeenCalled() - expect(app.currentRoute.component.beforeRender).toHaveBeenCalled() - expect(app.currentRoute.component.render).toHaveBeenCalled() - expect(result).toStrictEqual(
Component
) - }) + expect(app.updateComponentRouteData).toHaveBeenCalled() + expect(app.currentRoute.component.beforeRender).toHaveBeenCalled() + expect(app.currentRoute.component.render).toHaveBeenCalled() + expect(result).toStrictEqual(
Component
) + }) - it('should call the getComponentView function with not a component class', () => { - app.currentRoute = { - component: jest.fn().mockReturnValue(
Component
), - isComponentClass: false, - props: { - name: 'John Doe' + it('should call the getComponentView function with a component class with before render asynchrone', async () => { + app.currentRoute = { + component: { + afterRender: jest.fn(), + beforeRender: jest.fn().mockResolvedValue(), + render: jest.fn().mockReturnValue(
Component
) + }, + isComponentClass: true } - } - jest.spyOn(app.currentRoute.component, 'call') - const result = app.getComponentView() + const result = await app.getComponentView() + + expect(app.updateComponentRouteData).toHaveBeenCalled() + expect(app.currentRoute.component.beforeRender).toHaveBeenCalled() + // TODO check execution order + expect(app.currentRoute.component.render).toHaveBeenCalled() + expect(result).toStrictEqual(
Component
) + }) + }) - expect(app.updateComponentRouteData).not.toHaveBeenCalled() - expect(app.currentRoute.component.call).toHaveBeenCalledWith( - app.currentRoute.component, - { - name: 'John Doe' + describe('Not a component', () => { + it('should call the getComponentView function with not a component class', async () => { + app.currentRoute = { + component: jest.fn().mockReturnValue(
Component
), + isComponentClass: false, + props: { + name: 'John Doe' + } } - ) - expect(result).toStrictEqual(
Component
) + jest.spyOn(app.currentRoute.component, 'call') + + const result = await app.getComponentView() + + expect(app.updateComponentRouteData).not.toHaveBeenCalled() + expect(app.currentRoute.component.call).toHaveBeenCalledWith( + app.currentRoute.component, + { + name: 'John Doe' + } + ) + expect(result).toStrictEqual(
Component
) + }) }) }) From 2f653d1f9ab00915a8158971a7131ef52b43cac7 Mon Sep 17 00:00:00 2001 From: Yoriiis <2563298+yoriiis@users.noreply.github.com> Date: Mon, 23 Sep 2024 17:39:46 +0200 Subject: [PATCH 4/6] Update unit test --- src/app.ts | 72 +++++++++++++--------- tests/unit/app.test.js | 135 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 173 insertions(+), 34 deletions(-) diff --git a/src/app.ts b/src/app.ts index e9da64b..8ccd1ce 100644 --- a/src/app.ts +++ b/src/app.ts @@ -256,23 +256,26 @@ export default class App { this.initComponentInCache() } - const responseComponentView = this.getComponentView() - - responseComponentView.then((componentView: any) => { - if (componentView && this.currentRoute) { - if (!this.currentRoute.interfaceType) { - this.currentRoute.interfaceType = - this.getInterfaceTypeFromView(componentView) - this.routes.set(this.currentRoute.path, this.currentRoute) - } + try { + this.getComponentView().then((componentView) => { + if (componentView && this.currentRoute) { + if (!this.currentRoute.interfaceType) { + this.currentRoute.interfaceType = + this.getInterfaceTypeFromView(componentView) + this.routes.set(this.currentRoute.path, this.currentRoute) + } - if (this.currentRoute.interfaceType === 'STRING') { - componentView = this.transformLinksInStringComponent(componentView) + if (this.currentRoute.interfaceType === 'STRING') { + componentView = this.transformLinksInStringComponent(componentView) + } + this.target.appendChild(componentView) + this.currentRoute.isComponentClass && + this.currentRoute.component.afterRender() } - this.target.appendChild(componentView) - this.currentRoute.isComponentClass && this.currentRoute.component.afterRender() - } - }) + }) + } catch (error) { + console.warn('getComponentView::promise rejected') + } } } @@ -312,23 +315,36 @@ export default class App { const beforeRenderFn = this.currentRoute.component.beforeRender() if (beforeRenderFn instanceof Promise) { - return Promise.resolve(beforeRenderFn).then( - () => this.currentRoute && this.currentRoute.component.render() - ) - } else { - return Promise.resolve(this.currentRoute.component.render()) + return this.runRenderWhenReady(this.currentRoute, beforeRenderFn) } - } else { - return Promise.resolve( - this.currentRoute.component.call( - this.currentRoute.component, - this.currentRoute.props - ) - ) + + return Promise.resolve(this.currentRoute.component.render()) } + + return Promise.resolve( + this.currentRoute.component.call( + this.currentRoute.component, + this.currentRoute.props + ) + ) } - return Promise.reject() + return Promise.reject(new Error('getComponentView::promise not resolved')) + } + + /** + * Run render function when asynchronous before render is resolved + * @param currentRoute Current route + * @param beforeRenderFn Before render promise + * @returns The render content + */ + runRenderWhenReady(currentRoute: RouteData, beforeRenderFn: Promise) { + return Promise.resolve(beforeRenderFn).then(() => { + // Check is route has changed before the promise resolution + if (this.currentRoute && this.currentRoute.path === currentRoute.path) { + return currentRoute.component.render() + } + }) } /** diff --git a/tests/unit/app.test.js b/tests/unit/app.test.js index 3ac590d..e9e74ec 100644 --- a/tests/unit/app.test.js +++ b/tests/unit/app.test.js @@ -744,6 +744,34 @@ describe('App', () => { expect(app.target.appendChild).toHaveBeenCalledWith(
) expect(app.currentRoute.component.afterRender).toHaveBeenCalled() }) + + it('should call the createComponent function with a promise rejected', async () => { + app.currentRoute = { + component: { + afterRender: jest.fn() + }, + interfaceType: null, + isComponentClass: true, + isComponentClassReady: false + } + + app.initComponentInCache = jest.fn() + app.getComponentView = jest.fn() + app.getInterfaceTypeFromView = jest.fn() + app.transformLinksInStringComponent = jest.fn() + app.target.appendChild = jest.fn() + console.warn = jest.fn() + + await app.createComponent() + + expect(app.initComponentInCache).toHaveBeenCalled() + expect(app.getComponentView).toHaveBeenCalled() + expect(app.getInterfaceTypeFromView).not.toHaveBeenCalled() + expect(app.transformLinksInStringComponent).not.toHaveBeenCalled() + expect(app.target.appendChild).not.toHaveBeenCalled() + expect(app.currentRoute.component.afterRender).not.toHaveBeenCalled() + expect(console.warn).toHaveBeenCalledWith('getComponentView::promise rejected') + }) }) describe('initComponentInCache', () => { @@ -809,7 +837,7 @@ describe('App', () => { }) describe('Component', () => { - it('should call the getComponentView function with a component class with before render not asynchrone', async () => { + it('should call the getComponentView function with a component class with before render not a promise', async () => { app.currentRoute = { component: { afterRender: jest.fn(), @@ -818,31 +846,63 @@ describe('App', () => { }, isComponentClass: true } + app.runRenderWhenReady = jest.fn() const result = await app.getComponentView() expect(app.updateComponentRouteData).toHaveBeenCalled() expect(app.currentRoute.component.beforeRender).toHaveBeenCalled() + expect(app.runRenderWhenReady).not.toHaveBeenCalled() expect(app.currentRoute.component.render).toHaveBeenCalled() expect(result).toStrictEqual(
Component
) }) - it('should call the getComponentView function with a component class with before render asynchrone', async () => { + it('should call the getComponentView function with a component class with before render as a promise', async () => { app.currentRoute = { component: { afterRender: jest.fn(), - beforeRender: jest.fn().mockResolvedValue(), - render: jest.fn().mockReturnValue(
Component
) + beforeRender: jest + .fn() + .mockImplementation( + () => new Promise((resolve) => setTimeout(resolve, 2000)) + ), + render: jest.fn() }, isComponentClass: true } + app.runRenderWhenReady = jest.fn().mockResolvedValue(
Component
) const result = await app.getComponentView() expect(app.updateComponentRouteData).toHaveBeenCalled() expect(app.currentRoute.component.beforeRender).toHaveBeenCalled() - // TODO check execution order - expect(app.currentRoute.component.render).toHaveBeenCalled() + expect(app.runRenderWhenReady).toHaveBeenCalled() + expect(app.currentRoute.component.render).not.toHaveBeenCalled() + expect(result).toStrictEqual(
Component
) + }) + + it('should call the getComponentView function with a component class with before render as a promise and route has changed', async () => { + const beforeRenderMock = jest.fn().mockResolvedValue() + + app.currentRoute = { + component: { + afterRender: jest.fn(), + beforeRender: beforeRenderMock, + render: jest.fn() + }, + isComponentClass: true + } + app.runRenderWhenReady = jest.fn().mockResolvedValue(
Component
) + + const result = await app.getComponentView() + + expect(app.updateComponentRouteData).toHaveBeenCalled() + expect(app.currentRoute.component.beforeRender).toHaveBeenCalled() + expect(app.runRenderWhenReady).toHaveBeenCalledWith( + app.currentRoute, + expect.any(Promise) + ) + expect(app.currentRoute.component.render).not.toHaveBeenCalled() expect(result).toStrictEqual(
Component
) }) }) @@ -870,6 +930,69 @@ describe('App', () => { expect(result).toStrictEqual(
Component
) }) }) + + it('should call the getComponentView function with a promise rejection', async () => { + await expect(app.getComponentView()).rejects.toStrictEqual( + new Error('getComponentView::promise not resolved') + ) + }) + }) + + describe('runRenderWhenReady', () => { + beforeEach(() => { + jest.spyOn(App.prototype, 'createRoutesData').mockReturnValue(customRoutes) + jest.spyOn(App.prototype, 'addEvents').mockImplementation(() => { + /* Empty */ + }) + jest.spyOn(App.prototype, 'onRouteChange').mockImplementation(() => { + /* Empty */ + }) + + app = getInstance() + app.updateComponentRouteData = jest.fn() + }) + + it('should call the runRenderWhenReady function with render function called', async () => { + app.currentRoute = { + component: { + render: jest.fn().mockReturnValue(
Component
) + }, + isComponentClass: true, + path: '/home' + } + + const result = await app.runRenderWhenReady( + app.currentRoute, + jest.fn().mockResolvedValue() + ) + + expect(app.currentRoute.component.render).toHaveBeenCalled() + expect(result).toStrictEqual(
Component
) + }) + + it('should call the runRenderWhenReady function with route changed and render function not called', async () => { + app.currentRoute = { + component: { + render: jest.fn().mockReturnValue(
Component
) + }, + path: '/page-2' + } + + const previousRoute = { + component: { + render: jest.fn().mockReturnValue(
Component
) + }, + path: '/page-1' + } + + const result = await app.runRenderWhenReady( + previousRoute, + jest.fn().mockResolvedValue() + ) + + expect(app.currentRoute.component.render).not.toHaveBeenCalled() + expect(result).toStrictEqual(undefined) + }) }) describe('updateComponentRouteData', () => { From 02b578f2060ec41b07131c5765438f32ec4a18f3 Mon Sep 17 00:00:00 2001 From: Yoriiis <2563298+yoriiis@users.noreply.github.com> Date: Mon, 23 Sep 2024 18:06:18 +0200 Subject: [PATCH 5/6] Update version --- CHANGELOG.md | 6 ++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 824db62..e818a0b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # CHANGELOG +## 2.2.0 + +### New features + +- Add asynchronous `beforeRender` hook ([#20](https://github.com/costrojs/costro/pull/20)) + ## 2.1.2 ### Fixes diff --git a/package-lock.json b/package-lock.json index 2be5363..14927f7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "costro", - "version": "2.1.2", + "version": "2.2.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "costro", - "version": "2.1.2", + "version": "2.2.0", "license": "MIT", "devDependencies": { "@babel/core": "^7.21.8", diff --git a/package.json b/package.json index 2b18703..85627cd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "costro", - "version": "2.1.2", + "version": "2.2.0", "description": "Build web applications with Components, Store and Router in 3KB", "keywords": [ "costro", From 0f7938db62ee4da2bc4395af319ce2537a888c8b Mon Sep 17 00:00:00 2001 From: Yoriiis <2563298+yoriiis@users.noreply.github.com> Date: Tue, 24 Sep 2024 14:41:17 +0200 Subject: [PATCH 6/6] Optimize catch --- src/app.ts | 10 +++++----- tests/unit/app.test.js | 42 +++++++++++++++++++++++++++++++++--------- 2 files changed, 38 insertions(+), 14 deletions(-) diff --git a/src/app.ts b/src/app.ts index 8ccd1ce..53ba082 100644 --- a/src/app.ts +++ b/src/app.ts @@ -256,8 +256,8 @@ export default class App { this.initComponentInCache() } - try { - this.getComponentView().then((componentView) => { + this.getComponentView() + .then((componentView) => { if (componentView && this.currentRoute) { if (!this.currentRoute.interfaceType) { this.currentRoute.interfaceType = @@ -273,9 +273,9 @@ export default class App { this.currentRoute.component.afterRender() } }) - } catch (error) { - console.warn('getComponentView::promise rejected') - } + .catch((error) => { + console.warn('getComponentView::promise rejected', error) + }) } } diff --git a/tests/unit/app.test.js b/tests/unit/app.test.js index e9e74ec..2056691 100644 --- a/tests/unit/app.test.js +++ b/tests/unit/app.test.js @@ -745,6 +745,33 @@ describe('App', () => { expect(app.currentRoute.component.afterRender).toHaveBeenCalled() }) + it('should call the createComponent function with a promise returning undefined (route has changed)', async () => { + app.currentRoute = { + component: { + afterRender: jest.fn() + }, + interfaceType: null, + isComponentClass: true, + isComponentClassReady: false + } + + app.initComponentInCache = jest.fn() + app.getComponentView = jest.fn().mockResolvedValue(undefined) + app.getInterfaceTypeFromView = jest.fn() + app.transformLinksInStringComponent = jest.fn() + app.target.appendChild = jest.fn() + console.warn = jest.fn() + + await app.createComponent() + + expect(app.initComponentInCache).toHaveBeenCalled() + expect(app.getComponentView).toHaveBeenCalled() + expect(app.getInterfaceTypeFromView).not.toHaveBeenCalled() + expect(app.transformLinksInStringComponent).not.toHaveBeenCalled() + expect(app.target.appendChild).not.toHaveBeenCalled() + expect(app.currentRoute.component.afterRender).not.toHaveBeenCalled() + }) + it('should call the createComponent function with a promise rejected', async () => { app.currentRoute = { component: { @@ -756,10 +783,12 @@ describe('App', () => { } app.initComponentInCache = jest.fn() - app.getComponentView = jest.fn() + app.getComponentView = jest.fn().mockRejectedValue(new Error('Promise rejection error')) + app.getInterfaceTypeFromView = jest.fn() app.transformLinksInStringComponent = jest.fn() app.target.appendChild = jest.fn() + app.test = jest.fn() console.warn = jest.fn() await app.createComponent() @@ -770,7 +799,6 @@ describe('App', () => { expect(app.transformLinksInStringComponent).not.toHaveBeenCalled() expect(app.target.appendChild).not.toHaveBeenCalled() expect(app.currentRoute.component.afterRender).not.toHaveBeenCalled() - expect(console.warn).toHaveBeenCalledWith('getComponentView::promise rejected') }) }) @@ -857,15 +885,11 @@ describe('App', () => { expect(result).toStrictEqual(
Component
) }) - it('should call the getComponentView function with a component class with before render as a promise', async () => { + it('should call the getComponentView function with a component class with before render a promise', async () => { app.currentRoute = { component: { afterRender: jest.fn(), - beforeRender: jest - .fn() - .mockImplementation( - () => new Promise((resolve) => setTimeout(resolve, 2000)) - ), + beforeRender: jest.fn().mockResolvedValue(), render: jest.fn() }, isComponentClass: true @@ -881,7 +905,7 @@ describe('App', () => { expect(result).toStrictEqual(
Component
) }) - it('should call the getComponentView function with a component class with before render as a promise and route has changed', async () => { + it('should call the getComponentView function with a component class with before render a promise and route has changed', async () => { const beforeRenderMock = jest.fn().mockResolvedValue() app.currentRoute = {