From b49a3f508538cdbff2dd6575f023a3982267068c Mon Sep 17 00:00:00 2001 From: Waldemar Mazurek Date: Mon, 23 Sep 2024 11:43:00 +0200 Subject: [PATCH 1/4] Adds skipInitCheck property to compound container --- .../compound/wc-compound-container.cy.js | 12 +++ container/src/LuigiCompoundContainer.svelte | 67 ++++++++------- container/src/LuigiContainer.svelte | 84 +++++++++---------- .../src/services/webcomponents.service.ts | 3 + .../test-app/compound/compoundClientAPI.html | 1 + container/test-app/compound/helloWorldWC.js | 15 ++++ .../services/webcomponents.service.spec.ts | 13 +++ .../LuigiCompoundContainer.svelte.d.ts | 6 ++ docs/luigi-compound-container-api.md | 10 +++ 9 files changed, 137 insertions(+), 74 deletions(-) diff --git a/container/cypress/e2e/test-app/compound/wc-compound-container.cy.js b/container/cypress/e2e/test-app/compound/wc-compound-container.cy.js index 1cd7582460..bc647e32a6 100644 --- a/container/cypress/e2e/test-app/compound/wc-compound-container.cy.js +++ b/container/cypress/e2e/test-app/compound/wc-compound-container.cy.js @@ -105,6 +105,18 @@ describe('Compound Container Tests', () => { }); }); + it('LuigiClient API - getSkipInitCheck', () => { + cy.on('window:alert', stub); + + cy.get(containerSelector) + .shadow() + .contains('getSkipInitCheck') + .click() + .then(() => { + expect(stub.getCall(0)).to.be.calledWith('LuigiClient.getSkipInitCheck()=true'); + }); + }); + it('LuigiClient API updateContext', () => { cy.on('window:alert', stub); diff --git a/container/src/LuigiCompoundContainer.svelte b/container/src/LuigiCompoundContainer.svelte index 1e5794d68e..14772bf726 100644 --- a/container/src/LuigiCompoundContainer.svelte +++ b/container/src/LuigiCompoundContainer.svelte @@ -3,36 +3,37 @@ tag: null, shadow: 'none', props: { - viewurl: { type: 'String', reflect: false, attribute: 'viewurl' }, - deferInit: { type: 'Boolean', attribute: 'defer-init' }, - context: { type: 'String', reflect: false, attribute: 'context' }, - noShadow: { type: 'Boolean', attribute: 'no-shadow', reflect: false }, - compoundConfig: { + anchor: { type: 'String', reflect: false, attribute: 'anchor' }, + clientPermissions: { type: 'Object', reflect: false, - attribute: 'compound-config', + attribute: 'client-permissions', }, - nodeParams: { type: 'Object', reflect: false, attribute: 'node-params' }, - userSettings: { + compoundConfig: { type: 'Object', reflect: false, - attribute: 'user-settings', + attribute: 'compound-config', }, - anchor: { type: 'String', reflect: false, attribute: 'anchor' }, + context: { type: 'String', reflect: false, attribute: 'context' }, + deferInit: { type: 'Boolean', attribute: 'defer-init' }, + dirtyStatus: { type: 'Boolean', reflect: false, attribute: 'dirty-status'}, + documentTitle: {type: 'String', reflect: false, attribute: 'document-title'}, + hasBack: { type: 'Boolean', reflect: false, attribute: 'has-back'}, + noShadow: { type: 'Boolean', attribute: 'no-shadow', reflect: false }, + nodeParams: { type: 'Object', reflect: false, attribute: 'node-params' }, + pathParams: { type: 'Object', reflect: false, attribute: 'path-params' }, searchParams: { type: 'Object', reflect: false, attribute: 'search-params', }, - pathParams: { type: 'Object', reflect: false, attribute: 'path-params' }, - clientPermissions: { + skipInitCheck: { type: 'Boolean', reflect: false, attribute: 'skip-init-check' }, + userSettings: { type: 'Object', reflect: false, - attribute: 'client-permissions', + attribute: 'user-settings', }, - dirtyStatus: { type: 'Boolean', reflect: false, attribute: 'dirty-status'}, - hasBack: { type: 'Boolean', reflect: false, attribute: 'has-back'}, - documentTitle: {type: 'String', reflect: false, attribute: 'document-title'}, + viewurl: { type: 'String', reflect: false, attribute: 'viewurl' } }, extend: (customElementConstructor) => { let notInitFn = (name) => { @@ -64,21 +65,22 @@ import { Events } from './constants/communication'; import { GenericHelperFunctions } from './utilities/helpers'; - export let viewurl: string; - export let webcomponent: any; + export let anchor: string; + export let clientPermissions: any; + export let compoundConfig: any; export let context: string; export let deferInit: boolean; + export let dirtyStatus: boolean; + export let documentTitle: string; + export let hasBack: boolean; export let noShadow: boolean; - export let compoundConfig: any; export let nodeParams: any; - export let searchParams: any; export let pathParams: any; - export let clientPermissions: any; + export let searchParams: any; + export let skipInitCheck: boolean; export let userSettings: any; - export let anchor: string; - export let dirtyStatus: boolean; - export let hasBack: boolean; - export let documentTitle: string; + export let viewurl: string; + export let webcomponent: any; let containerInitialized = false; let mainComponent: HTMLElement; @@ -90,16 +92,17 @@ // Only needed for get rid of "unused export property" svelte compiler warnings export const unwarn = () => { return ( - nodeParams && - searchParams && - pathParams && - clientPermissions && - userSettings && anchor && + clientPermissions && dirtyStatus && - hasBack && documentTitle && - noShadow + hasBack && + noShadow && + nodeParams && + pathParams && + searchParams && + skipInitCheck && + userSettings ); }; diff --git a/container/src/LuigiContainer.svelte b/container/src/LuigiContainer.svelte index 625a97f7ea..b489a5a6bc 100644 --- a/container/src/LuigiContainer.svelte +++ b/container/src/LuigiContainer.svelte @@ -3,28 +3,28 @@ tag: null, shadow: 'none', props: { - viewurl: { type: 'String', reflect: false, attribute: 'viewurl' }, - deferInit: { type: 'Boolean', attribute: 'defer-init' }, - noShadow: { type: 'Boolean', attribute: 'no-shadow' }, - context: { type: 'String', reflect: false, attribute: 'context' }, - label: { type: 'String', reflect: false, attribute: 'label' }, - webcomponent: { type: 'String', reflect: false, attribute: 'webcomponent' }, - locale: { type: 'String', reflect: false, attribute: 'locale' }, - theme: { type: 'String', reflect: false, attribute: 'theme' }, activeFeatureToggleList: { type: 'Array', reflect: false, attribute: 'active-feature-toggle-list' }, - skipInitCheck: { type: 'Boolean', reflect: false, attribute: 'skip-init-check' }, - nodeParams: { type: 'Object', reflect: false, attribute: 'node-params' }, - userSettings: { type: 'Object', reflect: false, attribute: 'user-settings' }, + allowRules: { type: 'Array', reflect: false, attribute: 'allow-rules' }, anchor: { type: 'String', reflect: false, attribute: 'anchor' }, - searchParams: { type: 'Object', reflect: false, attribute: 'search-params' }, - pathParams: { type: 'Object', reflect: false, attribute: 'path-params' }, + authData: { type: 'Object', reflect: false, attribute: 'auth-data' }, clientPermissions: { type: 'Object', reflect: false, attribute: 'client-permissions' }, + context: { type: 'String', reflect: false, attribute: 'context' }, + deferInit: { type: 'Boolean', attribute: 'defer-init' }, dirtyStatus: { type: 'Boolean', reflect: false, attribute: 'dirty-status' }, - hasBack: { type: 'Boolean', reflect: false, attribute: 'has-back' }, documentTitle: { type: 'String', reflect: false, attribute: 'document-title' }, - allowRules: { type: 'Array', reflect: false, attribute: 'allow-rules' }, + hasBack: { type: 'Boolean', reflect: false, attribute: 'has-back' }, + label: { type: 'String', reflect: false, attribute: 'label' }, + locale: { type: 'String', reflect: false, attribute: 'locale' }, + noShadow: { type: 'Boolean', attribute: 'no-shadow' }, + nodeParams: { type: 'Object', reflect: false, attribute: 'node-params' }, + pathParams: { type: 'Object', reflect: false, attribute: 'path-params' }, sandboxRules: { type: 'Array', reflect: false, attribute: 'sandbox-rules' }, - authData: { type: 'Object', reflect: false, attribute: 'auth-data' } + searchParams: { type: 'Object', reflect: false, attribute: 'search-params' }, + skipInitCheck: { type: 'Boolean', reflect: false, attribute: 'skip-init-check' }, + theme: { type: 'String', reflect: false, attribute: 'theme' }, + userSettings: { type: 'Object', reflect: false, attribute: 'user-settings' }, + viewurl: { type: 'String', reflect: false, attribute: 'viewurl' }, + webcomponent: { type: 'String', reflect: false, attribute: 'webcomponent' } }, extend: customElementConstructor => { let notInitFn = name => { @@ -62,29 +62,28 @@ import { GenericHelperFunctions } from './utilities/helpers'; import { getAllowRules } from './services/iframe-helpers'; - export let viewurl: string; + export let activeFeatureToggleList: string[]; + export let allowRules: string[]; + export let anchor: string; + export let authData: any; + export let clientPermissions: any; export let context: string; - export let label: string; - export let webcomponent: any; export let deferInit: boolean; - export let noShadow: Boolean; + export let dirtyStatus: boolean; + export let documentTitle: string; + export let hasBack: boolean; + export let label: string; export let locale: string; - export let theme: string; - export let activeFeatureToggleList: string[]; - export let skipInitCheck: boolean; + export let noShadow: Boolean; export let nodeParams: any; - export let searchParams: any; export let pathParams: any; - export let clientPermissions: any; - export let dirtyStatus: boolean; - export let hasBack: boolean; - export let documentTitle: string; - export let allowRules: string[]; export let sandboxRules: string[]; - + export let searchParams: any; + export let skipInitCheck: boolean; + export let theme: string; export let userSettings: any; - export let anchor: string; - export let authData: any; + export let viewurl: string; + export let webcomponent: any; const iframeHandle: | { @@ -100,22 +99,23 @@ // Only needed for get rid of "unused export property" svelte compiler warnings export const unwarn = () => { return ( - locale && - theme && activeFeatureToggleList && - nodeParams && - searchParams && - pathParams && - clientPermissions && - userSettings && + allowRules && anchor && authData && + clientPermissions && dirtyStatus && - hasBack && documentTitle && - allowRules && + hasBack && + locale && + noShadow && + nodeParams && + pathParams && sandboxRules && - noShadow + searchParams && + skipInitCheck && + theme && + userSettings ); }; diff --git a/container/src/services/webcomponents.service.ts b/container/src/services/webcomponents.service.ts index 0461c1f6b6..e285274d30 100644 --- a/container/src/services/webcomponents.service.ts +++ b/container/src/services/webcomponents.service.ts @@ -332,6 +332,9 @@ export class WebComponentService { getUserSettings: (): Object => { return this.thisComponent.userSettings || {}; }, + getSkipInitCheck: (): boolean => { + return !!this.thisComponent.skipInitCheck; + }, setViewGroupData: data => { this.dispatchLuigiEvent(Events.SET_VIEW_GROUP_DATA_REQUEST, data); } diff --git a/container/test-app/compound/compoundClientAPI.html b/container/test-app/compound/compoundClientAPI.html index 37a6a7495f..43be1553c0 100644 --- a/container/test-app/compound/compoundClientAPI.html +++ b/container/test-app/compound/compoundClientAPI.html @@ -34,6 +34,7 @@

user-settings='{"language":"it", "date":""}' anchor="testAnchorCompound" defer-init="false" + skip-init-check="true" webcomponent="true" > diff --git a/container/test-app/compound/helloWorldWC.js b/container/test-app/compound/helloWorldWC.js index e4214bfb75..ef7dfb5b45 100644 --- a/container/test-app/compound/helloWorldWC.js +++ b/container/test-app/compound/helloWorldWC.js @@ -43,6 +43,9 @@ export default class extends HTMLElement { const getAnchorBtn = document.createElement('template'); getAnchorBtn.innerHTML = ''; + const getSkipInitCheckBtn = document.createElement('template'); + getSkipInitCheckBtn.innerHTML = ''; + const setViewGroupDataBtn = document.createElement('template'); setViewGroupDataBtn.innerHTML = ''; @@ -97,6 +100,7 @@ export default class extends HTMLElement { this._shadowRoot.appendChild(getClientPermissionsBtn.content.cloneNode(true)); this._shadowRoot.appendChild(getUserSettingsBtn.content.cloneNode(true)); this._shadowRoot.appendChild(getAnchorBtn.content.cloneNode(true)); + this._shadowRoot.appendChild(getSkipInitCheckBtn.content.cloneNode(true)); this._shadowRoot.appendChild(getDirtyStatusBtn.content.cloneNode(true)); this._shadowRoot.appendChild(retrieveContextValueBtn.content.cloneNode(true)); this._shadowRoot.appendChild(uxManagerMultipleRequestsBtn.content.cloneNode(true)); @@ -188,6 +192,7 @@ export default class extends HTMLElement { }); } }); + this.$getAnchorBtn = this._shadowRoot.querySelector('#getAnchor'); this.$getAnchorBtn.addEventListener('click', () => { let getAnchor = this.LuigiClient.getAnchor(); @@ -197,6 +202,16 @@ export default class extends HTMLElement { }); }); + this.$getSkipInitCheckBtn = this._shadowRoot.querySelector('#getSkipInitCheck'); + this.$getSkipInitCheckBtn.addEventListener('click', () => { + const skipInitCheck = this.LuigiClient.getSkipInitCheck(); + + this.LuigiClient.uxManager().showAlert({ + text: 'LuigiClient.getSkipInitCheck()=' + JSON.stringify(skipInitCheck), + type: 'info' + }); + }); + this.$getDirtyStatusBtn = this._shadowRoot.querySelector('#getDirtyStatus'); this.$getDirtyStatusBtn.addEventListener('click', () => { let dirtyStatus = this.LuigiClient.uxManager().getDirtyStatus(); diff --git a/container/test/services/webcomponents.service.spec.ts b/container/test/services/webcomponents.service.spec.ts index 8f68f146e4..2867a4c50d 100644 --- a/container/test/services/webcomponents.service.spec.ts +++ b/container/test/services/webcomponents.service.spec.ts @@ -1144,6 +1144,19 @@ describe('createClientAPI', () => { // assert expect(result).toEqual({}); }); + + it.each([true, false])('test getSkipInitCheck attribute', (value) => { + // mock and spy on data/functions + service.thisComponent = document.createElement('div'); + service.thisComponent.skipInitCheck = value; + + // act + const clientAPI = service.createClientAPI(undefined, 'nodeId', 'wc_id', 'component', false); + const result = clientAPI.getSkipInitCheck(); + + // assert + expect(result).toBe(value); + }); }); describe('initWC', () => { diff --git a/container/typings/LuigiCompoundContainer.svelte.d.ts b/container/typings/LuigiCompoundContainer.svelte.d.ts index 57a509a743..c76e519aca 100644 --- a/container/typings/LuigiCompoundContainer.svelte.d.ts +++ b/container/typings/LuigiCompoundContainer.svelte.d.ts @@ -97,6 +97,12 @@ export default class LuigiCompoundContainer extends HTMLElement { */ webcomponent: boolean | WebComponentSettings | string; + /** + * If set to true, skips handshake and ready event is fired immediately. + * @since NEXT_RELEASE_CONTAINER + */ + skipInitCheck: boolean; + /** * Function that updates the context of the compound microfrontend. * @param contextObj The context data diff --git a/docs/luigi-compound-container-api.md b/docs/luigi-compound-container-api.md index 0adbea9f4e..f7a38d5397 100644 --- a/docs/luigi-compound-container-api.md +++ b/docs/luigi-compound-container-api.md @@ -170,6 +170,16 @@ Type: ([boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Glo * **since**: 1.0.0 +### skipInitCheck + +If set to true, skips handshake and ready event is fired immediately. + +Type: [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean) + +**Meta** + +* **since**: NEXT_RELEASE_CONTAINER + ### updateContext Function that updates the context of the compound microfrontend. From c70ad457f799013481159b25e7f6451264f1b066 Mon Sep 17 00:00:00 2001 From: Waldemar Mazurek Date: Mon, 23 Sep 2024 11:46:48 +0200 Subject: [PATCH 2/4] Fixes Prettier issue --- container/test/services/webcomponents.service.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/container/test/services/webcomponents.service.spec.ts b/container/test/services/webcomponents.service.spec.ts index 2867a4c50d..58223ee9fe 100644 --- a/container/test/services/webcomponents.service.spec.ts +++ b/container/test/services/webcomponents.service.spec.ts @@ -1145,7 +1145,7 @@ describe('createClientAPI', () => { expect(result).toEqual({}); }); - it.each([true, false])('test getSkipInitCheck attribute', (value) => { + it.each([true, false])('test getSkipInitCheck attribute', value => { // mock and spy on data/functions service.thisComponent = document.createElement('div'); service.thisComponent.skipInitCheck = value; From 01d3c68b62b6b720ab2f6adcf23449e2cd9f4bf8 Mon Sep 17 00:00:00 2001 From: Waldemar Mazurek Date: Tue, 24 Sep 2024 17:16:40 +0200 Subject: [PATCH 3/4] Fixes code review issues --- .../test-app/compound/wc-compound-container.cy.js | 10 ++-------- container/src/LuigiCompoundContainer.svelte | 2 +- container/src/services/webcomponents.service.ts | 3 --- container/test-app/compound/helloWorldWC.js | 14 -------------- .../test/services/webcomponents.service.spec.ts | 13 ------------- 5 files changed, 3 insertions(+), 39 deletions(-) diff --git a/container/cypress/e2e/test-app/compound/wc-compound-container.cy.js b/container/cypress/e2e/test-app/compound/wc-compound-container.cy.js index e29eacd24f..c732dcc761 100644 --- a/container/cypress/e2e/test-app/compound/wc-compound-container.cy.js +++ b/container/cypress/e2e/test-app/compound/wc-compound-container.cy.js @@ -106,15 +106,9 @@ describe('Compound Container Tests', () => { }); it('LuigiClient API - getSkipInitCheck', () => { - cy.on('window:alert', stub); - cy.get(containerSelector) - .shadow() - .contains('getSkipInitCheck') - .click() - .then(() => { - expect(stub.getCall(0)).to.be.calledWith('LuigiClient.getSkipInitCheck()=true'); - }); + .invoke('attr', 'skip-init-check') + .should('eq', 'true'); }); it('LuigiClient API - getActiveFeatureToggles', () => { diff --git a/container/src/LuigiCompoundContainer.svelte b/container/src/LuigiCompoundContainer.svelte index d900f970aa..c6f36304b1 100644 --- a/container/src/LuigiCompoundContainer.svelte +++ b/container/src/LuigiCompoundContainer.svelte @@ -147,7 +147,7 @@ } webcomponentService.renderWebComponentCompound(node, thisComponent.getNoShadow() ? thisComponent : mainComponent, ctx).then(compCnt => { eventBusElement = compCnt as HTMLElement; - if (thisComponent.hasAttribute('skip-init-check') || !node.viewUrl) { + if (skipInitCheck || !node.viewUrl) { thisComponent.initialized = true; setTimeout(() => { webcomponentService.dispatchLuigiEvent(Events.INITIALIZED, {}); diff --git a/container/src/services/webcomponents.service.ts b/container/src/services/webcomponents.service.ts index e285274d30..0461c1f6b6 100644 --- a/container/src/services/webcomponents.service.ts +++ b/container/src/services/webcomponents.service.ts @@ -332,9 +332,6 @@ export class WebComponentService { getUserSettings: (): Object => { return this.thisComponent.userSettings || {}; }, - getSkipInitCheck: (): boolean => { - return !!this.thisComponent.skipInitCheck; - }, setViewGroupData: data => { this.dispatchLuigiEvent(Events.SET_VIEW_GROUP_DATA_REQUEST, data); } diff --git a/container/test-app/compound/helloWorldWC.js b/container/test-app/compound/helloWorldWC.js index b5e7dc5050..0598bdd4df 100644 --- a/container/test-app/compound/helloWorldWC.js +++ b/container/test-app/compound/helloWorldWC.js @@ -43,9 +43,6 @@ export default class extends HTMLElement { const getAnchorBtn = document.createElement('template'); getAnchorBtn.innerHTML = ''; - const getSkipInitCheckBtn = document.createElement('template'); - getSkipInitCheckBtn.innerHTML = ''; - const getFeatureToggleListBtn = document.createElement('template'); getFeatureToggleListBtn.innerHTML = ''; @@ -106,7 +103,6 @@ export default class extends HTMLElement { this._shadowRoot.appendChild(getClientPermissionsBtn.content.cloneNode(true)); this._shadowRoot.appendChild(getUserSettingsBtn.content.cloneNode(true)); this._shadowRoot.appendChild(getAnchorBtn.content.cloneNode(true)); - this._shadowRoot.appendChild(getSkipInitCheckBtn.content.cloneNode(true)); this._shadowRoot.appendChild(getFeatureToggleListBtn.content.cloneNode(true)); this._shadowRoot.appendChild(getThemeBtn.content.cloneNode(true)); this._shadowRoot.appendChild(getDirtyStatusBtn.content.cloneNode(true)); @@ -210,16 +206,6 @@ export default class extends HTMLElement { }); }); - this.$getSkipInitCheckBtn = this._shadowRoot.querySelector('#getSkipInitCheck'); - this.$getSkipInitCheckBtn.addEventListener('click', () => { - const skipInitCheck = this.LuigiClient.getSkipInitCheck(); - - this.LuigiClient.uxManager().showAlert({ - text: 'LuigiClient.getSkipInitCheck()=' + JSON.stringify(skipInitCheck), - type: 'info' - }); - }); - this.$getFeatureToggleListBtn = this._shadowRoot.querySelector('#getFeatureToggleList'); this.$getFeatureToggleListBtn.addEventListener('click', () => { const activeFeatureToggleList = this.LuigiClient.getActiveFeatureToggles(); diff --git a/container/test/services/webcomponents.service.spec.ts b/container/test/services/webcomponents.service.spec.ts index 58223ee9fe..8f68f146e4 100644 --- a/container/test/services/webcomponents.service.spec.ts +++ b/container/test/services/webcomponents.service.spec.ts @@ -1144,19 +1144,6 @@ describe('createClientAPI', () => { // assert expect(result).toEqual({}); }); - - it.each([true, false])('test getSkipInitCheck attribute', value => { - // mock and spy on data/functions - service.thisComponent = document.createElement('div'); - service.thisComponent.skipInitCheck = value; - - // act - const clientAPI = service.createClientAPI(undefined, 'nodeId', 'wc_id', 'component', false); - const result = clientAPI.getSkipInitCheck(); - - // assert - expect(result).toBe(value); - }); }); describe('initWC', () => { From d73fef443b1332d0cfa5e8d49cf567dcd36cb590 Mon Sep 17 00:00:00 2001 From: Waldemar Mazurek Date: Wed, 25 Sep 2024 08:20:28 +0200 Subject: [PATCH 4/4] Fixes docu issue --- docs/luigi-compound-container-api.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/luigi-compound-container-api.md b/docs/luigi-compound-container-api.md index 5fa5bbd7bb..b85debd77d 100644 --- a/docs/luigi-compound-container-api.md +++ b/docs/luigi-compound-container-api.md @@ -188,7 +188,7 @@ Type: [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Glob **Meta** -* **since**: 1.0.0 +* **since**: NEXT_RELEASE_CONTAINER ### activeFeatureToggleList