Skip to content

Commit

Permalink
Add publishEvent documentation and tests (#3882)
Browse files Browse the repository at this point in the history
  • Loading branch information
ndricimrr authored Oct 7, 2024
1 parent 21f345a commit 53e500e
Show file tree
Hide file tree
Showing 10 changed files with 202 additions and 31 deletions.
62 changes: 62 additions & 0 deletions client/luigi-client-wc-docu-mixin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/**
* <!-- label-success: Web Component API only-->
* Publish an event that can be listened to from the container host.
*
* Similar to {@link luigi-client-api.md#sendCustomMessage sendCustomMessage} but for WebComponent based microfrontends only.
*
* @param {CustomEvent} event Custom event to be published
* @memberof Lifecycle
*
* @example
* // case 1: publish an event from a WC based microfrontend
*
* // wcComponent.js
* // sending a message to parent host
* this.LuigiClient.publishEvent(new CustomEvent('sendSomeMsg', { detail: 'My own message' }));
*
* // host.html
* myContainer.addEventListener('custom-message', event => {
* console.log('My custom message from the microfrontend', event.detail.data);
* }
*
* // case 2: publish an event from a compound microfrontend
*
* // secondChild.js
* // Set the custom event name = 'sendInput' and
* // send a message to its parent (main.html) and sibling (firstChild.js)
* this.LuigiClient.publishEvent(new CustomEvent('sendInput', { detail: 'My own message' }));
*
* // main.html
* myContainer.addEventListener('custom-message', event => {
* console.log('My custom message from microfrontend', event.detail.data);
* }
*
* // Note: eventListeners.name must match CustomEvent name above
* // eventListeners.source = input1 = id of secondChild.js, which is where the message being sent from
* compoundConfig = {
* ...
* children: [
* {
* viewUrl: 'firstChild.js'
* ...
* eventListeners: [
* {
* source: 'input1',
* name: 'sendInput',
* action: 'update',
* dataConverter: data => {
* console.log(
* 'dataConverter(): Received Custom Message from "input1" MF ' + data
* );
* return 'new text: ' + data;
* }
* }
* ]
* },
* {
* viewUrl: 'secondChild.js',
* id: 'input1',
* }
*
*/
export function publishEvent(event) {}
Original file line number Diff line number Diff line change
Expand Up @@ -174,5 +174,26 @@ describe('Compound Container Tests', () => {

cy.get('#defer-init-flag').should('exist');
});

it('LuigiClient API publishEvent', () => {
cy.on('window:alert', stub);

// Set up a spy on console.log
cy.window().then(win => {
cy.spy(win.console, 'log').as('consoleLogSpy');
});

cy.get(containerSelector)
.shadow()
.contains('Publish event')
.click()
.then(() => {
expect(stub.getCall(0)).to.be.calledWith('sendInput');
cy.get('@consoleLogSpy').should(
'be.calledWith',
'dataConverter(): Received Custom Message from "input1" MF My own event data'
);
});
});
});
});
15 changes: 13 additions & 2 deletions container/cypress/e2e/test-app/wc/wc-container.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -137,12 +137,23 @@ describe('Web Container Test', () => {
.find('#customMessageDiv')
.should('have.text', 'Received Custom Message: ');

cy.get('#sendCustomMessageBtn')
.click()
cy.get('#sendCustomMessageBtn').click();
cy.get(containerSelector)
.shadow()
.find('#customMessageDiv')
.should('have.text', 'Received Custom Message: cool custom Message');
});

