monocart-reporter 2.1.0 → 2.2.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/README.md +109 -203
- package/lib/default/options.js +4 -1
- package/lib/generate-report.js +2 -2
- package/lib/index.d.ts +5 -5
- package/lib/index.js +10 -12
- package/lib/packages/monocart-common.js +1 -1
- package/lib/packages/monocart-network.js +1 -1
- package/lib/packages/monocart-reporter-app.js +1 -0
- package/lib/packages/monocart-vendor.js +12 -19
- package/lib/platform/share.js +0 -1
- package/lib/plugins/comments.js +33 -34
- package/lib/visitor.js +6 -7
- package/package.json +7 -7
- package/lib/packages/monocart-reporter.js +0 -1
- package/lib/utils/parse-source.js +0 -19
package/README.md
CHANGED
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
[](https://www.npmjs.com/package/monocart-reporter)
|
|
4
4
|
[](https://www.npmjs.com/package/monocart-reporter)
|
|
5
5
|

|
|
6
|
+

|
|
7
|
+
|
|
6
8
|
|
|
7
9
|
* A [Playwright](https://github.com/microsoft/playwright) Test [Reporter](https://playwright.dev/docs/test-reporters) (Node.js)
|
|
8
10
|
- Shows Test Report in A `Tree Grid`
|
|
@@ -15,28 +17,25 @@
|
|
|
15
17
|
* [Install](#install)
|
|
16
18
|
* [Playwright Config](#playwright-config)
|
|
17
19
|
* [Examples](#examples)
|
|
18
|
-
* [Output](#output)
|
|
20
|
+
* [Output](#output)
|
|
19
21
|
* [Reporter Options](#reporter-options)
|
|
20
22
|
* [View Trace Online](#view-trace-online)
|
|
21
|
-
* [Custom
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
* [Custom Fields Report](#custom-fields-report)
|
|
24
|
+
* [Custom Columns](#custom-columns)
|
|
25
|
+
- [Column Formatter](#column-formatter)
|
|
26
|
+
- [Searchable Fields](#searchable-fields)
|
|
27
|
+
* [Custom Fields in Comments](#custom-fields-in-comments)
|
|
28
|
+
* [Custom Data Visitor](#custom-data-visitor)
|
|
29
|
+
- [Collect Data from the Title](#collect-data-from-the-title)
|
|
30
|
+
- [Collect Data from the Annotations](#collect-data-from-the-annotations)
|
|
31
|
+
- [Remove Secrets and Sensitive Data](#remove-secrets-and-sensitive-data)
|
|
29
32
|
* [Style Tags](#style-tags)
|
|
30
33
|
* [Metadata](#metadata)
|
|
31
34
|
* [Trend Chart](#trend-chart)
|
|
32
35
|
* [Attach Lighthouse Audit Report](#attach-lighthouse-audit-report)
|
|
33
36
|
* [Code Coverage Report](#code-coverage-report)
|
|
34
|
-
- [Coverage Options](#coverage-options)
|
|
35
|
-
- [Istanbul](#istanbul)
|
|
36
|
-
- [V8](#v8)
|
|
37
|
-
- [V8 to Istanbul](#v8-to-istanbul)
|
|
38
|
-
- [Istanbul vs V8](#istanbul-vs-v8)
|
|
39
37
|
- [Global Coverage Report](#global-coverage-report)
|
|
38
|
+
- [Coverage Options](#coverage-options)
|
|
40
39
|
- [Coverage Examples](#coverage-examples)
|
|
41
40
|
* [Attach Network Report](#attach-network-report)
|
|
42
41
|
* [Global State Management](#global-state-management)
|
|
@@ -161,7 +160,10 @@ Separated metadata file (Already included in the above HTML and compressed, it c
|
|
|
161
160
|
|
|
162
161
|
// rows data handler (suite, case and step)
|
|
163
162
|
visitor: null,
|
|
164
|
-
// visitor: (data, metadata
|
|
163
|
+
// visitor: (data, metadata) => {},
|
|
164
|
+
|
|
165
|
+
// enable/disable custom fields in comments. Defaults to true.
|
|
166
|
+
customFieldsInComments: true,
|
|
165
167
|
|
|
166
168
|
// onEnd hook
|
|
167
169
|
onEnd: null
|
|
@@ -180,7 +182,12 @@ npx monocart serve-report <your-outputFile-path>
|
|
|
180
182
|
```
|
|
181
183
|
Or customize your own trace viewer url with option `traceViewerUrl` defaults to `https://trace.playwright.dev/?trace={traceUrl}`
|
|
182
184
|
|
|
183
|
-
## Custom
|
|
185
|
+
## Custom Fields Report
|
|
186
|
+
You can add custom fields to the report. for example: Owner, JIRA Key etc.
|
|
187
|
+
- First, you need to add [Custom Columns](#custom-columns) for the fields.
|
|
188
|
+
- Then, collect data for these fields with [Custom Fields in Comments](#custom-fields-in-comments) or [Custom Data Visitor](#custom-data-visitor)
|
|
189
|
+
|
|
190
|
+
### Custom Columns
|
|
184
191
|
The report will be displayed in a `Tree Grid`. The `columns` function is used to customize the grid columns. The column properties following:
|
|
185
192
|
- `id` (String) Column id (required)
|
|
186
193
|
- `name` (String) Column name, shows in grid header
|
|
@@ -235,7 +242,7 @@ module.exports = {
|
|
|
235
242
|
]
|
|
236
243
|
};
|
|
237
244
|
```
|
|
238
|
-
|
|
245
|
+
#### Column Formatter
|
|
239
246
|
> Note: The `formatter` function will be serialized into string via JSON, so closures, contexts, etc. will not work!
|
|
240
247
|
```js
|
|
241
248
|
// playwright.config.js
|
|
@@ -274,7 +281,7 @@ module.exports = {
|
|
|
274
281
|
};
|
|
275
282
|
```
|
|
276
283
|
|
|
277
|
-
|
|
284
|
+
#### Searchable Fields
|
|
278
285
|
```js
|
|
279
286
|
// playwright.config.js
|
|
280
287
|
module.exports = {
|
|
@@ -291,112 +298,25 @@ module.exports = {
|
|
|
291
298
|
};
|
|
292
299
|
```
|
|
293
300
|
|
|
294
|
-
|
|
295
|
-
The `visitor` function will be executed for each row item (suite, case and step). Arguments:
|
|
296
|
-
- `data` data item (suite/case/step) for reporter, you can rewrite some of its properties or add more
|
|
297
|
-
- `metadata` original data object from Playwright test, could be one of [Suite](https://playwright.dev/docs/api/class-suite), [TestCase](https://playwright.dev/docs/api/class-testcase) or [TestStep](https://playwright.dev/docs/api/class-teststep)
|
|
298
|
-
- `collect` see [collect data from the comments](#collect-data-from-the-comments)
|
|
299
|
-
|
|
300
|
-
### Collect Data from the Title
|
|
301
|
-
For example, we want to parse out the jira key from the title:
|
|
302
|
-
```js
|
|
303
|
-
test('[MCR-123] collect data from the title', () => {
|
|
304
|
-
|
|
305
|
-
});
|
|
306
|
-
```
|
|
307
|
-
You can simply use regular expressions to parse and get jira key:
|
|
308
|
-
```js
|
|
309
|
-
// playwright.config.js
|
|
310
|
-
module.exports = {
|
|
311
|
-
reporter: [
|
|
312
|
-
['monocart-reporter', {
|
|
313
|
-
name: "My Test Report",
|
|
314
|
-
outputFile: './test-results/report.html',
|
|
315
|
-
visitor: (data, metadata, collect) => {
|
|
316
|
-
// [MCR-123] collect data from the title
|
|
317
|
-
const matchResult = metadata.title.match(/\[(.+)\]/);
|
|
318
|
-
if (matchResult && matchResult[1]) {
|
|
319
|
-
data.jira = matchResult[1];
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
}]
|
|
323
|
-
]
|
|
324
|
-
};
|
|
325
|
-
```
|
|
326
|
-
multiple matches example: [collect-data](https://github.com/cenfun/monocart-reporter-test/tree/main/tests/collect-data)
|
|
327
|
-
|
|
328
|
-
### Collect Data from the Annotations
|
|
329
|
-
It should be easier than getting from title. see [custom annotations](https://playwright.dev/docs/test-annotations#custom-annotations) via `test.info().annotations`
|
|
330
|
-
```js
|
|
331
|
-
test('collect data from the annotations', () => {
|
|
332
|
-
test.info().annotations.push({
|
|
333
|
-
type: "jira",
|
|
334
|
-
description: "MCR-123"
|
|
335
|
-
})
|
|
336
|
-
});
|
|
337
|
-
```
|
|
338
|
-
```js
|
|
339
|
-
// playwright.config.js
|
|
340
|
-
module.exports = {
|
|
341
|
-
reporter: [
|
|
342
|
-
['monocart-reporter', {
|
|
343
|
-
name: "My Test Report",
|
|
344
|
-
outputFile: './test-results/report.html',
|
|
345
|
-
visitor: (data, metadata, collect) => {
|
|
346
|
-
// collect data from the annotations
|
|
347
|
-
if (metadata.annotations) {
|
|
348
|
-
const jiraItem = metadata.annotations.find((item) => item.type === 'jira');
|
|
349
|
-
if (jiraItem && jiraItem.description) {
|
|
350
|
-
data.jira = jiraItem.description;
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
}]
|
|
355
|
-
]
|
|
356
|
-
};
|
|
357
|
-
```
|
|
358
|
-
|
|
359
|
-
### Collect Data from the Comments
|
|
301
|
+
### Custom Fields in Comments
|
|
360
302
|
> The code comments are good enough to provide extra information without breaking existing code, and no dependencies, clean, easy to read, etc.
|
|
361
|
-
- First,
|
|
362
|
-
> Note: If there are any parsing error messages in red lines, try other parser options like `sourceType: 'module'` or `plugins: ['typescript']` according to your situation.
|
|
303
|
+
- First, enable option `customFieldsInComments` to `true`
|
|
363
304
|
```js
|
|
364
305
|
// playwright.config.js
|
|
365
306
|
module.exports = {
|
|
366
307
|
reporter: [
|
|
367
308
|
['monocart-reporter', {
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
// additional custom visitor for columns
|
|
371
|
-
visitor: (data, metadata, collect) => {
|
|
372
|
-
|
|
373
|
-
// auto collect data from the comments
|
|
374
|
-
const parserOptions = {
|
|
375
|
-
// Indicate the mode the code should be parsed in.
|
|
376
|
-
// Can be one of "script", "module", or "unambiguous". Defaults to "script".
|
|
377
|
-
// sourceType: 'module',
|
|
378
|
-
|
|
379
|
-
// enable typescript syntax.
|
|
380
|
-
// plugins: ['typescript']
|
|
381
|
-
|
|
382
|
-
// more https://babeljs.io/docs/babel-parser
|
|
383
|
-
};
|
|
384
|
-
const comments = collect.comments(parserOptions);
|
|
385
|
-
if (comments) {
|
|
386
|
-
// Append all collected comments data to report data
|
|
387
|
-
Object.assign(data, comments);
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
}
|
|
309
|
+
// enable/disable custom fields in comments. Defaults to true.
|
|
310
|
+
customFieldsInComments: true
|
|
391
311
|
}]
|
|
392
312
|
]
|
|
393
313
|
};
|
|
394
314
|
```
|
|
395
315
|
|
|
396
|
-
- Then, add comments
|
|
316
|
+
- Then, add comments for the tests
|
|
397
317
|
> Note: Each comment item must start with `@` which is similar to [JSDoc](https://jsdoc.app/).
|
|
398
318
|
|
|
399
|
-
For example,
|
|
319
|
+
For example, adding `owner` and `jira` to the cases, steps, and suites. or updating the value if the field exists like `title`
|
|
400
320
|
```js
|
|
401
321
|
/**
|
|
402
322
|
* for case
|
|
@@ -469,7 +389,71 @@ test.describe('suite title', () => {
|
|
|
469
389
|
const { test, expect } = require('@playwright/test');
|
|
470
390
|
```
|
|
471
391
|
|
|
472
|
-
###
|
|
392
|
+
### Custom Data Visitor
|
|
393
|
+
The `visitor` function will be executed for each row item (suite, case and step). Arguments:
|
|
394
|
+
- `data` data item (suite/case/step) for reporter, you can rewrite some of its properties or add more
|
|
395
|
+
- `metadata` original data object from Playwright test, could be one of [Suite](https://playwright.dev/docs/api/class-suite), [TestCase](https://playwright.dev/docs/api/class-testcase) or [TestStep](https://playwright.dev/docs/api/class-teststep)
|
|
396
|
+
|
|
397
|
+
#### Collect Data from the Title
|
|
398
|
+
For example, we want to parse out the jira key from the title:
|
|
399
|
+
```js
|
|
400
|
+
test('[MCR-123] collect data from the title', () => {
|
|
401
|
+
|
|
402
|
+
});
|
|
403
|
+
```
|
|
404
|
+
You can simply use regular expressions to parse and get jira key:
|
|
405
|
+
```js
|
|
406
|
+
// playwright.config.js
|
|
407
|
+
module.exports = {
|
|
408
|
+
reporter: [
|
|
409
|
+
['monocart-reporter', {
|
|
410
|
+
name: "My Test Report",
|
|
411
|
+
outputFile: './test-results/report.html',
|
|
412
|
+
visitor: (data, metadata) => {
|
|
413
|
+
// [MCR-123] collect data from the title
|
|
414
|
+
const matchResult = metadata.title.match(/\[(.+)\]/);
|
|
415
|
+
if (matchResult && matchResult[1]) {
|
|
416
|
+
data.jira = matchResult[1];
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
}]
|
|
420
|
+
]
|
|
421
|
+
};
|
|
422
|
+
```
|
|
423
|
+
multiple matches example: [collect-data](https://github.com/cenfun/monocart-reporter-test/tree/main/tests/collect-data)
|
|
424
|
+
|
|
425
|
+
#### Collect Data from the Annotations
|
|
426
|
+
It should be easier than getting from title. see [custom annotations](https://playwright.dev/docs/test-annotations#custom-annotations) via `test.info().annotations`
|
|
427
|
+
```js
|
|
428
|
+
test('collect data from the annotations', () => {
|
|
429
|
+
test.info().annotations.push({
|
|
430
|
+
type: "jira",
|
|
431
|
+
description: "MCR-123"
|
|
432
|
+
})
|
|
433
|
+
});
|
|
434
|
+
```
|
|
435
|
+
```js
|
|
436
|
+
// playwright.config.js
|
|
437
|
+
module.exports = {
|
|
438
|
+
reporter: [
|
|
439
|
+
['monocart-reporter', {
|
|
440
|
+
name: "My Test Report",
|
|
441
|
+
outputFile: './test-results/report.html',
|
|
442
|
+
visitor: (data, metadata) => {
|
|
443
|
+
// collect data from the annotations
|
|
444
|
+
if (metadata.annotations) {
|
|
445
|
+
const jiraItem = metadata.annotations.find((item) => item.type === 'jira');
|
|
446
|
+
if (jiraItem && jiraItem.description) {
|
|
447
|
+
data.jira = jiraItem.description;
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
}]
|
|
452
|
+
]
|
|
453
|
+
};
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
#### Remove Secrets and Sensitive Data
|
|
473
457
|
> The report may hosted outside of the organization’s internal boundaries, security becomes a big issue. Any secrets or sensitive data, such as usernames, passwords, tokens and API keys, should be handled with extreme care. The following example is removing the password and token from the report data with the string replacement in `visitor` function.
|
|
474
458
|
```js
|
|
475
459
|
// playwright.config.js
|
|
@@ -478,7 +462,7 @@ module.exports = {
|
|
|
478
462
|
['monocart-reporter', {
|
|
479
463
|
name: "My Test Report",
|
|
480
464
|
outputFile: './test-results/report.html',
|
|
481
|
-
visitor: (data, metadata
|
|
465
|
+
visitor: (data, metadata) => {
|
|
482
466
|
const mySecrets = [process.env.PASSWORD, process.env.TOKEN];
|
|
483
467
|
mySecrets.forEach((secret) => {
|
|
484
468
|
// remove from title
|
|
@@ -637,99 +621,16 @@ test('attach lighthouse audit report', async () => {
|
|
|
637
621
|
|
|
638
622
|
## Code Coverage Report
|
|
639
623
|
The reporter integrates [monocart-coverage-reports](https://github.com/cenfun/monocart-coverage-reports) for coverage reports, there are two APIs:
|
|
640
|
-
- `
|
|
641
|
-
- `data` There are two supported data inputs: [Istanbul](
|
|
624
|
+
- `addCoverageReport(data, testInfo)` Add coverage to global coverage report from a test. see [Global Coverage Report](#global-coverage-report)
|
|
625
|
+
- `data` There are two supported data inputs: [Istanbul](https://github.com/cenfun/monocart-coverage-reports?#collecting-istanbul-coverage-data) (Object) or [V8](https://github.com/cenfun/monocart-coverage-reports?#collecting-v8-coverage-data) (Array)
|
|
642
626
|
- `testInfo` see [TestInfo](https://playwright.dev/docs/api/class-testinfo)
|
|
627
|
+
- `attachCoverageReport(data, testInfo, options)` Attach a coverage report to a test. Arguments:
|
|
628
|
+
- `data` same as above
|
|
629
|
+
- `testInfo` same as above
|
|
643
630
|
- `options` (Object) see [Coverage Options](#coverage-options)
|
|
644
|
-
- `addCoverageReport(data, testInfo)` Add coverage to global coverage report from a test. see [Global Coverage Report](#global-coverage-report)
|
|
645
|
-
|
|
646
|
-
### Coverage Options
|
|
647
|
-
- Default [options](https://github.com/cenfun/monocart-coverage-reports/blob/main/lib/default/options.js)
|
|
648
|
-
- More examples [monocart-coverage-reports](https://github.com/cenfun/monocart-coverage-reports)
|
|
649
|
-
|
|
650
|
-
### [Istanbul](https://github.com/istanbuljs)
|
|
651
|
-
Requires your source code is instrumented. Usually we can use the tool [babel-plugin-istanbul](https://github.com/istanbuljs/babel-plugin-istanbul) to build instrumenting code. (see example: [webpack.config-istanbul.js](https://github.com/cenfun/monocart-reporter-test/blob/main/packages/coverage/webpack.config-istanbul.js)) The instrumented code will automatically generate coverage data and save it on `window.__coverage__`. The Istanbul HTML report will be generated and attached to the test report as an attachment.
|
|
652
|
-
```js
|
|
653
|
-
import { test, expect } from '@playwright/test';
|
|
654
|
-
import { attachCoverageReport } from 'monocart-reporter';
|
|
655
|
-
|
|
656
|
-
test('Take Istanbul coverage report', async ({ page }) => {
|
|
657
|
-
|
|
658
|
-
await page.goto('http://localhost:8090/coverage/istanbul.html');
|
|
659
|
-
|
|
660
|
-
// delay for mock code execution
|
|
661
|
-
await new Promise((resolve) => {
|
|
662
|
-
setTimeout(resolve, 500);
|
|
663
|
-
});
|
|
664
|
-
|
|
665
|
-
// take Istanbul coverage
|
|
666
|
-
const coverageData = await page.evaluate(() => window.__coverage__);
|
|
667
|
-
await page.close();
|
|
668
|
-
expect(coverageData, 'expect found Istanbul data: __coverage__').toBeTruthy();
|
|
669
|
-
|
|
670
|
-
// coverage report
|
|
671
|
-
const report = await attachCoverageReport(coverageData, test.info(), {
|
|
672
|
-
lcov: true
|
|
673
|
-
});
|
|
674
|
-
console.log(report.summary);
|
|
675
|
-
|
|
676
|
-
});
|
|
677
|
-
```
|
|
678
|
-
|
|
679
|
-
### [V8](https://v8.dev/blog/javascript-code-coverage)
|
|
680
|
-
Simply take coverage data with [class-coverage](https://playwright.dev/docs/api/class-coverage) APIs, so it is [Chromium-based only](https://chromedevtools.github.io/devtools-protocol/tot/Profiler/#type-ScriptCoverage), the V8 HTML report will be generated.
|
|
681
|
-
```js
|
|
682
|
-
import { test, expect } from '@playwright/test';
|
|
683
|
-
import { attachCoverageReport } from 'monocart-reporter';
|
|
684
|
-
|
|
685
|
-
test('Take V8 and Istanbul coverage report', async ({ page }) => {
|
|
686
|
-
|
|
687
|
-
await Promise.all([
|
|
688
|
-
page.coverage.startJSCoverage({
|
|
689
|
-
resetOnNavigation: false
|
|
690
|
-
}),
|
|
691
|
-
page.coverage.startCSSCoverage({
|
|
692
|
-
resetOnNavigation: false
|
|
693
|
-
})
|
|
694
|
-
]);
|
|
695
|
-
|
|
696
|
-
await page.goto('http://localhost:8090/coverage/v8.html');
|
|
697
|
-
|
|
698
|
-
// delay for mock code execution
|
|
699
|
-
await new Promise((resolve) => {
|
|
700
|
-
setTimeout(resolve, 500);
|
|
701
|
-
});
|
|
702
|
-
|
|
703
|
-
const [jsCoverage, cssCoverage] = await Promise.all([
|
|
704
|
-
page.coverage.stopJSCoverage(),
|
|
705
|
-
page.coverage.stopCSSCoverage()
|
|
706
|
-
]);
|
|
707
|
-
await page.close();
|
|
708
|
-
|
|
709
|
-
const coverageList = [... jsCoverage, ... cssCoverage];
|
|
710
|
-
|
|
711
|
-
const v8 = await attachCoverageReport(coverageList, test.info(), {
|
|
712
|
-
|
|
713
|
-
});
|
|
714
|
-
console.log(v8.summary);
|
|
715
|
-
|
|
716
|
-
});
|
|
717
|
-
```
|
|
718
631
|
|
|
719
632
|

|
|
720
633
|
|
|
721
|
-
### V8 to Istanbul
|
|
722
|
-
Take V8 coverage data and convert it to Istanbul's coverage format. The Istanbul HTML report will be generated.
|
|
723
|
-
```js
|
|
724
|
-
const report = await attachCoverageReport(coverageList, test.info(), {
|
|
725
|
-
reports: "html"
|
|
726
|
-
});
|
|
727
|
-
```
|
|
728
|
-
|
|
729
|
-
### Istanbul vs V8
|
|
730
|
-
- [Compare Istanbul, V8 and V8 to Istanbul Reports](https://github.com/cenfun/monocart-coverage-reports#compare-reports)
|
|
731
|
-
- [Compare Istanbul and V8 Workflows](https://github.com/cenfun/monocart-coverage-reports#compare-workflows)
|
|
732
|
-
|
|
733
634
|
### Global Coverage Report
|
|
734
635
|
The global coverage report will not be attached to any test case, but will merge all coverages into one global report after all the tests are finished.
|
|
735
636
|
- The global coverage options see [Coverage Options](#coverage-options)
|
|
@@ -751,13 +652,14 @@ module.exports = {
|
|
|
751
652
|
```
|
|
752
653
|
- It is recommended to use [automatic fixtures](https://playwright.dev/docs/test-fixtures#automatic-fixtures) to add coverage for each test:
|
|
753
654
|
```js
|
|
754
|
-
// fixtures.js for v8
|
|
655
|
+
// fixtures.js for v8 coverage
|
|
755
656
|
import { test as testBase, expect } from '@playwright/test';
|
|
756
657
|
import { addCoverageReport } from 'monocart-reporter';
|
|
757
658
|
|
|
758
659
|
const test = testBase.extend({
|
|
759
660
|
autoTestFixture: [async ({ page }, use) => {
|
|
760
661
|
|
|
662
|
+
// NOTE: it depends on your project name
|
|
761
663
|
const isChromium = test.info().project.name === 'Desktop Chromium';
|
|
762
664
|
|
|
763
665
|
// console.log('autoTestFixture setup...');
|
|
@@ -794,12 +696,16 @@ const test = testBase.extend({
|
|
|
794
696
|
export { test, expect };
|
|
795
697
|
```
|
|
796
698
|
|
|
699
|
+
### Coverage Options
|
|
700
|
+
- Default [options](https://github.com/cenfun/monocart-coverage-reports/blob/main/lib/default/options.js)
|
|
701
|
+
- More Introduction [monocart-coverage-reports](https://github.com/cenfun/monocart-coverage-reports)
|
|
702
|
+
|
|
797
703
|
### Coverage Examples
|
|
798
704
|
- For Playwright component testing:
|
|
799
705
|
- [playwright-ct-vue](https://github.com/cenfun/playwright-ct-vue)
|
|
800
706
|
- [playwright-ct-react](https://github.com/cenfun/playwright-ct-react)
|
|
801
707
|
- [playwright-ct-svelte](https://github.com/cenfun/playwright-ct-svelte)
|
|
802
|
-
- [
|
|
708
|
+
- [nextjs-with-playwright](https://github.com/cenfun/nextjs-with-playwright)
|
|
803
709
|
- [code-coverage-with-monocart-reporter](https://github.com/edumserrano/playwright-adventures/blob/main/demos/code-coverage-with-monocart-reporter/)
|
|
804
710
|
|
|
805
711
|
## Attach Network Report
|
package/lib/default/options.js
CHANGED
|
@@ -47,7 +47,10 @@ module.exports = {
|
|
|
47
47
|
|
|
48
48
|
// rows data handler (suite, case and step)
|
|
49
49
|
visitor: null,
|
|
50
|
-
// visitor: (data, metadata
|
|
50
|
+
// visitor: (data, metadata) => {},
|
|
51
|
+
|
|
52
|
+
// enable/disable custom fields in comments. Defaults to true.
|
|
53
|
+
customFieldsInComments: true,
|
|
51
54
|
|
|
52
55
|
// onEnd hook
|
|
53
56
|
onEnd: null
|
package/lib/generate-report.js
CHANGED
|
@@ -22,7 +22,7 @@ const generateHtml = async (outputDir, htmlFile, reportData, inline) => {
|
|
|
22
22
|
});
|
|
23
23
|
|
|
24
24
|
jsFiles.push(Util.resolvePackage('monocart-common.js'));
|
|
25
|
-
jsFiles.push(Util.resolvePackage('monocart-reporter.js'));
|
|
25
|
+
jsFiles.push(Util.resolvePackage('monocart-reporter-app.js'));
|
|
26
26
|
|
|
27
27
|
const options = {
|
|
28
28
|
inline,
|
|
@@ -51,7 +51,7 @@ const sendEmail = (emailOptions) => {
|
|
|
51
51
|
};
|
|
52
52
|
|
|
53
53
|
const showTestResults = (reportData) => {
|
|
54
|
-
Util.logInfo(
|
|
54
|
+
Util.logInfo(EC.cyan(reportData.name));
|
|
55
55
|
|
|
56
56
|
const summary = reportData.summary;
|
|
57
57
|
|
package/lib/index.d.ts
CHANGED
|
@@ -59,11 +59,11 @@ export type MonocartReporterOptions = {
|
|
|
59
59
|
// columns: (defaultColumns) => {},
|
|
60
60
|
|
|
61
61
|
// rows data handler (suite, case and step)
|
|
62
|
-
visitor?: (data: any, metadata: any
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
62
|
+
visitor?: (data: any, metadata: any) => void,
|
|
63
|
+
// visitor: (data, metadata) => {},
|
|
64
|
+
|
|
65
|
+
// enable/disable custom fields in comments. Defaults to true.
|
|
66
|
+
customFieldsInComments?: boolean,
|
|
67
67
|
|
|
68
68
|
// onEnd hook
|
|
69
69
|
onEnd?: (reportData: object, capability: {
|
package/lib/index.js
CHANGED
|
@@ -96,6 +96,12 @@ class Reporter {
|
|
|
96
96
|
return this.testMap.get(testId);
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
+
addTestLog(test, log) {
|
|
100
|
+
if (test && test.logs) {
|
|
101
|
+
test.logs.push(log);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
99
105
|
// ==========================================================================
|
|
100
106
|
|
|
101
107
|
// Whether this reporter uses stdio for reporting.
|
|
@@ -136,7 +142,7 @@ class Reporter {
|
|
|
136
142
|
// result stderr and stdout without order
|
|
137
143
|
if (test.logs) {
|
|
138
144
|
const retryLogs = ['\n', EC.yellow(`Retry #${result.retry}`), '\n'].join('');
|
|
139
|
-
|
|
145
|
+
this.addTestLog(test, retryLogs);
|
|
140
146
|
} else {
|
|
141
147
|
test.logs = [];
|
|
142
148
|
}
|
|
@@ -144,18 +150,12 @@ class Reporter {
|
|
|
144
150
|
|
|
145
151
|
onStdErr(chunk, test, result) {
|
|
146
152
|
// Note that output may happen when no test is running, in which case this will be void.
|
|
147
|
-
test
|
|
148
|
-
if (test) {
|
|
149
|
-
test.logs.push(EC.red(chunk));
|
|
150
|
-
}
|
|
153
|
+
this.addTestLog(test || this.lastTest, EC.red(chunk));
|
|
151
154
|
}
|
|
152
155
|
|
|
153
156
|
onStdOut(chunk, test, result) {
|
|
154
157
|
// Note that output may happen when no test is running, in which case this will be void.
|
|
155
|
-
test
|
|
156
|
-
if (test) {
|
|
157
|
-
test.logs.push(chunk);
|
|
158
|
-
}
|
|
158
|
+
this.addTestLog(test || this.lastTest, chunk);
|
|
159
159
|
}
|
|
160
160
|
|
|
161
161
|
// Called on some global error, for example unhandled exception in the worker process.
|
|
@@ -163,9 +163,7 @@ class Reporter {
|
|
|
163
163
|
// EC.logRed(error);
|
|
164
164
|
|
|
165
165
|
// add the error to test logs
|
|
166
|
-
|
|
167
|
-
this.lastTest.logs.push(EC.red(error.message));
|
|
168
|
-
}
|
|
166
|
+
this.addTestLog(this.lastTest, EC.red(error.message));
|
|
169
167
|
|
|
170
168
|
}
|
|
171
169
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("turbogrid")):"function"==typeof define&&define.amd?define("monocart-common",["turbogrid"],t):"object"==typeof exports?exports["monocart-common"]=t(require("turbogrid")):e["monocart-common"]=t(e.turbogrid)}(self,(e=>(()=>{var t={162:function(e,t,r){var n,o,a;o=[],void 0===(a="function"==typeof(n=function(){"use strict";function t(e,t){return void 0===t?t={autoBom:!1}:"object"!=typeof t&&(console.warn("Deprecated: Expected third argument to be a object"),t={autoBom:!t}),t.autoBom&&/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(e.type)?new Blob(["\ufeff",e],{type:e.type}):e}function n(e,t,r){var n=new XMLHttpRequest;n.open("GET",e),n.responseType="blob",n.onload=function(){c(n.response,t,r)},n.onerror=function(){console.error("could not download file")},n.send()}function o(e){var t=new XMLHttpRequest;t.open("HEAD",e,!1);try{t.send()}catch(e){}return 200<=t.status&&299>=t.status}function a(e){try{e.dispatchEvent(new MouseEvent("click"))}catch(r){var t=document.createEvent("MouseEvents");t.initMouseEvent("click",!0,!0,window,0,0,0,80,20,!1,!1,!1,!1,0,null),e.dispatchEvent(t)}}var i="object"==typeof window&&window.window===window?window:"object"==typeof self&&self.self===self?self:"object"==typeof r.g&&r.g.global===r.g?r.g:void 0,s=i.navigator&&/Macintosh/.test(navigator.userAgent)&&/AppleWebKit/.test(navigator.userAgent)&&!/Safari/.test(navigator.userAgent),c=i.saveAs||("object"!=typeof window||window!==i?function(){}:"download"in HTMLAnchorElement.prototype&&!s?function(e,t,r){var s=i.URL||i.webkitURL,c=document.createElement("a");t=t||e.name||"download",c.download=t,c.rel="noopener","string"==typeof e?(c.href=e,c.origin===location.origin?a(c):o(c.href)?n(e,t,r):a(c,c.target="_blank")):(c.href=s.createObjectURL(e),setTimeout((function(){s.revokeObjectURL(c.href)}),4e4),setTimeout((function(){a(c)}),0))}:"msSaveOrOpenBlob"in navigator?function(e,r,i){if(r=r||e.name||"download","string"!=typeof e)navigator.msSaveOrOpenBlob(t(e,i),r);else if(o(e))n(e,r,i);else{var s=document.createElement("a");s.href=e,s.target="_blank",setTimeout((function(){a(s)}))}}:function(e,t,r,o){if((o=o||open("","_blank"))&&(o.document.title=o.document.body.innerText="downloading..."),"string"==typeof e)return n(e,t,r);var a="application/octet-stream"===e.type,c=/constructor/i.test(i.HTMLElement)||i.safari,u=/CriOS\/[\d]+/.test(navigator.userAgent);if((u||a&&c||s)&&"undefined"!=typeof FileReader){var l=new FileReader;l.onloadend=function(){var e=l.result;e=u?e:e.replace(/^data:[^;]*;/,"data:attachment/file;"),o?o.location.href=e:location=e,o=null},l.readAsDataURL(e)}else{var f=i.URL||i.webkitURL,d=f.createObjectURL(e);o?o.location=d:location.href=d,o=null,setTimeout((function(){f.revokeObjectURL(d)}),4e4)}});i.saveAs=c.saveAs=c,e.exports=c})?n.apply(t,o):n)||(e.exports=a)},925:e=>{var t,r,n=(t=(e,t)=>{t.exports={data:'(()=>{var x=(e,n)=>()=>(n||e((n={exports:{}}).exports,n),n.exports);var S=x((V,R)=>{var _=0,p=-3;function b(){this.table=new Uint16Array(16),this.trans=new Uint16Array(288)}function N(e,n){this.source=e,this.sourceIndex=0,this.tag=0,this.bitcount=0,this.dest=n,this.destLen=0,this.ltree=new b,this.dtree=new b}var y=new b,k=new b,w=new Uint8Array(30),h=new Uint16Array(30),L=new Uint8Array(30),T=new Uint16Array(30),O=new Uint8Array([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]),A=new b,c=new Uint8Array(288+32);function D(e,n,r,a){var t,i;for(t=0;t<r;++t)e[t]=0;for(t=0;t<30-r;++t)e[t+r]=t/r|0;for(i=a,t=0;t<30;++t)n[t]=i,i+=1<<e[t]}function z(e,n){var r;for(r=0;r<7;++r)e.table[r]=0;for(e.table[7]=24,e.table[8]=152,e.table[9]=112,r=0;r<24;++r)e.trans[r]=256+r;for(r=0;r<144;++r)e.trans[24+r]=r;for(r=0;r<8;++r)e.trans[24+144+r]=280+r;for(r=0;r<112;++r)e.trans[24+144+8+r]=144+r;for(r=0;r<5;++r)n.table[r]=0;for(n.table[5]=32,r=0;r<32;++r)n.trans[r]=r}var I=new Uint16Array(16);function l(e,n,r,a){var t,i;for(t=0;t<16;++t)e.table[t]=0;for(t=0;t<a;++t)e.table[n[r+t]]++;for(e.table[0]=0,i=0,t=0;t<16;++t)I[t]=i,i+=e.table[t];for(t=0;t<a;++t)n[r+t]&&(e.trans[I[n[r+t]]++]=t)}function B(e){e.bitcount--||(e.tag=e.source[e.sourceIndex++],e.bitcount=7);var n=e.tag&1;return e.tag>>>=1,n}function u(e,n,r){if(!n)return r;for(;e.bitcount<24;)e.tag|=e.source[e.sourceIndex++]<<e.bitcount,e.bitcount+=8;var a=e.tag&65535>>>16-n;return e.tag>>>=n,e.bitcount-=n,a+r}function v(e,n){for(;e.bitcount<24;)e.tag|=e.source[e.sourceIndex++]<<e.bitcount,e.bitcount+=8;var r=0,a=0,t=0,i=e.tag;do a=2*a+(i&1),i>>>=1,++t,r+=n.table[t],a-=n.table[t];while(a>=0);return e.tag=i,e.bitcount-=t,n.trans[r+a]}function C(e,n,r){var a,t,i,o,s,f;for(a=u(e,5,257),t=u(e,5,1),i=u(e,4,4),o=0;o<19;++o)c[o]=0;for(o=0;o<i;++o){var F=u(e,3,0);c[O[o]]=F}for(l(A,c,0,19),s=0;s<a+t;){var g=v(e,A);switch(g){case 16:var M=c[s-1];for(f=u(e,2,3);f;--f)c[s++]=M;break;case 17:for(f=u(e,3,3);f;--f)c[s++]=0;break;case 18:for(f=u(e,7,11);f;--f)c[s++]=0;break;default:c[s++]=g;break}}l(n,c,0,a),l(r,c,a,t)}function U(e,n,r){for(;;){var a=v(e,n);if(a===256)return _;if(a<256)e.dest[e.destLen++]=a;else{var t,i,o,s;for(a-=257,t=u(e,w[a],h[a]),i=v(e,r),o=e.destLen-u(e,L[i],T[i]),s=o;s<o+t;++s)e.dest[e.destLen++]=e.dest[s]}}}function K(e){for(var n,r,a;e.bitcount>8;)e.sourceIndex--,e.bitcount-=8;if(n=e.source[e.sourceIndex+1],n=256*n+e.source[e.sourceIndex],r=e.source[e.sourceIndex+3],r=256*r+e.source[e.sourceIndex+2],n!==(~r&65535))return p;for(e.sourceIndex+=4,a=n;a;--a)e.dest[e.destLen++]=e.source[e.sourceIndex++];return e.bitcount=0,_}function j(e,n){var r=new N(e,n),a,t,i;do{switch(a=B(r),t=u(r,2,0),t){case 0:i=K(r);break;case 1:i=U(r,y,k);break;case 2:C(r,r.ltree,r.dtree),i=U(r,r.ltree,r.dtree);break;default:i=p}if(i!==_)throw new Error("Data error")}while(!a);return r.destLen<r.dest.length?typeof r.dest.slice=="function"?r.dest.slice(0,r.destLen):r.dest.subarray(0,r.destLen):r.dest}z(y,k);D(w,h,4,3);D(L,T,2,1);w[28]=0;h[28]=258;R.exports=j});var E=x((W,q)=>{var G=S(),H=e=>Uint8Array.from(atob(e),n=>n.charCodeAt(0)),J=e=>new TextDecoder().decode(e);q.exports=function(e){if(e){let[n,r]=e.split(".");if(n&&r){let a=H(n),t=new Uint8Array(parseInt(r));return G(a,t),J(t)}}}});var P=E();onmessage=function(e){postMessage(P(e.data))};postMessage("workerReady");})();\n'}},()=>(r||t((r={exports:{}}).exports,r),r.exports))();e.exports=e=>new Promise((t=>{let r=new Worker(URL.createObjectURL(new Blob([n.data],{type:"application/javascript"})));r.onmessage=n=>{"workerReady"!==n.data?(t(n.data),r.terminate()):r.postMessage(e)},r.onerror=e=>{t({error:e}),r.terminate()}}))},209:e=>{const t={tagPattern:/(\s*)@([^@\s]+)(\s*)/g,lineBreakPattern:/\r\n|[\r\n\u2028\u2029]/gu,attachments:{audit:{name:"audit",contentType:"text/html",reportFile:"audit-report.json"},coverage:{name:"coverage",contentType:"text/html",reportFile:"coverage-report.json"},network:{name:"network",contentType:"text/html",reportFile:"network-report.json"}},pageTimings:[{key:"onContentLoad",name:"Content Loaded",color:"#1a1aa6"},{key:"onLoad",name:"Page Loaded",color:"#c80000"}],timings:[{key:"blocked",name:"Blocking",color:"#858585"},{key:"dns",name:"DNS Lookup",color:"#009688"},{key:"connect",name:"Connecting",color:"#b52dcd"},{key:"send",name:"Sending",color:"#74979a"},{key:"wait",name:"Waiting",color:"#00a846"},{key:"receive",name:"Receiving",color:"#0299de"}],hasOwn:function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},isNull:function(e){return null==e},uid:function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:20;const t="0123456789abcdefghijklmnopqrstuvwxyz";let r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";for(;e--;)r+=t[36*Math.random()|0];return r},zero:function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:2;return(e=`${e}`).padStart(t,"0")},toNum:function(e,t){return"number"!=typeof e&&(e=parseFloat(e)),isNaN(e)&&(e=0),t&&(e=Math.round(e)),e},isList:function(e){return!!(e&&e instanceof Array&&e.length>0)},forEach:function(e,r){const n=e=>"break"===e||!1===e,o=(e,a)=>{if(t.isList(e))for(const t of e){const e=r(t,a);if(n(e))return e;const i=o(t.subs,t);if(n(i))return i}};o(e)},formatPath:function(e){return e&&(e=e.replace(/\\/g,"/")),e},getCurrentTrendInfo:e=>{const{date:t,duration:r,summary:n}=e,o={date:t,duration:r};return Object.keys(n).forEach((e=>{const t=n[e];o[e]=t.value})),o},isTagItem:e=>"case"===e.type||"suite"===e.type&&"describe"===e.suiteType,delay:function(e){return new Promise((t=>{e?setTimeout(t,e):setImmediate(t)}))},generatePercentChart:function(e){return`<div style="--mcr-percent:${e}%;" class="mcr-percent-chart"></div>`},getStatus:(e,t)=>t?e<t[0]?"low":e<t[1]?"medium":"high":"unknown",isJsonType:e=>!(!e||"application/json"!==e&&"json"!==e),isMarkdownType:e=>!(!e||"text/markdown"!==e&&"markdown"!==e),isTextType(e){if(e){if(e.startsWith("text"))return!0;if(t.isMarkdownType(e))return!0;if(t.isJsonType(e))return!0}return!1},dFixed:function(e){let r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:1;return Number.isInteger(e)?e:t.toNum(t.toNum(e).toFixed(r))},pxFixed:e=>{const t=Math.floor(e);return e<t+.5?t+.5:t+1.5},point:(e,r)=>`${t.dFixed(e)},${t.dFixed(r)}`,NF:function(e){return"number"==typeof e&&e?e.toLocaleString():e},PF:function(e){let r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:1,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:1,o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"%",a=arguments.length>4&&void 0!==arguments[4]?arguments[4]:"";e=t.toNum(e),r=t.toNum(r);let i=0;r&&(i=e/r);const s=(100*i).toFixed(n);return o?s+a+o:parseFloat(s)},PSF:function(e){let r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:1,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:1;return t.PF(e,r,n,"%"," ")},PNF:function(e){let r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:1,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:1;return t.PF(e,r,n,"")},BF:function(e){let r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:1,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"";if(0===(e=t.toNum(e,!0)))return`0${n}B`;let o="";e<0&&(e=Math.abs(e),o="-");const a=["B","KB","MB","GB","TB","PB","EB","ZB","YB"];for(let t=0,i=a.length;t<i;t++){const i=Math.pow(1024,t),s=Math.pow(1024,t+1);if(e>i&&e<s){const s=a[t];e=o+(e/i).toFixed(r)+n+s;break}}return e},BSF:function(e){let r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:1;return t.BF(e,r," ")},TF:function(e){let r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";const n=t.toNum(e,!0);if(n<1e3)return`${n}${r}ms`;if(n<6e4){const e=Math.floor(n/1e3),t=Math.round((n-1e3*e)/100);return t?`${e}.${t}${r}s`:`${e}${r}s`}const o=Math.round(n/1e3),a=60,i=3600,s=24*i;if(o<i){const e=Math.floor(o/a);return`${e}${r}m ${o-e*a}${r}s`}if(o<s){const e=Math.floor(o/i),t=Math.floor((o-e*i)/a);return`${e}${r}h ${t}${r}m ${o-e*i-t*a}${r}s`}const c=Math.floor(o/s),u=Math.floor((o-c*s)/i),l=Math.floor((o-c*s-u*i)/a);return`${c}${r}d ${u}${r}h ${l}${r}m ${o-c*s-u*i-l*a}${r}s`},TSF:function(e){return t.TF(e," ")}};e.exports=t},46:t=>{"use strict";t.exports=e}},r={};function n(e){var o=r[e];if(void 0!==o)return o.exports;var a=r[e]={exports:{}};return t[e].call(a.exports,a,a.exports,n),a.exports}n.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return n.d(t,{a:t}),t},n.d=(e,t)=>{for(var r in t)n.o(t,r)&&!n.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},n.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),n.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),n.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var o={};return(()=>{"use strict";n.r(o),n.d(o,{CommonUtil:()=>k,debounce:()=>t,decodeIcons:()=>M,hash:()=>g,inflate:()=>i(),microtask:()=>r,niceTicks:()=>p,saveAs:()=>h.saveAs,setFavicon:()=>A,store:()=>b});class e{start(e){this.callback=e,this.started||(this.started=!0,this.create())}create(){if("function"!=typeof window.queueMicrotask){if("function"!=typeof Promise)throw new Error("Current browser does NOT support queueMicrotask or Promise");Promise.resolve().then((()=>{this.execute()}))}else window.queueMicrotask((()=>{this.execute()}))}execute(){if(!this.started)return;this.started=!1;const e=this.callback;this.callback=null,"function"==typeof e&&e.call(this)}cancel(){this.started=!1,this.callback=null}}const t=function(e,t=100){let r;const n=function(){clearTimeout(r),r=setTimeout((()=>{e.apply(this,arguments)}),t)};return n.cancel=()=>{clearTimeout(r)},n},r=function(t){const r=new e,n=function(){r.start((()=>{t.apply(this,arguments)}))};return n.cancel=()=>{r.cancel()},n};var a=n(925),i=n.n(a);function s(e){return""+e}function c(e){var t=s(e).split(".");return t.length>1?t[1].length:0}function u(e){var t=s(e);return parseInt(t.replace(".",""))}function l(e,t){var r=c(e),n=c(t);if(r+n===0)return e+t;var o=Math.pow(10,Math.max(r,n));return(Math.round(e*o)+Math.round(t*o))/o}function f(e,t){var r=c(e),n=c(t);return r+n===0?e*t:u(e)*u(t)/Math.pow(10,r+n)}function d(e,t){var r=Math.floor(Math.log(e)/Math.log(10)),n=e/Math.pow(10,r);return(t?n<1.5?1:n<3?2:n<7?5:10:n<=1?1:n<=2?2:n<=5?5:10)*Math.pow(10,r)}var w=function(e){return"number"!=typeof e&&(e=parseFloat(e)),isNaN(e)&&(e=0),e};function p(e,t,r){if(e=w(e),t=w(t),(r=w(r))||(r=4),e===t)t=e+1;else if(e>t){var n=e;e=t,t=n}for(var o=d(t-e,!1),a=d(o/(r-1),!0),i=f(Math.floor(e/a),a),s=f(Math.ceil(t/a),a),c=[],u=i;u<=s;)c.push(u),u=l(u,a);return c}var h=n(162);const m={get:function(e){let t={};const r=location.hash.slice(1);if(r){const e=new URLSearchParams(r);t=Object.fromEntries(e)}return e?t[e]:t},set:function(e,t){if(!e)return;let r=e;2===arguments.length&&(r={},r[e]=t);const n=m.get();Object.keys(r).forEach((e=>{n[e]=r[e]}));const o=new URLSearchParams(n);location.hash=o.toString()},remove:function(e){if(!e)return void(location.hash="");let t=e;Array.isArray(e)||(t=[e]);const r=m.get();t.forEach((e=>{delete r[e]}));const n=new URLSearchParams(r);location.hash=n.toString()}},g=m,v=e=>`mcr-${e}`,b={get(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";const r=window.localStorage.getItem(v(e));return null===r?t:r},set(e,t){window.localStorage.setItem(v(e),t)},remove(e){window.localStorage.removeItem(v(e))}},M=e=>{const t=e.keys(),r={};return t.forEach((t=>{const n=t.toLowerCase().split("/").pop().slice(0,-4),o=e(t),a=o.slice(o.indexOf(",")+1),i=atob(a);r[n]=i})),r};var y=n(46),x=n(209),T=n.n(x);const k={...y.Util,...T(),isTouchDevice:function(){return"ontouchstart"in window||navigator.maxTouchPoints>0||navigator.msMaxTouchPoints>0}},A=()=>{const e=document.querySelector('link[rel="icon"]');e&&(e.href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNjAwIDE2MDAiPg0KICAgIDxwYXRoIGZpbGw9ImNob2NvbGF0ZSIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMzAwLDBMMjU3LDMwMmwxOTIsOThINjAwbDUwLTQ5LDE1MC01MCwxNTAsNTAsNTAsNDloMTQ5bDE5NS05OEwxMzAwLDBsMzAwLDQwMEwxMzAwLDYwMWwyMDEsOTlMMTI0OCw4MDBsMiwxMDEtMTUwLDMwMCw1MCwxOTktMTUwLDIwMEg2MDBMNDUwLDE0MDBsNTEtMTk5TDM1MCw5MDFWODAwTDEwMSw3MDBsMjAwLTk5TDAsNDAwWk01MDAsNTUwSDYwMEw4MDAsNjUwbDIwMC0xMDBoMTAwVjg1MEgxMDAwVjY1MEw4MDAsNzUwLDYwMCw2NTBWODUwSDUwMFY1NTBaIi8+DQo8L3N2Zz4=")}})(),o})()));
|
|
1
|
+
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("turbogrid")):"function"==typeof define&&define.amd?define("monocart-common",["turbogrid"],t):"object"==typeof exports?exports["monocart-common"]=t(require("turbogrid")):e["monocart-common"]=t(e.turbogrid)}(self,(e=>(()=>{var t={162:function(e,t,r){var n,o,a;o=[],void 0===(a="function"==typeof(n=function(){"use strict";function t(e,t){return void 0===t?t={autoBom:!1}:"object"!=typeof t&&(console.warn("Deprecated: Expected third argument to be a object"),t={autoBom:!t}),t.autoBom&&/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(e.type)?new Blob(["\ufeff",e],{type:e.type}):e}function n(e,t,r){var n=new XMLHttpRequest;n.open("GET",e),n.responseType="blob",n.onload=function(){c(n.response,t,r)},n.onerror=function(){console.error("could not download file")},n.send()}function o(e){var t=new XMLHttpRequest;t.open("HEAD",e,!1);try{t.send()}catch(e){}return 200<=t.status&&299>=t.status}function a(e){try{e.dispatchEvent(new MouseEvent("click"))}catch(r){var t=document.createEvent("MouseEvents");t.initMouseEvent("click",!0,!0,window,0,0,0,80,20,!1,!1,!1,!1,0,null),e.dispatchEvent(t)}}var i="object"==typeof window&&window.window===window?window:"object"==typeof self&&self.self===self?self:"object"==typeof r.g&&r.g.global===r.g?r.g:void 0,s=i.navigator&&/Macintosh/.test(navigator.userAgent)&&/AppleWebKit/.test(navigator.userAgent)&&!/Safari/.test(navigator.userAgent),c=i.saveAs||("object"!=typeof window||window!==i?function(){}:"download"in HTMLAnchorElement.prototype&&!s?function(e,t,r){var s=i.URL||i.webkitURL,c=document.createElement("a");t=t||e.name||"download",c.download=t,c.rel="noopener","string"==typeof e?(c.href=e,c.origin===location.origin?a(c):o(c.href)?n(e,t,r):a(c,c.target="_blank")):(c.href=s.createObjectURL(e),setTimeout((function(){s.revokeObjectURL(c.href)}),4e4),setTimeout((function(){a(c)}),0))}:"msSaveOrOpenBlob"in navigator?function(e,r,i){if(r=r||e.name||"download","string"!=typeof e)navigator.msSaveOrOpenBlob(t(e,i),r);else if(o(e))n(e,r,i);else{var s=document.createElement("a");s.href=e,s.target="_blank",setTimeout((function(){a(s)}))}}:function(e,t,r,o){if((o=o||open("","_blank"))&&(o.document.title=o.document.body.innerText="downloading..."),"string"==typeof e)return n(e,t,r);var a="application/octet-stream"===e.type,c=/constructor/i.test(i.HTMLElement)||i.safari,u=/CriOS\/[\d]+/.test(navigator.userAgent);if((u||a&&c||s)&&"undefined"!=typeof FileReader){var l=new FileReader;l.onloadend=function(){var e=l.result;e=u?e:e.replace(/^data:[^;]*;/,"data:attachment/file;"),o?o.location.href=e:location=e,o=null},l.readAsDataURL(e)}else{var f=i.URL||i.webkitURL,d=f.createObjectURL(e);o?o.location=d:location.href=d,o=null,setTimeout((function(){f.revokeObjectURL(d)}),4e4)}});i.saveAs=c.saveAs=c,e.exports=c})?n.apply(t,o):n)||(e.exports=a)},925:e=>{var t,r,n=(t=(e,t)=>{t.exports={data:'(()=>{var x=(e,n)=>()=>(n||e((n={exports:{}}).exports,n),n.exports);var S=x((V,R)=>{var _=0,p=-3;function b(){this.table=new Uint16Array(16),this.trans=new Uint16Array(288)}function N(e,n){this.source=e,this.sourceIndex=0,this.tag=0,this.bitcount=0,this.dest=n,this.destLen=0,this.ltree=new b,this.dtree=new b}var y=new b,k=new b,w=new Uint8Array(30),h=new Uint16Array(30),L=new Uint8Array(30),T=new Uint16Array(30),O=new Uint8Array([16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15]),A=new b,c=new Uint8Array(288+32);function D(e,n,r,a){var t,i;for(t=0;t<r;++t)e[t]=0;for(t=0;t<30-r;++t)e[t+r]=t/r|0;for(i=a,t=0;t<30;++t)n[t]=i,i+=1<<e[t]}function z(e,n){var r;for(r=0;r<7;++r)e.table[r]=0;for(e.table[7]=24,e.table[8]=152,e.table[9]=112,r=0;r<24;++r)e.trans[r]=256+r;for(r=0;r<144;++r)e.trans[24+r]=r;for(r=0;r<8;++r)e.trans[24+144+r]=280+r;for(r=0;r<112;++r)e.trans[24+144+8+r]=144+r;for(r=0;r<5;++r)n.table[r]=0;for(n.table[5]=32,r=0;r<32;++r)n.trans[r]=r}var I=new Uint16Array(16);function l(e,n,r,a){var t,i;for(t=0;t<16;++t)e.table[t]=0;for(t=0;t<a;++t)e.table[n[r+t]]++;for(e.table[0]=0,i=0,t=0;t<16;++t)I[t]=i,i+=e.table[t];for(t=0;t<a;++t)n[r+t]&&(e.trans[I[n[r+t]]++]=t)}function B(e){e.bitcount--||(e.tag=e.source[e.sourceIndex++],e.bitcount=7);var n=e.tag&1;return e.tag>>>=1,n}function u(e,n,r){if(!n)return r;for(;e.bitcount<24;)e.tag|=e.source[e.sourceIndex++]<<e.bitcount,e.bitcount+=8;var a=e.tag&65535>>>16-n;return e.tag>>>=n,e.bitcount-=n,a+r}function v(e,n){for(;e.bitcount<24;)e.tag|=e.source[e.sourceIndex++]<<e.bitcount,e.bitcount+=8;var r=0,a=0,t=0,i=e.tag;do a=2*a+(i&1),i>>>=1,++t,r+=n.table[t],a-=n.table[t];while(a>=0);return e.tag=i,e.bitcount-=t,n.trans[r+a]}function C(e,n,r){var a,t,i,o,s,f;for(a=u(e,5,257),t=u(e,5,1),i=u(e,4,4),o=0;o<19;++o)c[o]=0;for(o=0;o<i;++o){var F=u(e,3,0);c[O[o]]=F}for(l(A,c,0,19),s=0;s<a+t;){var g=v(e,A);switch(g){case 16:var M=c[s-1];for(f=u(e,2,3);f;--f)c[s++]=M;break;case 17:for(f=u(e,3,3);f;--f)c[s++]=0;break;case 18:for(f=u(e,7,11);f;--f)c[s++]=0;break;default:c[s++]=g;break}}l(n,c,0,a),l(r,c,a,t)}function U(e,n,r){for(;;){var a=v(e,n);if(a===256)return _;if(a<256)e.dest[e.destLen++]=a;else{var t,i,o,s;for(a-=257,t=u(e,w[a],h[a]),i=v(e,r),o=e.destLen-u(e,L[i],T[i]),s=o;s<o+t;++s)e.dest[e.destLen++]=e.dest[s]}}}function K(e){for(var n,r,a;e.bitcount>8;)e.sourceIndex--,e.bitcount-=8;if(n=e.source[e.sourceIndex+1],n=256*n+e.source[e.sourceIndex],r=e.source[e.sourceIndex+3],r=256*r+e.source[e.sourceIndex+2],n!==(~r&65535))return p;for(e.sourceIndex+=4,a=n;a;--a)e.dest[e.destLen++]=e.source[e.sourceIndex++];return e.bitcount=0,_}function j(e,n){var r=new N(e,n),a,t,i;do{switch(a=B(r),t=u(r,2,0),t){case 0:i=K(r);break;case 1:i=U(r,y,k);break;case 2:C(r,r.ltree,r.dtree),i=U(r,r.ltree,r.dtree);break;default:i=p}if(i!==_)throw new Error("Data error")}while(!a);return r.destLen<r.dest.length?typeof r.dest.slice=="function"?r.dest.slice(0,r.destLen):r.dest.subarray(0,r.destLen):r.dest}z(y,k);D(w,h,4,3);D(L,T,2,1);w[28]=0;h[28]=258;R.exports=j});var E=x((W,q)=>{var G=S(),H=e=>Uint8Array.from(atob(e),n=>n.charCodeAt(0)),J=e=>new TextDecoder().decode(e);q.exports=function(e){if(e){let[n,r]=e.split(".");if(n&&r){let a=H(n),t=new Uint8Array(parseInt(r));return G(a,t),J(t)}}}});var P=E();onmessage=function(e){postMessage(P(e.data))};postMessage("workerReady");})();\n'}},()=>(r||t((r={exports:{}}).exports,r),r.exports))();e.exports=e=>new Promise((t=>{let r=new Worker(URL.createObjectURL(new Blob([n.data],{type:"application/javascript"})));r.onmessage=n=>{"workerReady"!==n.data?(t(n.data),r.terminate()):r.postMessage(e)},r.onerror=e=>{t({error:e}),r.terminate()}}))},209:e=>{const t={tagPattern:/(\s*)@([^@\s]+)(\s*)/g,attachments:{audit:{name:"audit",contentType:"text/html",reportFile:"audit-report.json"},coverage:{name:"coverage",contentType:"text/html",reportFile:"coverage-report.json"},network:{name:"network",contentType:"text/html",reportFile:"network-report.json"}},pageTimings:[{key:"onContentLoad",name:"Content Loaded",color:"#1a1aa6"},{key:"onLoad",name:"Page Loaded",color:"#c80000"}],timings:[{key:"blocked",name:"Blocking",color:"#858585"},{key:"dns",name:"DNS Lookup",color:"#009688"},{key:"connect",name:"Connecting",color:"#b52dcd"},{key:"send",name:"Sending",color:"#74979a"},{key:"wait",name:"Waiting",color:"#00a846"},{key:"receive",name:"Receiving",color:"#0299de"}],hasOwn:function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},isNull:function(e){return null==e},uid:function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:20;const t="0123456789abcdefghijklmnopqrstuvwxyz";let r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";for(;e--;)r+=t[36*Math.random()|0];return r},zero:function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:2;return(e=`${e}`).padStart(t,"0")},toNum:function(e,t){return"number"!=typeof e&&(e=parseFloat(e)),isNaN(e)&&(e=0),t&&(e=Math.round(e)),e},isList:function(e){return!!(e&&e instanceof Array&&e.length>0)},forEach:function(e,r){const n=e=>"break"===e||!1===e,o=(e,a)=>{if(t.isList(e))for(const t of e){const e=r(t,a);if(n(e))return e;const i=o(t.subs,t);if(n(i))return i}};o(e)},formatPath:function(e){return e&&(e=e.replace(/\\/g,"/")),e},getCurrentTrendInfo:e=>{const{date:t,duration:r,summary:n}=e,o={date:t,duration:r};return Object.keys(n).forEach((e=>{const t=n[e];o[e]=t.value})),o},isTagItem:e=>"case"===e.type||"suite"===e.type&&"describe"===e.suiteType,delay:function(e){return new Promise((t=>{e?setTimeout(t,e):setImmediate(t)}))},generatePercentChart:function(e){return`<div style="--mcr-percent:${e}%;" class="mcr-percent-chart"></div>`},getStatus:(e,t)=>t?e<t[0]?"low":e<t[1]?"medium":"high":"unknown",isJsonType:e=>!(!e||"application/json"!==e&&"json"!==e),isMarkdownType:e=>!(!e||"text/markdown"!==e&&"markdown"!==e),isTextType(e){if(e){if(e.startsWith("text"))return!0;if(t.isMarkdownType(e))return!0;if(t.isJsonType(e))return!0}return!1},dFixed:function(e){let r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:1;return Number.isInteger(e)?e:t.toNum(t.toNum(e).toFixed(r))},pxFixed:e=>{const t=Math.floor(e);return e<t+.5?t+.5:t+1.5},point:(e,r)=>`${t.dFixed(e)},${t.dFixed(r)}`,NF:function(e){return"number"==typeof e&&e?e.toLocaleString():e},PF:function(e){let r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:1,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:1,o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"%",a=arguments.length>4&&void 0!==arguments[4]?arguments[4]:"";e=t.toNum(e),r=t.toNum(r);let i=0;r&&(i=e/r);const s=(100*i).toFixed(n);return o?s+a+o:parseFloat(s)},PSF:function(e){let r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:1,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:1;return t.PF(e,r,n,"%"," ")},PNF:function(e){let r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:1,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:1;return t.PF(e,r,n,"")},BF:function(e){let r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:1,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"";if(0===(e=t.toNum(e,!0)))return`0${n}B`;let o="";e<0&&(e=Math.abs(e),o="-");const a=["B","KB","MB","GB","TB","PB","EB","ZB","YB"];for(let t=0,i=a.length;t<i;t++){const i=Math.pow(1024,t),s=Math.pow(1024,t+1);if(e>i&&e<s){const s=a[t];e=o+(e/i).toFixed(r)+n+s;break}}return e},BSF:function(e){let r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:1;return t.BF(e,r," ")},TF:function(e){let r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";const n=t.toNum(e,!0);if(n<1e3)return`${n}${r}ms`;if(n<6e4){const e=Math.floor(n/1e3),t=Math.round((n-1e3*e)/100);return t?`${e}.${t}${r}s`:`${e}${r}s`}const o=Math.round(n/1e3),a=60,i=3600,s=24*i;if(o<i){const e=Math.floor(o/a);return`${e}${r}m ${o-e*a}${r}s`}if(o<s){const e=Math.floor(o/i),t=Math.floor((o-e*i)/a);return`${e}${r}h ${t}${r}m ${o-e*i-t*a}${r}s`}const c=Math.floor(o/s),u=Math.floor((o-c*s)/i),l=Math.floor((o-c*s-u*i)/a);return`${c}${r}d ${u}${r}h ${l}${r}m ${o-c*s-u*i-l*a}${r}s`},TSF:function(e){return t.TF(e," ")}};e.exports=t},46:t=>{"use strict";t.exports=e}},r={};function n(e){var o=r[e];if(void 0!==o)return o.exports;var a=r[e]={exports:{}};return t[e].call(a.exports,a,a.exports,n),a.exports}n.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return n.d(t,{a:t}),t},n.d=(e,t)=>{for(var r in t)n.o(t,r)&&!n.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},n.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),n.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),n.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var o={};return(()=>{"use strict";n.r(o),n.d(o,{CommonUtil:()=>k,debounce:()=>t,decodeIcons:()=>M,hash:()=>g,inflate:()=>i(),microtask:()=>r,niceTicks:()=>p,saveAs:()=>h.saveAs,setFavicon:()=>A,store:()=>b});class e{start(e){this.callback=e,this.started||(this.started=!0,this.create())}create(){if("function"!=typeof window.queueMicrotask){if("function"!=typeof Promise)throw new Error("Current browser does NOT support queueMicrotask or Promise");Promise.resolve().then((()=>{this.execute()}))}else window.queueMicrotask((()=>{this.execute()}))}execute(){if(!this.started)return;this.started=!1;const e=this.callback;this.callback=null,"function"==typeof e&&e.call(this)}cancel(){this.started=!1,this.callback=null}}const t=function(e,t=100){let r;const n=function(){clearTimeout(r),r=setTimeout((()=>{e.apply(this,arguments)}),t)};return n.cancel=()=>{clearTimeout(r)},n},r=function(t){const r=new e,n=function(){r.start((()=>{t.apply(this,arguments)}))};return n.cancel=()=>{r.cancel()},n};var a=n(925),i=n.n(a);function s(e){return""+e}function c(e){var t=s(e).split(".");return t.length>1?t[1].length:0}function u(e){var t=s(e);return parseInt(t.replace(".",""))}function l(e,t){var r=c(e),n=c(t);if(r+n===0)return e+t;var o=Math.pow(10,Math.max(r,n));return(Math.round(e*o)+Math.round(t*o))/o}function f(e,t){var r=c(e),n=c(t);return r+n===0?e*t:u(e)*u(t)/Math.pow(10,r+n)}function d(e,t){var r=Math.floor(Math.log(e)/Math.log(10)),n=e/Math.pow(10,r);return(t?n<1.5?1:n<3?2:n<7?5:10:n<=1?1:n<=2?2:n<=5?5:10)*Math.pow(10,r)}var w=function(e){return"number"!=typeof e&&(e=parseFloat(e)),isNaN(e)&&(e=0),e};function p(e,t,r){if(e=w(e),t=w(t),(r=w(r))||(r=4),e===t)t=e+1;else if(e>t){var n=e;e=t,t=n}for(var o=d(t-e,!1),a=d(o/(r-1),!0),i=f(Math.floor(e/a),a),s=f(Math.ceil(t/a),a),c=[],u=i;u<=s;)c.push(u),u=l(u,a);return c}var h=n(162);const m={get:function(e){let t={};const r=location.hash.slice(1);if(r){const e=new URLSearchParams(r);t=Object.fromEntries(e)}return e?t[e]:t},set:function(e,t){if(!e)return;let r=e;2===arguments.length&&(r={},r[e]=t);const n=m.get();Object.keys(r).forEach((e=>{n[e]=r[e]}));const o=new URLSearchParams(n);location.hash=o.toString()},remove:function(e){if(!e)return void(location.hash="");let t=e;Array.isArray(e)||(t=[e]);const r=m.get();t.forEach((e=>{delete r[e]}));const n=new URLSearchParams(r);location.hash=n.toString()}},g=m,v=e=>`mcr-${e}`,b={get(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";const r=window.localStorage.getItem(v(e));return null===r?t:r},set(e,t){window.localStorage.setItem(v(e),t)},remove(e){window.localStorage.removeItem(v(e))}},M=e=>{const t=e.keys(),r={};return t.forEach((t=>{const n=t.toLowerCase().split("/").pop().slice(0,-4),o=e(t),a=o.slice(o.indexOf(",")+1),i=atob(a);r[n]=i})),r};var y=n(46),x=n(209),T=n.n(x);const k={...y.Util,...T(),isTouchDevice:function(){return"ontouchstart"in window||navigator.maxTouchPoints>0||navigator.msMaxTouchPoints>0}},A=()=>{const e=document.querySelector('link[rel="icon"]');e&&(e.href="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxNjAwIDE2MDAiPg0KICAgIDxwYXRoIGZpbGw9ImNob2NvbGF0ZSIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMzAwLDBMMjU3LDMwMmwxOTIsOThINjAwbDUwLTQ5LDE1MC01MCwxNTAsNTAsNTAsNDloMTQ5bDE5NS05OEwxMzAwLDBsMzAwLDQwMEwxMzAwLDYwMWwyMDEsOTlMMTI0OCw4MDBsMiwxMDEtMTUwLDMwMCw1MCwxOTktMTUwLDIwMEg2MDBMNDUwLDE0MDBsNTEtMTk5TDM1MCw5MDFWODAwTDEwMSw3MDBsMjAwLTk5TDAsNDAwWk01MDAsNTUwSDYwMEw4MDAsNjUwbDIwMC0xMDBoMTAwVjg1MEgxMDAwVjY1MEw4MDAsNzUwLDYwMCw2NTBWODUwSDUwMFY1NTBaIi8+DQo8L3N2Zz4=")}})(),o})()));
|