@luigi-project/testing-utilities 2.13.1-dev.202406240829 → 2.13.1-dev.202406260026

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/README.md CHANGED
@@ -3,16 +3,14 @@
3
3
  The [Luigi Testing Utilities](https://github.com/SAP/luigi/tree/main/client-frameworks-support/testing-utilities) are a set of auxiliary functions used to enhance the user experience while testing Luigi-based micro frontends. The functions abstract away Luigi-specific logic from the tester so that it is easier for them to mock and assert Luigi functionality.
4
4
 
5
5
  ## LuigiMockUtil
6
- This class contains certain utility helper functions needed when writing e2e tests with different test frameworks. You can simply import this module into you project and then use an instance of it to test micro frontend functionality.
6
+ Since version 2.9.0 this class contains certain utility helper functions needed when writing e2e tests with Cypress or Protractor. You can simply import this module into you project and then use an instance of it to test micro frontend functionality.
7
7
  Before version 2.9.0 this class could only be used for [protractor-based](https://www.npmjs.com/package/protractor) e2e tests.
8
- Since version 2.9.0 this class supports both Cypress and Protractor.
9
- Since version 2.14.0 this class supports also Nightwatch, WebdriverIO and Puppeteer.
10
8
 
11
9
  ## How to use the library
12
10
 
13
11
  **Prerequisites:**
14
12
 
15
- _In order to use this utility library, you need to import LuigiMockModule into your Angular application's entry point - more details [here](https://docs.luigi-project.io/docs/framework-support-libraries/?section=luigicontextservice). You also have to install [Cypress](https://www.npmjs.com/package/cypress) or [Nightwatch](https://www.npmjs.com/package/nightwatch) or [WebdriverIO](https://www.npmjs.com/package/webdriverio) or [Puppeteer](https://www.npmjs.com/package/puppeteer) or [Protractor](https://www.npmjs.com/package/protractor) locally as a dev dependency for your project. Bear in mind Protractor is deprecated in Angular since version 15._
13
+ _In order to use this utility library, you need to import LuigiMockModule into your Angular application's entry point. See more [here](https://docs.luigi-project.io/docs/framework-support-libraries/?section=luigicontextservice). You also have to install [Cypress](https://www.npmjs.com/package/cypress) or [Protractor](https://www.npmjs.com/package/protractor) locally as a dev dependency for your project. Bear in mind Protractor is deprecated in Angular since version 15._
16
14
 
17
15
 
18
16
  1. Import the library in the `package.json`:
@@ -22,14 +20,14 @@ npm install @luigi-project/testing-utilities -s
22
20
 
23
21
  2. Once the library is imported and saved in your Angular project, you can now import the module `LuigiMockUtil` into your test:
24
22
  ```javascript
25
- import { LuigiMockUtil } from '@luigi-project/testing-utilities';
23
+ import { LuigiMockUtil } from "@luigi-project/testing-utilities";
26
24
  ```
27
25
 
28
26
  ### Example how to use the library with Protractor
29
27
 
30
28
  ```javascript
31
29
  import { browser } from 'protractor'; // <-- target e2e testing library
32
- import { LuigiMockUtil } from '@luigi-project/testing-utilities';
30
+ import { LuigiMockUtil } from "@luigi-project/testing-utilities";
33
31
 
34
32
  describe('Another test using protractor', () => {
35
33
  let luigiMockUtil: LuigiMockUtil;
@@ -50,7 +48,7 @@ describe('Another test using protractor', () => {
50
48
  ### Example how to use the library with Cypress
51
49
 
52
50
  ```javascript
53
- import { LuigiMockUtil } from '@luigi-project/testing-utilities';
51
+ import { LuigiMockUtil } from "@luigi-project/testing-utilities";
54
52
 
55
53
  describe('Another test using cypress', () => {
56
54
  let luigiMockUtil: LuigiMockUtil;
@@ -97,154 +95,6 @@ describe('Another test using cypress', () => {
97
95
  });
98
96
  ```
99
97
 
100
- ### Example how to use the library with Nightwatch
101
-
102
- ```javascript
103
- import { browser } from 'nightwatch'; // <-- target e2e testing library
104
- import { LuigiMockUtil } from '@luigi-project/testing-utilities';
105
-
106
- describe('Another test using nightwatch', function () {
107
- const luigiMockUtil: LuigiMockUtil = new LuigiMockUtil(browser);
108
-
109
- before((browser) => browser.navigateTo('http://localhost:4200'));
110
-
111
- it('should mock path exists', async () => {
112
- // Be sure '.pathExists' element is present
113
- await browser.expect.element('.pathExists').to.be.present;
114
- await browser.element('.pathExists').click().then(() => {
115
- luigiMockUtil.mockPathExists('/test', false);
116
- browser.execute(() => window.sessionStorage.getItem('luigiMockData'), [], function (result) {
117
- expect(result.value).to.contains('{"pathExists":{"/test":false}}');
118
- });
119
- });
120
- });
121
-
122
- it('should mock context update', async () => {
123
- const context = {ctxKey: 'ctxValue'};
124
-
125
- await luigiMockUtil.mockContext(context);
126
- // Wait until '#luigi-debug-vis-cnt' element is present
127
- await browser.waitForElementPresent('#luigi-debug-vis-cnt', undefined, undefined, false, () => {
128
- const wrapper = browser.expect.element('#luigi-debug-vis-cnt');
129
-
130
- wrapper.to.be.present;
131
- wrapper.text.to.contains('{"msg":"luigi.get-context","context":{"ctxKey":"ctxValue"}}');
132
- });
133
- });
134
-
135
- after((browser) => browser.end());
136
- });
137
- ```
138
-
139
- ### Example how to use the library with WebdriverIO
140
-
141
- ```javascript
142
- import { browser } from '@wdio/globals'; // <-- target e2e testing library
143
- import { LuigiMockUtil } from '@luigi-project/testing-utilities';
144
-
145
- describe('Another test using webdriverio', () => {
146
- const baseUrl = 'http://localhost:4200';
147
- const defaultTimeout = { 'implicit': 500 };
148
- let luigiMockUtil: LuigiMockUtil;
149
-
150
- it('should mock path exists', async () => {
151
- luigiMockUtil = new LuigiMockUtil(browser);
152
-
153
- await browser.url(baseUrl);
154
- // Be sure '.pathExists' element is present
155
- await $('.pathExists').click().then(() => {
156
- luigiMockUtil.mockPathExists('/test', false);
157
- });
158
- // Wait until session storage item is set
159
- await browser.setTimeout(defaultTimeout);
160
-
161
- const result = await browser.execute(() => window.sessionStorage.getItem('luigiMockData'));
162
-
163
- await expect(result).toEqual('{"pathExists":{"/test":false}}');
164
- });
165
-
166
- it('should mock context update', async () => {
167
- luigiMockUtil = new LuigiMockUtil(browser);
168
-
169
- const context = {ctxKey: 'ctxValue'};
170
-
171
- await browser.url(baseUrl);
172
- await luigiMockUtil.mockContext(context);
173
- // Wait until '#luigi-debug-vis-cnt' element is present
174
- await browser.setTimeout(defaultTimeout);
175
- await expect($('#luigi-debug-vis-cnt')).toHaveHTML(expect.stringContaining('{"msg":"luigi.get-context","context":{"ctxKey":"ctxValue"}}'));
176
- });
177
- });
178
- ```
179
-
180
- ### Example how to use the library with Puppeteer
181
-
182
- ```javascript
183
- import * as puppeteer from 'puppeteer'; // <-- target e2e testing library
184
- import { LuigiMockUtil } from '@luigi-project/testing-utilities';
185
-
186
- let luigiMockUtil: LuigiMockUtil;
187
- let browser: puppeteer.Browser;
188
- let page: puppeteer.Page;
189
-
190
- describe('Another test using puppeteer ->', () => {
191
- beforeAll(async () => {
192
- browser = await puppeteer.launch({
193
- args: ['--no-sandbox'],
194
- headless: false,
195
- ignoreDefaultArgs: ['--disable-extensions'],
196
- });
197
- });
198
-
199
- beforeEach(async () => {
200
- page = await browser.newPage();
201
- luigiMockUtil = new LuigiMockUtil(page);
202
-
203
- await page?.goto('http://localhost:4200', {timeout: 0});
204
- });
205
-
206
- afterEach(async () => {
207
- await page?.close();
208
- });
209
-
210
- afterAll(async () => {
211
- await browser?.close();
212
- });
213
-
214
- it('should mock path exists', async () => {
215
- // Be sure '.pathExists' element is present
216
- await page.waitForSelector('.pathExists').then(async () => {
217
- await expect(page.locator('.pathExists').wait()).toBeTruthy();
218
-
219
- await page.click('.pathExists').then(async () => {
220
- await luigiMockUtil.mockPathExists('/test', false);
221
- // Wait until session storage item is set
222
- await new Promise(resolve => setTimeout(resolve, 500));
223
-
224
- const result = await page.evaluate(() => window.sessionStorage.getItem('luigiMockData'));
225
-
226
- await expect(result).toContain('{"pathExists":{"/test":false}}');
227
- });
228
- });
229
- });
230
-
231
- it('should mock context update', async () => {
232
- const context = {ctxKey: 'ctxValue'};
233
-
234
- await luigiMockUtil.mockContext(context);
235
- // Wait until '#luigi-debug-vis-cnt' element is present
236
- await page.waitForSelector('#luigi-debug-vis-cnt').then(async () => {
237
- const result = await page
238
- .locator('#luigi-debug-vis-cnt div:nth-child(1)')
239
- .map(div => div.innerText)
240
- .wait();
241
-
242
- expect(result).toContain('{"msg":"luigi.get-context","context":{"ctxKey":"ctxValue"}}');
243
- });
244
- });
245
- });
246
- ```
247
-
248
98
  #### Functions provided
249
99
  - **mockContext**: Mocks the context by sending Luigi context messages with the desired mocked context as parameter.
250
100
  - **mockPathExists**: This method serves as a mock for the Luigi Client `pathExists()` function. It is used in e2e tests when component being tested utilizes a call to `LuigiClient.linkManager().pathExists()`
@@ -17,7 +17,7 @@ export declare class LuigiMockUtil {
17
17
  * Mocks the context by sending luigi context messages with the desired mocked context as parameter.
18
18
  * @param mockContext an object representing the context to be mocked
19
19
  */
20
- mockContext: (mockContext: Record<string, any>) => void;
20
+ mockContext: (mockContext: any) => void;
21
21
  /**
22
22
  * This method serves as a mock for the luigi client pathExists() function.
23
23
  * It is used in e2e tests when component being tested utilizes a call to `LuigiClient.linkManager().pathExists()`
@@ -5,29 +5,21 @@ export class LuigiMockUtil {
5
5
  * @param mockContext an object representing the context to be mocked
6
6
  */
7
7
  this.mockContext = (mockContext) => {
8
- const window = this.getGlobalThis();
9
- const postMessageToLuigi = (context) => {
10
- window.postMessage({ msg: 'luigi.get-context', context }, '*');
11
- return Object.assign(Object.assign({}, context), { windowMessage: 'isPosted' });
8
+ const context = mockContext;
9
+ const targetDocument = this.getGlobalThis();
10
+ const postMessageToLuigi = () => {
11
+ targetDocument.postMessage({ msg: 'luigi.get-context', context }, '*');
12
12
  };
13
13
  try {
14
- switch (true) {
15
- case 'evaluate' in this.browser:
16
- this.browser.evaluate(postMessageToLuigi, mockContext);
17
- break;
18
- case 'execute' in this.browser:
19
- this.browser.execute(postMessageToLuigi, mockContext);
20
- break;
21
- case 'executeScript' in this.browser:
22
- this.browser.executeScript(postMessageToLuigi, mockContext);
23
- break;
24
- default:
25
- this.browser(postMessageToLuigi.bind(this, mockContext));
26
- break;
14
+ if (this.browser.executeScript) {
15
+ this.browser.executeScript(postMessageToLuigi, context);
16
+ }
17
+ else {
18
+ this.browser(postMessageToLuigi);
27
19
  }
28
20
  }
29
- catch (error) {
30
- console.debug('Failed to mock context: ', error);
21
+ catch (e) {
22
+ console.debug('Failed to mock context: ', e);
31
23
  }
32
24
  };
33
25
  /**
@@ -47,42 +39,32 @@ export class LuigiMockUtil {
47
39
  *
48
40
  */
49
41
  this.mockPathExists = (path, exists) => {
50
- const window = this.getGlobalThis();
51
- const mockContext = { path, exists };
42
+ const targetDocument = this.getGlobalThis();
52
43
  /**
53
44
  * Sets the path exists mock data in sessionStorage.
54
45
  * @param {string} path - The path for which mock data is to be set.
55
46
  * @param {boolean} exists - Boolean indicating whether the path exists.
56
- * @returns {Object} - Object indicating session storage item.
47
+ * @returns {void}
57
48
  */
58
- const setPathExistsMockData = (context) => {
59
- window.sessionStorage.clear();
60
- const pathExistsMockData = {
49
+ const setPathExistsMockData = () => {
50
+ targetDocument.sessionStorage.clear();
51
+ let pathExistsMockData = {
61
52
  pathExists: {
62
- [context['path']]: context['exists']
53
+ [path]: exists
63
54
  }
64
55
  };
65
- window.sessionStorage.setItem('luigiMockData', JSON.stringify(pathExistsMockData));
66
- return Object.assign(Object.assign({}, pathExistsMockData), { sessionItem: 'isStored' });
56
+ targetDocument.sessionStorage.setItem('luigiMockData', JSON.stringify(pathExistsMockData));
67
57
  };
68
58
  try {
69
- switch (true) {
70
- case 'evaluate' in this.browser:
71
- this.browser.evaluate(setPathExistsMockData, mockContext);
72
- break;
73
- case 'execute' in this.browser:
74
- this.browser.execute(setPathExistsMockData, mockContext);
75
- break;
76
- case 'executeScript' in this.browser:
77
- this.browser.executeScript(setPathExistsMockData, mockContext);
78
- break;
79
- default:
80
- this.browser(setPathExistsMockData.bind(this, mockContext));
81
- break;
59
+ if (this.browser.executeScript) {
60
+ this.browser.executeScript(setPathExistsMockData, path, exists);
61
+ }
62
+ else {
63
+ this.browser(setPathExistsMockData, path, exists);
82
64
  }
83
65
  }
84
- catch (error) {
85
- console.debug('Failed to mock path exists: ', error);
66
+ catch (e) {
67
+ console.debug('Failed to mock path exists: ', e);
86
68
  }
87
69
  };
88
70
  this.messages = [];
@@ -101,27 +83,15 @@ export class LuigiMockUtil {
101
83
  * @returns {Promise<void>} - A Promise that resolves when parsing is complete.
102
84
  */
103
85
  async parseLuigiMockedMessages() {
104
- const window = this.getGlobalThis();
105
- const getTextNodeValues = () => {
106
- const debugCtn = window.getElementById('luigi-debug-vis-cnt');
107
- return Array.from((debugCtn === null || debugCtn === void 0 ? void 0 : debugCtn.childNodes) || []).map((item) => item.textContent || '');
108
- };
109
- let textElements;
110
86
  try {
111
- switch (true) {
112
- case 'evaluate' in this.browser:
113
- this.browser.evaluate(getTextNodeValues);
114
- break;
115
- case 'execute' in this.browser:
116
- this.browser.execute(getTextNodeValues);
117
- break;
118
- case 'executeScript' in this.browser:
119
- this.browser.executeScript(getTextNodeValues);
120
- break;
121
- default:
122
- this.browser(getTextNodeValues);
123
- break;
124
- }
87
+ const getTextNodeValues = () => {
88
+ const targetDocument = this.getGlobalThis();
89
+ const debugCtn = targetDocument.getElementById('luigi-debug-vis-cnt');
90
+ return Array.from((debugCtn === null || debugCtn === void 0 ? void 0 : debugCtn.childNodes) || []).map((item) => item.textContent || '');
91
+ };
92
+ const textElements = this.browser.executeScript
93
+ ? await this.browser.executeScript(getTextNodeValues)
94
+ : await this.browser(getTextNodeValues);
125
95
  this.messages = textElements
126
96
  .map((item) => {
127
97
  try {
@@ -133,8 +103,8 @@ export class LuigiMockUtil {
133
103
  })
134
104
  .filter((item) => item !== undefined);
135
105
  }
136
- catch (error) {
137
- console.debug('Failed to parse luigi mocked messages: ', error);
106
+ catch (e) {
107
+ console.debug('Failed to parse luigi mocked messages: ', e);
138
108
  }
139
109
  }
140
110
  /**
package/package.json CHANGED
@@ -19,7 +19,7 @@
19
19
  "microfrontends",
20
20
  "testing"
21
21
  ],
22
- "version": "2.13.1-dev.202406240829",
22
+ "version": "2.13.1-dev.202406260026",
23
23
  "engines": {
24
24
  "node": ">=18"
25
25
  }