@luigi-project/testing-utilities 1.24.1-dev.20220992341 → 1.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.d.ts +2 -1
- package/index.js +2 -6
- package/luigi-mock-engine.d.ts +4 -0
- package/luigi-mock-engine.js +152 -0
- package/luigi-mock-util.js +36 -54
- package/package.json +2 -2
- package/index.js.map +0 -1
- package/luigi-mock-util.js.map +0 -1
package/index.d.ts
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
export { LuigiMockUtil } from './luigi-mock-util';
|
|
1
|
+
export { LuigiMockUtil } from './luigi-mock-util.js';
|
|
2
|
+
export { LuigiMockEngine } from './luigi-mock-engine.js';
|
package/index.js
CHANGED
|
@@ -1,6 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
exports.LuigiMockUtil = void 0;
|
|
4
|
-
var luigi_mock_util_1 = require("./luigi-mock-util");
|
|
5
|
-
Object.defineProperty(exports, "LuigiMockUtil", { enumerable: true, get: function () { return luigi_mock_util_1.LuigiMockUtil; } });
|
|
6
|
-
//# sourceMappingURL=index.js.map
|
|
1
|
+
export { LuigiMockUtil } from './luigi-mock-util.js';
|
|
2
|
+
export { LuigiMockEngine } from './luigi-mock-engine.js';
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* This class mocks Luigi Core related functionality.
|
|
3
|
+
*
|
|
4
|
+
* Micro Frontends that use Luigi Client would usually communicate with Luigi Core
|
|
5
|
+
* back and forth. When testing Luigi Client based components, Luigi Core might
|
|
6
|
+
* not be present which leads into limitations on integration/e2e testing for standalone
|
|
7
|
+
* microfrontends.
|
|
8
|
+
*
|
|
9
|
+
* This module adds a hook to the window postMessage API by adding an event listener to the
|
|
10
|
+
* global message event of the window object and mocking the callback.
|
|
11
|
+
* In the normal workflow this message would picked up by Luigi Core which then sends the response back.
|
|
12
|
+
*/
|
|
13
|
+
export class LuigiMockEngine {
|
|
14
|
+
// Add a hook to the post message api to mock the LuigiCore response to the Client
|
|
15
|
+
static initPostMessageHook() {
|
|
16
|
+
return async () => {
|
|
17
|
+
// Check if Luigi Client is running standalone
|
|
18
|
+
if (window.parent === window) {
|
|
19
|
+
console.debug('Detected standalone mode');
|
|
20
|
+
// Check and skip if Luigi environment is already mocked
|
|
21
|
+
if (window.luigiMockEnvironment) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
// mock target origin
|
|
25
|
+
if (window.LuigiClient) {
|
|
26
|
+
window.LuigiClient.setTargetOrigin('*');
|
|
27
|
+
}
|
|
28
|
+
window.luigiMockEnvironment = {
|
|
29
|
+
msgListener: function (e) {
|
|
30
|
+
if (e.data.msg && (e.data.msg.startsWith('luigi.') || e.data.msg === 'storage')) {
|
|
31
|
+
console.debug('Luigi msg', e.data);
|
|
32
|
+
if (e.data.msg === 'luigi.get-context') {
|
|
33
|
+
window.postMessage({
|
|
34
|
+
msg: 'luigi.init',
|
|
35
|
+
emulated: true,
|
|
36
|
+
internal: {
|
|
37
|
+
viewStackSize: 1
|
|
38
|
+
},
|
|
39
|
+
context: e.data.context
|
|
40
|
+
}, '*');
|
|
41
|
+
}
|
|
42
|
+
// vizualise retrieved event data
|
|
43
|
+
LuigiMockEngine.visualize(JSON.stringify(e.data));
|
|
44
|
+
// Check and run mocked callback if it exists
|
|
45
|
+
const mockListener = window.luigiMockEnvironment.mockListeners[e.data.msg];
|
|
46
|
+
if (mockListener) {
|
|
47
|
+
mockListener(e);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
mockListeners: {
|
|
52
|
+
'luigi.navigation.pathExists': (event) => {
|
|
53
|
+
const mockData = window.sessionStorage.getItem('luigiMockData');
|
|
54
|
+
let mockDataParsed = mockData ? JSON.parse(mockData) : undefined;
|
|
55
|
+
const inputPath = event.data.data.link;
|
|
56
|
+
const pathExists = mockDataParsed && mockDataParsed.pathExists && mockDataParsed.pathExists[inputPath];
|
|
57
|
+
const response = {
|
|
58
|
+
msg: 'luigi.navigation.pathExists.answer',
|
|
59
|
+
data: {
|
|
60
|
+
correlationId: event.data.data.id,
|
|
61
|
+
pathExists: pathExists ? pathExists : false
|
|
62
|
+
},
|
|
63
|
+
emulated: true
|
|
64
|
+
};
|
|
65
|
+
window.postMessage(response, '*');
|
|
66
|
+
},
|
|
67
|
+
//ux
|
|
68
|
+
'luigi.ux.confirmationModal.show': (event) => {
|
|
69
|
+
const response = {
|
|
70
|
+
msg: 'luigi.ux.confirmationModal.hide',
|
|
71
|
+
data: event.data,
|
|
72
|
+
emulated: true
|
|
73
|
+
};
|
|
74
|
+
window.postMessage(response, '*');
|
|
75
|
+
},
|
|
76
|
+
'luigi.ux.alert.show': (event) => {
|
|
77
|
+
const response = {
|
|
78
|
+
msg: 'luigi.ux.alert.hide',
|
|
79
|
+
data: event.data,
|
|
80
|
+
emulated: true
|
|
81
|
+
};
|
|
82
|
+
window.postMessage(response, '*');
|
|
83
|
+
},
|
|
84
|
+
'luigi.ux.set-current-locale': (event) => {
|
|
85
|
+
const response = {
|
|
86
|
+
msg: 'luigi.current-locale-changed',
|
|
87
|
+
currentLocale: event.data.data.currentLocale,
|
|
88
|
+
emulated: true
|
|
89
|
+
};
|
|
90
|
+
window.postMessage(response, '*');
|
|
91
|
+
},
|
|
92
|
+
// linkManager
|
|
93
|
+
'luigi.navigation.open': (event) => {
|
|
94
|
+
const response = {
|
|
95
|
+
msg: 'luigi.navigate.ok',
|
|
96
|
+
data: event.data,
|
|
97
|
+
emulated: true
|
|
98
|
+
};
|
|
99
|
+
window.postMessage(response, '*');
|
|
100
|
+
},
|
|
101
|
+
'luigi.navigation.splitview.close': (event) => {
|
|
102
|
+
const response = {
|
|
103
|
+
msg: 'luigi.navigate.ok',
|
|
104
|
+
data: event.data,
|
|
105
|
+
emulated: true
|
|
106
|
+
};
|
|
107
|
+
window.postMessage(response, '*');
|
|
108
|
+
},
|
|
109
|
+
'luigi.navigation.splitview.collapse': (event) => {
|
|
110
|
+
const response = {
|
|
111
|
+
msg: 'luigi.navigate.ok',
|
|
112
|
+
data: event.data,
|
|
113
|
+
emulated: true
|
|
114
|
+
};
|
|
115
|
+
window.postMessage(response, '*');
|
|
116
|
+
},
|
|
117
|
+
'luigi.navigation.splitview.expand': (event) => {
|
|
118
|
+
const response = {
|
|
119
|
+
msg: 'luigi.navigate.ok',
|
|
120
|
+
data: event.data,
|
|
121
|
+
emulated: true
|
|
122
|
+
};
|
|
123
|
+
window.postMessage(response, '*');
|
|
124
|
+
},
|
|
125
|
+
// storage
|
|
126
|
+
storage: () => { }
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
// Listen to the global 'message' event of the window object
|
|
130
|
+
window.addEventListener('message', window.luigiMockEnvironment.msgListener);
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
/*
|
|
135
|
+
* This method takes a data object of type 'any' and vizualizes a simple container
|
|
136
|
+
* which holds data that is useful for e2e testing.
|
|
137
|
+
*/
|
|
138
|
+
static visualize(data) {
|
|
139
|
+
let luigiVisualizationContainer = document.querySelector('#luigi-debug-vis-cnt');
|
|
140
|
+
// Construct element structure if not already constructed
|
|
141
|
+
if (!luigiVisualizationContainer) {
|
|
142
|
+
luigiVisualizationContainer = document.createElement('div');
|
|
143
|
+
luigiVisualizationContainer.setAttribute('id', 'luigi-debug-vis-cnt');
|
|
144
|
+
// Hide the added DOM element to avoid interferring/overlapping with other elements during testing.
|
|
145
|
+
luigiVisualizationContainer.setAttribute('style', 'display:none');
|
|
146
|
+
document.body.appendChild(luigiVisualizationContainer);
|
|
147
|
+
}
|
|
148
|
+
const line = document.createElement('div');
|
|
149
|
+
line.textContent = data;
|
|
150
|
+
luigiVisualizationContainer.appendChild(line);
|
|
151
|
+
}
|
|
152
|
+
}
|
package/luigi-mock-util.js
CHANGED
|
@@ -1,16 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.LuigiMockUtil = void 0;
|
|
13
|
-
class LuigiMockUtil {
|
|
1
|
+
export class LuigiMockUtil {
|
|
14
2
|
constructor(browser) {
|
|
15
3
|
/**
|
|
16
4
|
* Mocks the context by sending luigi context messegaes with the desired mocked context as parameter.
|
|
@@ -54,25 +42,23 @@ class LuigiMockUtil {
|
|
|
54
42
|
/**
|
|
55
43
|
* Parses the elements added by LuigiMockModule into the DOM and assigns them to the local this.messages variable
|
|
56
44
|
*/
|
|
57
|
-
parseLuigiMockedMessages() {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
}
|
|
75
|
-
});
|
|
45
|
+
async parseLuigiMockedMessages() {
|
|
46
|
+
try {
|
|
47
|
+
const textElements = await this.browser.executeScript(() => Array.from(document.getElementById('luigi-debug-vis-cnt').childNodes).map(item => item.textContent));
|
|
48
|
+
this.messages = textElements
|
|
49
|
+
.map((item) => {
|
|
50
|
+
try {
|
|
51
|
+
return JSON.parse(item);
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
return undefined;
|
|
55
|
+
}
|
|
56
|
+
})
|
|
57
|
+
.filter(item => item !== undefined);
|
|
58
|
+
}
|
|
59
|
+
catch (e) {
|
|
60
|
+
console.debug('Failed to parse luigi mocked messages: ', e);
|
|
61
|
+
}
|
|
76
62
|
}
|
|
77
63
|
/**
|
|
78
64
|
* Checks on the printed DOM Luigi message responses for a modal with given title
|
|
@@ -100,29 +86,27 @@ class LuigiMockUtil {
|
|
|
100
86
|
* }
|
|
101
87
|
*
|
|
102
88
|
*/
|
|
103
|
-
modalOpenedWithTitle(title) {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
const
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
return message.params.modal.title === title;
|
|
117
|
-
}
|
|
118
|
-
return false;
|
|
119
|
-
});
|
|
120
|
-
if (indexFoundModalMessageWTitle >= 0) {
|
|
121
|
-
return true;
|
|
89
|
+
async modalOpenedWithTitle(title) {
|
|
90
|
+
// parse messages into a readable array
|
|
91
|
+
await this.parseLuigiMockedMessages();
|
|
92
|
+
// traverse the array and find the modal message response
|
|
93
|
+
// check if its modal option has the title
|
|
94
|
+
const indexFoundModalMessageWTitle = this.messages.findIndex(message => {
|
|
95
|
+
const msgExists = message.msg &&
|
|
96
|
+
message.msg === 'luigi.navigation.open' &&
|
|
97
|
+
message.params &&
|
|
98
|
+
message.params.modal &&
|
|
99
|
+
message.params.modal.title;
|
|
100
|
+
if (msgExists) {
|
|
101
|
+
return message.params.modal.title === title;
|
|
122
102
|
}
|
|
123
|
-
console.debug('Could not find modal with title: ', title);
|
|
124
103
|
return false;
|
|
125
104
|
});
|
|
105
|
+
if (indexFoundModalMessageWTitle >= 0) {
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
console.debug('Could not find modal with title: ', title);
|
|
109
|
+
return false;
|
|
126
110
|
}
|
|
127
111
|
/**
|
|
128
112
|
* Return list of messages, representing message elements added in the DOM for testing.
|
|
@@ -131,5 +115,3 @@ class LuigiMockUtil {
|
|
|
131
115
|
return this.messages;
|
|
132
116
|
}
|
|
133
117
|
}
|
|
134
|
-
exports.LuigiMockUtil = LuigiMockUtil;
|
|
135
|
-
//# sourceMappingURL=luigi-mock-util.js.map
|
package/package.json
CHANGED
package/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,qDAAkD;AAAzC,gHAAA,aAAa,OAAA"}
|
package/luigi-mock-util.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"luigi-mock-util.js","sourceRoot":"","sources":["../src/luigi-mock-util.ts"],"names":[],"mappings":"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"}
|