it('receive custom message from WC', () => {
cy.on('window:alert', stub);

cy.get('[data-test-id="luigi-client-api-test-01"]')
.shadow()
.contains('Publish event')
.click()
.then(() => {
expect(stub.getCall(0)).to.be.calledWith('My Custom Message from Microfrontend');
});
});
});
});
1 change: 1 addition & 0 deletions container/src/services/webcomponents.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,7 @@ export class WebComponentService {
},
publishEvent: ev => {
if (eventBusElement && eventBusElement.eventBus) {
// compound component use case only
eventBusElement.eventBus.onPublishEvent(ev, nodeId, wc_id);
}
const payload = {
Expand Down
8 changes: 6 additions & 2 deletions container/test-app/compound/compoundClientAPI.html
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,11 @@ <h3>
import MFEventID from '../bundle.js';

const compoundContainer = document.getElementById('dashboard');

compoundContainer.addEventListener(MFEventID.CUSTOM_MESSAGE, e => {
console.log('Publish Event', e.detail);
console.log('CUSTOM_MESSAGE Listener picked up: ', e.detail);
});

compoundContainer.compoundConfig = {
renderer: {
use: 'grid',
Expand Down Expand Up @@ -103,6 +105,9 @@ <h3>
name: 'sendInput',
action: 'update',
dataConverter: data => {
console.log(
'dataConverter(): Received Custom Message from "input1" MF ' + data
);
return 'new text: ' + data;
}
}
Expand Down Expand Up @@ -168,7 +173,6 @@ <h3>
}
);
compoundContainer.addEventListener(MFEventID.CUSTOM_MESSAGE, event => {
console.log('Custom Event', event);
if (event.detail.id !== 'timer') {
alert(event.detail.id);
}
Expand Down
16 changes: 9 additions & 7 deletions container/test-app/compound/helloWorldWC.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export default class extends HTMLElement {
current_locale.innerHTML = '<button id="current_locale">getCurrentLocale</button>';

const templateBtn2 = document.createElement('template');
templateBtn2.innerHTML = '<button class="button2">Publish event</button>';
templateBtn2.innerHTML = '<button id="publishEvent">Publish event</button>';

const addNodeParamsBtn = document.createElement('template');
addNodeParamsBtn.innerHTML = '<button id="addNodeParams">add node params</button>';
Expand Down Expand Up @@ -151,20 +151,22 @@ export default class extends HTMLElement {
});
}
});
this._shadowRoot.querySelector('.button2').addEventListener('click', () => {

this.$publishEventBtn = this._shadowRoot.querySelector('#publishEvent');
this.$publishEventBtn.addEventListener('click', () => {
if (this.LuigiClient) {
this.LuigiClient.publishEvent(new CustomEvent('btnClick'));
this.LuigiClient.publishEvent(new CustomEvent('sendInput', { detail: 'My own event data' }));
}
});

this.$button2 = this._shadowRoot.querySelector('#addNodeParams');
this.$button2.addEventListener('click', () => {
this.$addNodeParamsBtn = this._shadowRoot.querySelector('#addNodeParams');
this.$addNodeParamsBtn.addEventListener('click', () => {
if (this.LuigiClient) {
this.LuigiClient.addNodeParams({ Luigi: 'rocks' }, true);
}
});
this.$button3 = this._shadowRoot.querySelector('#getNodeParams');
this.$button3.addEventListener('click', () => {
this.$getNodeParamsBtn = this._shadowRoot.querySelector('#getNodeParams');
this.$getNodeParamsBtn.addEventListener('click', () => {
if (this.LuigiClient) {
let nodeParams = this.LuigiClient.getNodeParams(false);
this.LuigiClient.uxManager().showAlert({
Expand Down
17 changes: 11 additions & 6 deletions container/test-app/wc/clientAPI.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ <h3>
component based microfrontend
</h3>
<button id="luigi-update-context" type="button">Update context</button>
<button id="sendCustomMessageBtn" style="margin: 25px 0 15px">sendCustomMessage</button>
<button id="sendCustomMessageBtn" style="margin: 25px 0 15px">
sendCustomMessage
</button>

<div style="height: fit-content;">
<div style="border: 1px solid blue">
Expand Down Expand Up @@ -49,7 +51,7 @@ <h3>
defer-init="true"
></luigi-container>
</div>

<!-- Used for testing dynamic compound container creation -->
<div class="content"></div>

Expand All @@ -70,10 +72,14 @@ <h3>
deferInitContainer.init();
});
// document.querySelector('luigi-container');
const container = document.querySelector('[data-test-id="luigi-client-api-test-01"]')
const container = document.querySelector(
'[data-test-id="luigi-client-api-test-01"]'
);
const sendCustomMsgBtn = document.getElementById('sendCustomMessageBtn');
sendCustomMsgBtn.addEventListener('click', () => {
container.sendCustomMessage('custom-message-id', {dataToSend: 'cool custom Message'});
container.sendCustomMessage('custom-message-id', {
dataToSend: 'cool custom Message'
});
});

[...document.querySelectorAll('luigi-container')].forEach(luigiContainer => {
Expand All @@ -96,9 +102,8 @@ <h3>
}
);
luigiContainer.addEventListener(MFEventID.CUSTOM_MESSAGE, event => {
console.log('Custom Event', event);
if (event.detail.id !== 'timer') {
alert(event.detail.id);
alert(event.detail.data);
}
});

Expand Down
25 changes: 12 additions & 13 deletions container/test-app/wc/helloWorldWC.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export default class extends HTMLElement {
templateBtn.innerHTML = '<button id="aButton">Click me!</button>';

const templateBtn2 = document.createElement('template');
templateBtn2.innerHTML = '<button class="button2">Publish event</button>';
templateBtn2.innerHTML = '<button id="publishEvent">Publish event</button>';

const addNodeParamsBtn = document.createElement('template');
addNodeParamsBtn.innerHTML = '<button id="addNodeParams">add node params</button>';
Expand Down Expand Up @@ -90,7 +90,6 @@ export default class extends HTMLElement {

const customMessageDiv = document.createElement('template');
customMessageDiv.innerHTML = '<div id="customMessageDiv">Received Custom Message: </div>';


this._shadowRoot = this.attachShadow({
mode: 'open',
Expand Down Expand Up @@ -141,20 +140,21 @@ export default class extends HTMLElement {
});
}
});
this._shadowRoot.querySelector('.button2').addEventListener('click', () => {
this._shadowRoot.querySelector('#publishEvent').addEventListener('click', () => {
if (this.LuigiClient) {
this.LuigiClient.publishEvent(new CustomEvent('btnClick'));
// send a custom event (similar to sendCustomMessage)
this.LuigiClient.publishEvent(new CustomEvent('sendMSG', { detail: 'My Custom Message from Microfrontend' }));
}
});

this.$button2 = this._shadowRoot.querySelector('#addNodeParams');
this.$button2.addEventListener('click', () => {
this.$addNodeParamsBtn = this._shadowRoot.querySelector('#addNodeParams');
this.$addNodeParamsBtn.addEventListener('click', () => {
if (this.LuigiClient) {
this.LuigiClient.addNodeParams({ Luigi: 'rocks' }, true);
}
});
this.$button3 = this._shadowRoot.querySelector('#getNodeParams');
this.$button3.addEventListener('click', () => {
this.$getNodeParamsBtn = this._shadowRoot.querySelector('#getNodeParams');
this.$getNodeParamsBtn.addEventListener('click', () => {
if (this.LuigiClient) {
let nodeParams = this.LuigiClient.getNodeParams(false);
this.LuigiClient.uxManager().showAlert({
Expand Down Expand Up @@ -313,13 +313,12 @@ export default class extends HTMLElement {
}
});

this.addEventListener('custom-message-id', (event) => {
console.log('custom message received: ', event.detail)
this.addEventListener('custom-message-id', event => {
console.log('custom message received: ', event.detail);
const customMessageDiv = this._shadowRoot.querySelector('#customMessageDiv');
customMessageDiv.textContent = `Received Custom Message: ${event.detail.dataToSend}`;
customMessageDiv.style = "color: red;";
})

customMessageDiv.style = 'color: red;';
});
}

get context() {
Expand Down
66 changes: 66 additions & 0 deletions docs/luigi-client-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,72 @@ This document outlines the features provided by the Luigi Client API. It covers

Use the functions and parameters to define the Lifecycle of listeners, navigation nodes, and Event data.

#### publishEvent

<!-- label-success: Web Component API only-->

Publish an event that can be listened to from the container host.

Similar to [sendCustomMessage](luigi-client-api.md#sendCustomMessage) but for WebComponent based microfrontends only.

##### Parameters

* `event` **[CustomEvent](https://developer.mozilla.org/docs/Web/API/CustomEvent/CustomEvent)** Custom event to be published

##### Examples

```javascript
// case 1: publish an event from a WC based microfrontend

// wcComponent.js
// sending a message to parent host
this.LuigiClient.publishEvent(new CustomEvent('sendSomeMsg', { detail: 'My own message' }));

// host.html
myContainer.addEventListener('custom-message', event => {
console.log('My custom message from the microfrontend', event.detail.data);
}

// case 2: publish an event from a compound microfrontend

// secondChild.js
// Set the custom event name = 'sendInput' and
// send a message to its parent (main.html) and sibling (firstChild.js)
this.LuigiClient.publishEvent(new CustomEvent('sendInput', { detail: 'My own message' }));

// main.html
myContainer.addEventListener('custom-message', event => {
console.log('My custom message from microfrontend', event.detail.data);
}

// Note: eventListeners.name must match CustomEvent name above
// eventListeners.source = input1 = id of secondChild.js, which is where the message being sent from
compoundConfig = {
...
children: [
{
viewUrl: 'firstChild.js'
...
eventListeners: [
{
source: 'input1',
name: 'sendInput',
action: 'update',
dataConverter: data => {
console.log(
'dataConverter(): Received Custom Message from "input1" MF ' + data
);
return 'new text: ' + data;
}
}
]
},
{
viewUrl: 'secondChild.js',
id: 'input1',
}
```
#### isLuigiClientInitialized
Check if LuigiClient is initialized
Expand Down
2 changes: 1 addition & 1 deletion scripts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"docu:container:generate:container-api": "documentation readme ../container/typings/LuigiContainer.svelte.d.ts --parse-extension ts -f md --readme-file=../docs/luigi-container-api.md --section=\"API Reference\" --markdown-toc=false --quiet --github false",
"docu:container:generate:compound-container-api": "documentation readme ../container/typings/LuigiCompoundContainer.svelte.d.ts --parse-extension ts -f md --readme-file=../docs/luigi-compound-container-api.md --section=\"API Reference\" --markdown-toc=false --quiet --github false",
"docu:client": "npm run docu:client:validate && npm run docu:client:generate:section",
"docu:client:generate:section": "documentation readme ../client/src/luigi-client.js -f md --readme-file=../docs/luigi-client-api.md --section=\"API Reference\" --markdown-toc=false --quiet --github false",
"docu:client:generate:section": "documentation readme ../client/src/luigi-client.js ../client/luigi-client-wc-docu-mixin.js -f md --readme-file=../docs/luigi-client-api.md --section=\"API Reference\" --markdown-toc=false --quiet --github false",
"docu:client:validate": "documentation lint ../client/src/luigi-client.js",
"docu:core": "npm run docu:core:validate && npm run docu:core:generate:sections",
"docu:core:validate": "documentation lint --shallow ../core/src/core-api/config.js ../core/src/core-api/elements.js ../core/src/core-api/auth.js ../core/src/core-api/navigation.js ../core/src/core-api/i18n.js ../core/src/core-api/custom-messages.js ../core/src/core-api/ux.js ../core/src/core-api/globalsearch.js ../core/src/core-api/theming.js ../core/src/core-api/featuretoggles.js",
Expand Down

0 comments on commit 53e500e

Please sign in to comment.