monocart-reporter 1.7.3 → 1.7.4

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
@@ -30,11 +30,18 @@
30
30
  * [Metadata](#metadata)
31
31
  * [Trend Chart](#trend-chart)
32
32
  * [Attach Lighthouse Audit Report](#attach-lighthouse-audit-report)
33
- * [Attach Code Coverage Report](#attach-code-coverage-report)
33
+ * [Code Coverage Report](#code-coverage-report)
34
+ - [Coverage Options](#coverage-options)
35
+ - [Istanbul](#istanbul)
36
+ - [V8](#v8)
37
+ - [V8 to Istanbul](#v8-to-istanbul)
34
38
  - [Compare Istanbul, V8 and V8 to Istanbul](#compare-istanbul-v8-and-v8-to-istanbul)
35
39
  - [Global Coverage Report](#global-coverage-report) for Component Testing
36
40
  * [Attach Network Report](#attach-network-report)
37
41
  * [Global State Management](#global-state-management)
42
+ - [Setup Global State](#setup-global-state)
43
+ - [Get, Set, and Remove Global Data](#get-set-and-remove-global-data)
44
+ - [Send and Receive Messages between Processes](#send-and-receive-messages-between-processes)
38
45
  * [Merge Shard Reports](#merge-shard-reports)
39
46
  * [onEnd hook](#onend-hook)
40
47
  - [Send Email](#send-email)
@@ -46,7 +53,7 @@
46
53
  - [Teams Integration](#teams-integration)
47
54
  - [Dingtalk/Weixin/Feishu Integration](#dingtalkweixinfeishu-integration)
48
55
  * [Contributing](#contributing)
49
- * [Changelog](#changelog)
56
+ * [Changelog](CHANGELOG.md)
50
57
  ## Preview
51
58
  [https://cenfun.github.io/monocart-reporter](https://cenfun.github.io/monocart-reporter)
52
59
 
@@ -625,23 +632,27 @@ test('attach lighthouse audit report', async () => {
625
632
  ```
626
633
  Preview [Audit HTML Report](https://cenfun.github.io/monocart-reporter/audit-78a0a1cc4420ee9da113/index.html)
627
634
 
628
- ## Attach Code Coverage Report
629
- Attach a code coverage report with API `attachCoverageReport(data, testInfo, options)`. Arguments:
630
- - `data` There are two supported data inputs `Istanbul` (Object) or `V8` (Array)
631
- - `testInfo` see [TestInfo](https://playwright.dev/docs/api/class-testinfo)
632
- - `options` (Object)
633
- - `title` (String) report title.
634
- - `toIstanbul` (Boolean) Whether to convert to Istanbul report from V8 list. Defaults to `html-spa` report | (String) or using `html` report. V8 only.
635
- - `entryFilter` (Function) A filter function to execute for each element in the V8 list. V8 only.
636
- - `sourceFilter` (Function) A filter function to execute for each element in the sources which unpacked from the source map. Sourcemap only.
637
- - `watermarks` (Object) Istanbul watermarks, see [here](https://github.com/istanbuljs/istanbuljs/tree/master/packages/istanbul-lib-report) | (Array) V8 watermarks, Defaults to `[50, 80]`.
638
- - `lcov` (Boolean) Whether to create `lcov.info`. (for Sonar coverage)
639
- - `sourcePath` (Function) source path handler, return a new source path. ([issue#53](https://github.com/cenfun/monocart-reporter/issues/53)).
640
- - `inline` (Boolean) Whether inline all scripts to the single HTML file. V8 only.
641
-
642
- (see example: [report-coverage.spec.js](https://github.com/cenfun/monocart-reporter/blob/main/tests/report-coverage/report-coverage.spec.js))
643
-
644
- - [Istanbul](https://github.com/istanbuljs) 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.js](https://github.com/cenfun/monocart-reporter-test/blob/main/packages/coverage/webpack.config.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.
635
+ ## Code Coverage Report
636
+ There are two APIs for coverage report:
637
+ - `attachCoverageReport(data, testInfo, options)`
638
+ Attach a coverage report to a test. Arguments:
639
+ - `data` There are two supported data inputs `Istanbul` (Object) or `V8` (Array)
640
+ - `testInfo` see [TestInfo](https://playwright.dev/docs/api/class-testinfo)
641
+ - `options` (Object) see [Coverage Options](#coverage-options)
642
+ - `addCoverageReport(data, testInfo)` Add coverage to global coverage report from a test. see [Global Coverage Report](#global-coverage-report)
643
+
644
+ ### Coverage Options
645
+ - `title` (String) report title.
646
+ - `toIstanbul` (Boolean) Whether to convert to Istanbul report from V8 list. Defaults to `html-spa` report | (String) or using `html` report. V8 only.
647
+ - `entryFilter` (Function) A filter function to execute for each element in the V8 list. V8 only.
648
+ - `sourceFilter` (Function) A filter function to execute for each element in the sources which unpacked from the source map. Sourcemap only.
649
+ - `watermarks` (Object) Istanbul watermarks, see [here](https://github.com/istanbuljs/istanbuljs/tree/master/packages/istanbul-lib-report) | (Array) V8 watermarks, Defaults to `[50, 80]`.
650
+ - `lcov` (Boolean) Whether to create `lcov.info`. (for Sonar coverage)
651
+ - `sourcePath` (Function) source path handler, return a new source path. ([issue#53](https://github.com/cenfun/monocart-reporter/issues/53)).
652
+ - `inline` (Boolean) Whether inline all scripts to the single HTML file. V8 only.
653
+
654
+ ### [Istanbul](https://github.com/istanbuljs)
655
+ 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.
645
656
  ```js
646
657
  import { test, expect } from '@playwright/test';
647
658
  import { attachCoverageReport } from 'monocart-reporter';
@@ -669,9 +680,8 @@ test('Take Istanbul coverage report', async ({ page }) => {
669
680
  });
670
681
  ```
671
682
 
672
- ![](/docs/istanbul.png)
673
-
674
- - [V8](https://v8.dev/blog/javascript-code-coverage) ([Chromium-based only](https://chromedevtools.github.io/devtools-protocol/tot/Profiler/#type-ScriptCoverage)) Simply take coverage data with [class-coverage](https://playwright.dev/docs/api/class-coverage) APIs, the V8 HTML report will be generated.
683
+ ### [V8](https://v8.dev/blog/javascript-code-coverage)
684
+ 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.
675
685
  ```js
676
686
  import { test, expect } from '@playwright/test';
677
687
  import { attachCoverageReport } from 'monocart-reporter';
@@ -712,7 +722,8 @@ test('Take V8 and Istanbul coverage report', async ({ page }) => {
712
722
 
713
723
  ![](/docs/v8.gif)
714
724
 
715
- - `V8 to Istanbul` Take V8 coverage data with [class-coverage](https://playwright.dev/docs/api/class-coverage) APIs, then the V8 coverage format will be converted to Istanbul's coverage format. The Istanbul HTML report will be generated.
725
+ ### V8 to Istanbul
726
+ Take V8 coverage data and convert it to Istanbul's coverage format. The Istanbul HTML report will be generated.
716
727
  ```js
717
728
  const report = await attachCoverageReport(coverageList, test.info(), {
718
729
  toIstanbul: true
@@ -724,7 +735,7 @@ const report = await attachCoverageReport(coverageList, test.info(), {
724
735
  | :--------------| :------ | :------ | :---------------------- |
725
736
  | Input data format | Istanbul (Object) | V8 (Array) | V8 (Array) |
726
737
  | Options | `watermarks: {}` | `watermarks: [50, 80]` | `toIstanbul: true, watermarks: {}` |
727
- | Output report | [Istanbul HTML report](https://cenfun.github.io/monocart-reporter/coverage-6eaa280d68aea439a847/index.html) | [V8 HTML report](https://cenfun.github.io/monocart-reporter/coverage/index.html) | [Istanbul HTML report](https://cenfun.github.io/monocart-reporter/coverage-bbea6fd47b9c551582fe/index.html) |
738
+ | Output report | [Istanbul HTML report](https://cenfun.github.io/monocart-reporter/coverage-77aa6f37601a97417803/index.html) | [V8 HTML report](https://cenfun.github.io/monocart-reporter/coverage/index.html) | [Istanbul HTML report](https://cenfun.github.io/monocart-reporter/coverage-01eebe0ebc796534d759-1/index.html) |
728
739
  | Indicators | Covered Lines, Branches, Statements and Functions, Execution Counts | Covered Bytes, Lines (after formatted) Execution Counts | Covered Lines, Branches, Statements and Functions, Execution Counts |
729
740
  | Source code without [instrumentation](https://github.com/istanbuljs/babel-plugin-istanbul) | ❌ | ✅ | ✅ |
730
741
  | CSS coverage | ❌ | ✅ | ❌ |
@@ -732,7 +743,8 @@ const report = await attachCoverageReport(coverageList, test.info(), {
732
743
  | Code formatting | N/A | ✅ | ❌ |
733
744
 
734
745
  ### Global Coverage Report
735
- 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. The API is `addCoverageReport(v8list, testInfo)`, currently supported `V8` only. Here is an example for Playwright Component Testing [playwright-ct-vue](https://github.com/cenfun/playwright-ct-vue).
746
+ 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.
747
+ - The global coverage options see [Coverage Options](#coverage-options)
736
748
  ```js
737
749
  // playwright.config.js
738
750
  module.exports = {
@@ -749,6 +761,54 @@ module.exports = {
749
761
  ]
750
762
  };
751
763
  ```
764
+ - It is recommended to use [automatic fixtures](https://playwright.dev/docs/test-fixtures#automatic-fixtures) to add coverage for each test:
765
+ ```js
766
+ // fixtures.js for v8
767
+ import { test as testBase, expect } from '@playwright/test';
768
+ import { addCoverageReport } from 'monocart-reporter';
769
+
770
+ const test = testBase.extend({
771
+ autoTestFixture: [async ({ page }, use) => {
772
+
773
+ const isChromium = test.info().project.name === 'Desktop Chromium';
774
+
775
+ // console.log('autoTestFixture setup...');
776
+ // coverage API is chromium only
777
+ if (isChromium) {
778
+ await Promise.all([
779
+ page.coverage.startJSCoverage({
780
+ resetOnNavigation: false
781
+ }),
782
+ page.coverage.startCSSCoverage({
783
+ resetOnNavigation: false
784
+ })
785
+ ]);
786
+ }
787
+
788
+ await use('autoTestFixture');
789
+
790
+ // console.log('autoTestFixture teardown...');
791
+ if (isChromium) {
792
+ const [jsCoverage, cssCoverage] = await Promise.all([
793
+ page.coverage.stopJSCoverage(),
794
+ page.coverage.stopCSSCoverage()
795
+ ]);
796
+ const coverageList = [... jsCoverage, ... cssCoverage];
797
+ // console.log(coverageList.map((item) => item.url));
798
+ await addCoverageReport(coverageList, test.info());
799
+ }
800
+
801
+ }, {
802
+ scope: 'test',
803
+ auto: true
804
+ }]
805
+ });
806
+ export { test, expect };
807
+ ```
808
+ - The coverage examples for Playwright component testing:
809
+ - [playwright-ct-vue](https://github.com/cenfun/playwright-ct-vue)
810
+ - [playwright-ct-react](https://github.com/cenfun/playwright-ct-react)
811
+ - [playwright-ct-svelte](https://github.com/cenfun/playwright-ct-svelte)
752
812
 
753
813
  ## Attach Network Report
754
814
  Attach a network report with API `attachNetworkReport(har, testInfo)`. Arguments:
@@ -826,7 +886,7 @@ Preview [Network HTML Report](https://cenfun.github.io/monocart-reporter/network
826
886
 
827
887
  ## Global State Management
828
888
  When tests are executed in [isolation](https://playwright.dev/docs/browser-contexts) mode, the reporter and each test may run in a different process, they cannot share data with each other. we can start a local WebSocket server to serve the global data, and read/write the global data with `useState` API from a test.
829
- - setup global state
889
+ ### Setup Global State
830
890
  ```js
831
891
  module.exports = {
832
892
  reporter: [
@@ -850,7 +910,7 @@ module.exports = {
850
910
  ]
851
911
  };
852
912
  ```
853
- - get/set/remove global data
913
+ ### Get, Set, and Remove Global Data
854
914
  ```js
855
915
  const { test } = require('@playwright/test');
856
916
  const { useState } = require('monocart-reporter');
@@ -878,7 +938,23 @@ test('state test', async ({ browserName }) => {
878
938
  console.log(all);
879
939
  });
880
940
  ```
881
- - customize sending and receiving messages
941
+ ### Send and Receive Messages between Processes
942
+ - send message and receive response from a test (child process)
943
+ ```js
944
+ const { test } = require('@playwright/test');
945
+ const { useState } = require('monocart-reporter');
946
+ test('state test send message', async () => {
947
+ const state = useState({
948
+ // port: 8130
949
+ });
950
+ const response = await state.send({
951
+ testId: test.info().testId,
952
+ data: 'my test data'
953
+ });
954
+ console.log('receive response on client', response);
955
+ });
956
+ ```
957
+ - receive message and send response from global state (main process)
882
958
  ```js
883
959
  module.exports = {
884
960
  reporter: [
@@ -887,28 +963,23 @@ module.exports = {
887
963
  name: "My Test Report",
888
964
  outputFile: './test-results/report.html',
889
965
  state: {
890
- // receive messages and send back response
891
- onReceive: function(... args) {
892
- console.log('receive on server', args);
893
- return ['custom response', ... args];
966
+ onReceive: function(message) {
967
+ const test = this.getTest(message.testId);
968
+ if (test) {
969
+ // current test
970
+ }
971
+
972
+ console.log('receive message on server', message);
973
+
974
+ return {
975
+ data: 'my response data'
976
+ };
894
977
  }
895
978
  }
896
979
  }]
897
980
  ]
898
981
  };
899
982
  ```
900
- ```js
901
- const { test } = require('@playwright/test');
902
- const { useState } = require('monocart-reporter');
903
- test('state test', async ({ browserName }) => {
904
- const state = useState({
905
- // port: 8130
906
- });
907
- // send messages
908
- const res = await state.send('string data', {});
909
- console.log('receive on client', res);
910
- });
911
- ```
912
983
 
913
984
 
914
985
  ## Merge Shard Reports
@@ -944,7 +1015,7 @@ await merge(reportDataList, {
944
1015
  ```
945
1016
  Preview [merged report](https://cenfun.github.io/monocart-reporter-test/merged)
946
1017
 
947
- ## onEnd hook
1018
+ ## onEnd Hook
948
1019
  The `onEnd` function will be executed after report generated. Arguments:
949
1020
  - `reportData` all report data, properties:
950
1021
  - `name` (String) report name
@@ -981,54 +1052,41 @@ module.exports = {
981
1052
  };
982
1053
  ```
983
1054
  ## Send Email
984
- Simply send email with [nodemailer](https://nodemailer.com), check example: [send-email](https://github.com/cenfun/monocart-reporter-test/tree/main/integrations/send-email)
985
-
986
- ![](/docs/email.png)
987
-
1055
+ - Simply send email with [nodemailer](https://nodemailer.com)
1056
+ - Example: [send-email](https://github.com/cenfun/monocart-reporter-test/tree/main/integrations/send-email)
988
1057
 
989
1058
  ## Testrail Integration
990
- Send test results to your Testrail, check example: [testrail](https://github.com/cenfun/monocart-reporter-test/tree/main/integrations/testrail)
991
-
992
- ![](/docs/testrail.png)
1059
+ - Send test results to your [Testrail](https://www.testrail.com/)
1060
+ - Example: [testrail](https://github.com/cenfun/monocart-reporter-test/tree/main/integrations/testrail)
993
1061
 
994
1062
  ## Jira + Zephyr Scale Integration
995
- Create test cycle and executions with [zephyr-scale-api](https://support.smartbear.com/zephyr-scale-cloud/api-docs/), check example: [zephyr-scale](https://github.com/cenfun/monocart-reporter-test/tree/main/integrations/zephyr-scale)
996
-
997
- ![](/docs/zephyr.png)
1063
+ - Create test cycle and executions with [zephyr-scale-api](https://support.smartbear.com/zephyr-scale-cloud/api-docs/)
1064
+ - Example: [zephyr-scale](https://github.com/cenfun/monocart-reporter-test/tree/main/integrations/zephyr-scale)
998
1065
 
999
1066
  ## Jira + Xray Integration
1000
1067
  - Import test execution results with [Xray REST API](https://docs.getxray.app/display/XRAYCLOUD/REST+API)
1001
1068
  - Update Jira issue status with [Jira Transition API](https://developer.atlassian.com/cloud/jira/platform/rest/v3/api-group-issues/#api-rest-api-3-issue-issueidorkey-transitions-post)
1002
- check example: [xray](https://github.com/cenfun/monocart-reporter-test/tree/main/integrations/xray)
1003
-
1004
- ![](/docs/xray.png)
1069
+ - Example: [xray](https://github.com/cenfun/monocart-reporter-test/tree/main/integrations/xray)
1005
1070
 
1006
1071
  ## Slack Integration
1007
- 1. Simply send message with [@slack/webhook](https://github.com/slackapi/node-slack-sdk), example: [slack-webhook](https://github.com/cenfun/monocart-reporter-test/tree/main/integrations/slack-webhook)
1008
- 2. Recommended: Post chat message and upload image with [@slack/web-api](https://github.com/slackapi/node-slack-sdk), example: [slack-web-api](https://github.com/cenfun/monocart-reporter-test/tree/main/integrations/slack-web-api)
1009
-
1010
- ![](/docs/slack.png)
1072
+ - Simply send message with [@slack/webhook](https://github.com/slackapi/node-slack-sdk)
1073
+ - Example: [slack-webhook](https://github.com/cenfun/monocart-reporter-test/tree/main/integrations/slack-webhook)
1074
+ - Post chat message and upload image with [@slack/web-api](https://github.com/slackapi/node-slack-sdk)
1075
+ - Example: [slack-web-api](https://github.com/cenfun/monocart-reporter-test/tree/main/integrations/slack-web-api)
1011
1076
 
1012
1077
  ## Discord Integration
1013
- Using [Discord webhooks](https://discord.com/developers/docs/resources/webhook) to post messages to channels. check example: [discord-webhook](https://github.com/cenfun/monocart-reporter-test/tree/main/integrations/discord-webhook)
1014
-
1015
- ![](/docs/discord.png)
1078
+ - Using [Discord webhooks](https://discord.com/developers/docs/resources/webhook) to post messages to channels.
1079
+ - Example: [discord-webhook](https://github.com/cenfun/monocart-reporter-test/tree/main/integrations/discord-webhook)
1016
1080
 
1017
1081
  ## Teams Integration
1018
- Please create an [Incoming Webhooks](https://learn.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/how-to/add-incoming-webhook) for the channel first. check example: [teams-webhook](https://github.com/cenfun/monocart-reporter-test/tree/main/integrations/teams-webhook)
1019
-
1020
- ![](/docs/teams.png)
1082
+ - Please create an [Incoming Webhooks](https://learn.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/how-to/add-incoming-webhook) for the channel first.
1083
+ - Example: [teams-webhook](https://github.com/cenfun/monocart-reporter-test/tree/main/integrations/teams-webhook)
1021
1084
 
1022
1085
  ## Dingtalk/Weixin/Feishu Integration
1023
1086
  - [dingtalk-webhook](https://github.com/cenfun/monocart-reporter-test/tree/main/integrations/dingtalk-webhook)
1024
1087
  - [weixin-webhook](https://github.com/cenfun/monocart-reporter-test/tree/main/integrations/weixin-webhook)
1025
1088
  - [feishu-webhook](https://github.com/cenfun/monocart-reporter-test/tree/main/integrations/feishu-webhook)
1026
1089
 
1027
- ## Dependencies
1028
- - UI Framework [Vue 3](https://github.com/vuejs/core)
1029
- - Lightweight UI Components [vine-ui](https://github.com/cenfun/vine-ui)
1030
- - High Performance Grid [turbogrid](https://github.com/cenfun/turbogrid)
1031
- - String compress/decompress [lz-utils](https://github.com/cenfun/lz-utils)
1032
1090
 
1033
1091
  ## Contributing
1034
1092
  ```sh
@@ -1038,5 +1096,8 @@ npm run test
1038
1096
  npm run build
1039
1097
  npm run dev
1040
1098
  ```
1041
- ## CHANGELOG
1042
- - [CHANGELOG.md](CHANGELOG.md)
1099
+ ## Dependencies
1100
+ - UI Framework [Vue 3](https://github.com/vuejs/core)
1101
+ - Lightweight UI Components [vine-ui](https://github.com/cenfun/vine-ui)
1102
+ - High Performance Grid [turbogrid](https://github.com/cenfun/turbogrid)
1103
+ - String compress/decompress [lz-utils](https://github.com/cenfun/lz-utils)
@@ -1,6 +1,6 @@
1
1
  const fs = require('fs');
2
- const { parse } = require('../runtime/monocart-vendor.js');
3
2
  const Util = require('../utils/util.js');
3
+ const parseSource = require('../utils/parse-source.js');
4
4
 
5
5
  const cacheMap = new Map();
6
6
 
@@ -15,24 +15,25 @@ function getEmptyLines(lines) {
15
15
  return emptyLines;
16
16
  }
17
17
 
18
- const getFileComments = (filePath, parserOptions = {}) => {
18
+ const getFileComments = (sourcePath, options = {}) => {
19
19
 
20
20
  const map = new Map();
21
21
 
22
- if (!fs.existsSync(filePath)) {
22
+ if (!fs.existsSync(sourcePath)) {
23
23
  return map;
24
24
  }
25
25
 
26
- // console.log('babel parse file: ', filePath);
26
+ // console.log('babel parse file: ', sourcePath);
27
27
 
28
- const source = fs.readFileSync(filePath).toString('utf-8');
28
+ const source = fs.readFileSync(sourcePath).toString('utf-8');
29
29
 
30
- let ast;
31
- try {
32
- ast = parse(source, parserOptions);
33
- } catch (e) {
34
- Util.logError(e.message);
35
- Util.logError(`failed to collect comments from the file: ${Util.relativePath(filePath)}`);
30
+ const ast = parseSource({
31
+ source,
32
+ sourcePath,
33
+ options
34
+ });
35
+
36
+ if (!ast) {
36
37
  return map;
37
38
  }
38
39
 
@@ -1,11 +1,10 @@
1
1
  const path = require('path');
2
2
 
3
3
  const Util = require('../../../utils/util.js');
4
+ const decodeMappings = require('../../../utils/decode-mappings.js');
4
5
 
5
6
  // position mapping for conversion between offset and line/column
6
7
  const PositionMapping = require('./position-mapping.js');
7
-
8
- const decodeMappings = require('./decode-mappings.js');
9
8
  const findOriginalRange = require('./find-original-range.js');
10
9
 
11
10
  const { dedupeCountRanges } = require('./dedupe.js');
@@ -222,8 +221,6 @@ const getDistCoverage = (item, state) => {
222
221
  addJsCoverage(coverage, block, range, index, positionMapping);
223
222
  });
224
223
  });
225
- // only for js
226
- item.ranges = coverage.ranges;
227
224
  return coverage;
228
225
  }
229
226
 
@@ -238,10 +235,76 @@ const unpackDistSource = (item, state) => {
238
235
  const coverage = getDistCoverage(item, state);
239
236
  const sourcePath = item.sourcePath;
240
237
  state.coverageData[sourcePath] = getFileCoverage(sourcePath, coverage);
238
+ // after dedupe
239
+ item.ranges = coverage.ranges;
241
240
  };
242
241
 
243
242
  // ========================================================================================================
244
243
 
244
+ const decodeSourceMappings = async (sourceMap, generatedPositionMapping) => {
245
+
246
+ const decodedList = await decodeMappings(sourceMap.mappings);
247
+
248
+ const originalIndexMap = new Map();
249
+ sourceMap.sources.forEach((item, i) => {
250
+ originalIndexMap.set(i, []);
251
+ });
252
+
253
+ const allDecodedMappings = [];
254
+ let generatedIndex = 0;
255
+ decodedList.forEach((segments, generatedLine) => {
256
+ let item = null;
257
+ segments.forEach((segment) => {
258
+ const [generatedColumn, sourceIndex, originalLine, originalColumn] = segment;
259
+ const generatedOffset = generatedPositionMapping.locationToOffset({
260
+ // 1-base
261
+ line: generatedLine + 1,
262
+ column: generatedColumn
263
+ });
264
+
265
+ item = {
266
+ generatedOffset,
267
+ generatedLine,
268
+ generatedColumn,
269
+ generatedIndex,
270
+
271
+ sourceIndex,
272
+ originalLine,
273
+ originalColumn
274
+ };
275
+
276
+ allDecodedMappings.push(item);
277
+ generatedIndex += 1;
278
+
279
+ if (typeof sourceIndex === 'undefined') {
280
+ return;
281
+ }
282
+
283
+ originalIndexMap.get(sourceIndex).push(item);
284
+
285
+ });
286
+
287
+ // line last one
288
+ if (item) {
289
+ const line = generatedPositionMapping.getLine(item.generatedLine + 1);
290
+ // last column
291
+ item.generatedEndOffset = item.generatedOffset + (line.length - item.generatedColumn);
292
+ }
293
+
294
+ });
295
+
296
+ // defaults to sort by generated offset, not need sort
297
+ // allDecodedMappings.sort((a, b) => {
298
+ // return a.generatedOffset - b.generatedOffset;
299
+ // });
300
+
301
+ return {
302
+ allDecodedMappings,
303
+ originalIndexMap
304
+ };
305
+
306
+ };
307
+
245
308
  const getOriginalDecodedMappings = (originalIndexMap, sourceIndex, positionMapping) => {
246
309
  // all mappings for the original file sorted
247
310
  const decodedMappings = originalIndexMap.get(sourceIndex);
@@ -323,70 +386,6 @@ const initOriginalList = (sourceMap, originalIndexMap, fileSources, options) =>
323
386
  return map;
324
387
  };
325
388
 
326
- const decodeSourceMappings = async (sourceMap, generatedPositionMapping) => {
327
-
328
- const decodedList = await decodeMappings(sourceMap.mappings);
329
-
330
- const originalIndexMap = new Map();
331
- sourceMap.sources.forEach((item, i) => {
332
- originalIndexMap.set(i, []);
333
- });
334
-
335
- const allDecodedMappings = [];
336
- let generatedIndex = 0;
337
- decodedList.forEach((segments, generatedLine) => {
338
- let item = null;
339
- segments.forEach((segment) => {
340
- const [generatedColumn, sourceIndex, originalLine, originalColumn] = segment;
341
- const generatedOffset = generatedPositionMapping.locationToOffset({
342
- // 1-base
343
- line: generatedLine + 1,
344
- column: generatedColumn
345
- });
346
-
347
- item = {
348
- generatedOffset,
349
- generatedLine,
350
- generatedColumn,
351
- generatedIndex,
352
-
353
- sourceIndex,
354
- originalLine,
355
- originalColumn
356
- };
357
-
358
- allDecodedMappings.push(item);
359
- generatedIndex += 1;
360
-
361
- if (typeof sourceIndex === 'undefined') {
362
- return;
363
- }
364
-
365
- originalIndexMap.get(sourceIndex).push(item);
366
-
367
- });
368
-
369
- // line last one
370
- if (item) {
371
- const line = generatedPositionMapping.getLine(item.generatedLine + 1);
372
- // last column
373
- item.generatedEndOffset = item.generatedOffset + (line.length - item.generatedColumn);
374
- }
375
-
376
- });
377
-
378
- // defaults to sort by generated offset, not need sort
379
- // allDecodedMappings.sort((a, b) => {
380
- // return a.generatedOffset - b.generatedOffset;
381
- // });
382
-
383
- return {
384
- allDecodedMappings,
385
- originalIndexMap
386
- };
387
-
388
- };
389
-
390
389
  const unpackSourceMap = async (item, state, options) => {
391
390
  const sourceMap = item.sourceMap;
392
391
  const generatedPositionMapping = state.positionMapping;
@@ -28,6 +28,11 @@ const findOffsetMapping = (generatedState, offset) => {
28
28
 
29
29
  const decodedMappings = generatedState.decodedMappings;
30
30
 
31
+ // possible no length
32
+ if (!decodedMappings.length) {
33
+ return;
34
+ }
35
+
31
36
  const mapping = findMapping(decodedMappings, offset);
32
37
 
33
38
  const generatedOffset = mapping.generatedOffset;