@teamscale/javascript-instrumenter 0.0.1-beta.10 → 0.0.1-beta.21

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/CHANGELOG.md ADDED
@@ -0,0 +1,11 @@
1
+ We use [Semantic Versioning](https://semver.org/).
2
+
3
+ # New Release
4
+
5
+ # 0.0.1-beta.21
6
+
7
+ - [fix] Include/exclude pattern and the paths to match were not normalized
8
+
9
+ # 0.0.1-beta.20
10
+
11
+ - [feature] Automatic release now for NPM packages and Docker images
package/README.md CHANGED
@@ -9,7 +9,7 @@ in the Teamscale Simple Coverage Format and sent to a Teamscale instance.
9
9
  The Teamscale JavaScript Profiler consists of the [Coverage Collector](https://www.npmjs.com/package/@teamscale/coverage-collector)
10
10
  and this JavaScript Instrumenter.
11
11
  More details on using them (in combination) can be found
12
- on the projects' [Github page](https://github.com/cqse/teamscale-javascript-profiler/).
12
+ in the [Teamscale Documentation](https://docs.teamscale.com/howto/recording-test-coverage-for-javascript/).
13
13
 
14
14
  The Instrumenter instruments a given (set of) JavaScript file(s) such that (1) coverage
15
15
  information is produced and (2) forwarded to the Collector.
@@ -25,28 +25,6 @@ yarn install
25
25
  yarn build
26
26
  ```
27
27
 
28
- ### Preparation: Source Maps
29
-
30
- Please make sure to enable the generation of source map files to ensure
31
- that the profiled code can be mapped back to the original.
32
-
33
- For example, when the tool Vite is used to bundle the code,
34
- the generation of source map information can be enabled by setting:
35
-
36
- ```
37
- build: {
38
- sourcemap: true
39
- }
40
- ```
41
-
42
- or
43
-
44
- ```
45
- build: {
46
- sourcemap: `inline`
47
- }
48
- ```
49
-
50
28
  ## Workflow Integration
51
29
 
52
30
  There are several options to run the Instrumenter. For example, via `yarn` by running
@@ -85,12 +63,8 @@ yarn instrumenter --inplace ./the/path/to/the/file.js --source-map ./the/path/to
85
63
  yarn instrumenter ./the/path/to/the/file.js --to ./the/file/path/to/write/to.js
86
64
  ```
87
65
 
88
- ### Integration with Testing Frameworks
89
-
90
- This is planned work: Provide a Babel plugin that provides a code transformation
91
- such that coverage information is collected and this information is forwarded.
92
-
93
66
  ## Limitations
94
67
 
95
68
  This tool inherits most of the limitations of IstanbulJs, including
96
69
  a considerable performance impact.
70
+
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@teamscale/javascript-instrumenter",
3
- "version": "0.0.1-beta.10",
3
+ "version": "0.0.1-beta.21",
4
4
  "description": "Istanbul-based coverage instrumenter with coverage forwarding via WebSockets",
5
5
  "main": "dist/src/main.js",
6
6
  "bin": "dist/src/main.js",
@@ -63,11 +63,11 @@ class IstanbulInstrumenter {
63
63
  if (!taskElement.isInPlace()) {
64
64
  fs.writeFileSync(taskElement.toFile, inputFileSource);
65
65
  }
66
- return new Task_1.TaskResult(0, 0, 1, 0, 0, 0);
66
+ return new Task_1.TaskResult(0, 0, 0, 1, 0, 0, 0);
67
67
  }
68
68
  // Not all file types are supported by the instrumenter
69
69
  if (!this.isFileTypeSupported(taskElement.fromFile)) {
70
- return new Task_1.TaskResult(0, 0, 0, 1, 0, 0);
70
+ return new Task_1.TaskResult(0, 0, 0, 0, 1, 0, 0);
71
71
  }
72
72
  // Report progress
73
73
  this.logger.info(`Instrumenting "${path.basename(taskElement.fromFile)}"`);
@@ -87,7 +87,7 @@ class IstanbulInstrumenter {
87
87
  //
88
88
  if (this.shouldExcludeFromInstrumentation(sourcePattern, taskElement.fromFile, (_a = inputSourceMap === null || inputSourceMap === void 0 ? void 0 : inputSourceMap.sources) !== null && _a !== void 0 ? _a : [])) {
89
89
  fs.writeFileSync(taskElement.toFile, inputFileSource);
90
- return new Task_1.TaskResult(1, 0, 0, 0, 0, 0);
90
+ return new Task_1.TaskResult(0, 1, 0, 0, 0, 0, 0);
91
91
  }
92
92
  // The main instrumentation (adding coverage statements) is performed now:
93
93
  instrumentedSource = instrumenter
@@ -117,7 +117,7 @@ class IstanbulInstrumenter {
117
117
  //
118
118
  const vaccineSource = this.loadVaccine(collector);
119
119
  fs.writeFileSync(taskElement.toFile, `${exports.IS_INSTRUMENTED_TOKEN} ${vaccineSource} ${instrumentedSource} \n${finalSourceMap}`);
120
- return new Task_1.TaskResult(1, 0, 0, 0, 0, 0);
120
+ return new Task_1.TaskResult(1, 0, 0, 0, 0, 0, 0);
121
121
  }
122
122
  /**
123
123
  * Loads the vaccine from the vaccine file and adjusts some template parameters.
@@ -51,12 +51,19 @@ export declare class OriginSourcePattern {
51
51
  /**
52
52
  * Does the given pattern require to include the given set of files?
53
53
  *
54
+ * For example, a JavaScript bundle is compiled from several (origin) source files.
55
+ * If one of the files in the bundle is needed, then the full bundle is needed, that is,
56
+ * this function is required to return `true`.
57
+ *
54
58
  * @param originFiles - The file set to decide for include or exclude.
55
59
  *
56
- * @returns `true` if (1) all of the given files are supposed to be excluded,
57
- * or (2) if one of the files is supposed to be included.
60
+ * @returns `false` if (1) all given files are supposed to be excluded,
61
+ * or (2) `true` if at least one of the files is supposed to be included.
58
62
  */
59
63
  isAnyIncluded(originFiles: string[]): boolean;
64
+ private static normalizeGlobPattern;
65
+ private static normalizePath;
66
+ private static removeTrailingCurrentWorkingDir;
60
67
  }
61
68
  /**
62
69
  * The actual instrumentation task.
@@ -87,6 +94,8 @@ export declare class InstrumentationTask {
87
94
  export declare class TaskResult {
88
95
  /** Number of task elements that were performed (instrumented) */
89
96
  readonly translated: number;
97
+ /** Number of task elements that were excluded because of corresponding include/exclude patterns. */
98
+ readonly excluded: number;
90
99
  /** Number of instrumentations that were taken from a cache */
91
100
  readonly translatedFromCache: number;
92
101
  /** Number of skips due to a present instrumentation */
@@ -97,7 +106,7 @@ export declare class TaskResult {
97
106
  readonly failed: number;
98
107
  /** Number of warnings that were produced during the instrumentation process */
99
108
  readonly warnings: number;
100
- constructor(translated: number, translatedFromCache: number, alreadyInstrumented: number, unsupported: number, failed: number, warnings: number);
109
+ constructor(translated: number, excluded: number, translatedFromCache: number, alreadyInstrumented: number, unsupported: number, failed: number, warnings: number);
101
110
  /**
102
111
  * Returns the sum of the present task results and the given one.
103
112
  *
@@ -1 +1 @@
1
- {"version":3,"file":"Task.d.ts","sourceRoot":"","sources":["../../../src/instrumenter/Task.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAI/C;;GAEG;AACH,8BAAsB,kBAAkB;CAAG;AAE3C;;;GAGG;AACH,qBAAa,WAAW;IACvB,sBAAsB;IACtB,SAAgB,QAAQ,EAAE,MAAM,CAAC;IAEjC,2BAA2B;IAC3B,SAAgB,MAAM,EAAE,MAAM,CAAC;IAE/B,gEAAgE;IAChE,SAAgB,qBAAqB,EAAE,QAAQ,CAAC,kBAAkB,CAAC,CAAC;gBAExD,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,iBAAiB,CAAC,EAAE,kBAAkB;IAMpF;;OAEG;IACI,SAAS,IAAI,OAAO;CAK3B;AAED;;;GAGG;AACH,qBAAa,kBAAkB;IAC9B,2CAA2C;IAC3C,SAAgB,IAAI,EAAE,MAAM,CAAC;IAE7B,gDAAgD;IAChD,SAAgB,IAAI,EAAE,MAAM,CAAC;gBAEjB,SAAS,EAAE,MAAM;CAK7B;AAED;;;;;;GAMG;AACH,qBAAa,mBAAmB;IAC/B,mGAAmG;IACnG,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqB;IAE7C;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqB;gBAEjC,OAAO,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS;IAKpE;;;;;;;OAOG;IACI,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,OAAO;CAepD;AAED;;GAEG;AACH,qBAAa,mBAAmB;IAC/B;;OAEG;IACH,SAAgB,SAAS,EAAE,kBAAkB,CAAC;IAE9C;;OAEG;IACH,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAgB;IAE1C;;;OAGG;IACH,SAAgB,mBAAmB,EAAE,mBAAmB,CAAC;gBAE7C,SAAS,EAAE,kBAAkB,EAAE,QAAQ,EAAE,WAAW,EAAE,EAAE,mBAAmB,EAAE,mBAAmB;IAM5G;;OAEG;IACH,IAAI,QAAQ,IAAI,WAAW,EAAE,CAI5B;CACD;AAED;;GAEG;AACH,qBAAa,UAAU;IACtB,iEAAiE;IACjE,SAAgB,UAAU,EAAE,MAAM,CAAC;IAEnC,8DAA8D;IAC9D,SAAgB,mBAAmB,EAAE,MAAM,CAAC;IAE5C,uDAAuD;IACvD,SAAgB,mBAAmB,EAAE,MAAM,CAAC;IAE5C,sDAAsD;IACtD,SAAgB,WAAW,EAAE,MAAM,CAAC;IAEpC,6DAA6D;IAC7D,SAAgB,MAAM,EAAE,MAAM,CAAC;IAE/B,+EAA+E;IAC/E,SAAgB,QAAQ,EAAE,MAAM,CAAC;gBAGhC,UAAU,EAAE,MAAM,EAClB,mBAAmB,EAAE,MAAM,EAC3B,mBAAmB,EAAE,MAAM,EAC3B,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM;IAgBjB;;;;OAIG;IACI,aAAa,CAAC,KAAK,EAAE,UAAU,GAAG,UAAU;IAWnD;;OAEG;WACW,OAAO,IAAI,UAAU;IAInC;;;;OAIG;WACW,KAAK,CAAC,CAAC,EAAE,KAAK,GAAG,UAAU;IAKzC;;;;OAIG;WACW,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU;CAI9C;AAED;;GAEG;AACH,qBAAa,sBAAuB,SAAQ,kBAAkB;IAC7D,2CAA2C;IAC3C,SAAgB,iBAAiB,EAAE,MAAM,CAAC;gBAE9B,iBAAiB,EAAE,MAAM;CAIrC"}
1
+ {"version":3,"file":"Task.d.ts","sourceRoot":"","sources":["../../../src/instrumenter/Task.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAK/C;;GAEG;AACH,8BAAsB,kBAAkB;CAAG;AAE3C;;;GAGG;AACH,qBAAa,WAAW;IACvB,sBAAsB;IACtB,SAAgB,QAAQ,EAAE,MAAM,CAAC;IAEjC,2BAA2B;IAC3B,SAAgB,MAAM,EAAE,MAAM,CAAC;IAE/B,gEAAgE;IAChE,SAAgB,qBAAqB,EAAE,QAAQ,CAAC,kBAAkB,CAAC,CAAC;gBAExD,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,iBAAiB,CAAC,EAAE,kBAAkB;IAMpF;;OAEG;IACI,SAAS,IAAI,OAAO;CAK3B;AAED;;;GAGG;AACH,qBAAa,kBAAkB;IAC9B,2CAA2C;IAC3C,SAAgB,IAAI,EAAE,MAAM,CAAC;IAE7B,gDAAgD;IAChD,SAAgB,IAAI,EAAE,MAAM,CAAC;gBAEjB,SAAS,EAAE,MAAM;CAK7B;AAED;;;;;;GAMG;AACH,qBAAa,mBAAmB;IAC/B,mGAAmG;IACnG,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqB;IAE7C;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqB;gBAEjC,OAAO,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS;IAKpE;;;;;;;;;;;OAWG;IACI,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,OAAO;IAiBpD,OAAO,CAAC,MAAM,CAAC,oBAAoB;IAQnC,OAAO,CAAC,MAAM,CAAC,aAAa;IAI5B,OAAO,CAAC,MAAM,CAAC,+BAA+B;CAO9C;AAED;;GAEG;AACH,qBAAa,mBAAmB;IAC/B;;OAEG;IACH,SAAgB,SAAS,EAAE,kBAAkB,CAAC;IAE9C;;OAEG;IACH,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAgB;IAE1C;;;OAGG;IACH,SAAgB,mBAAmB,EAAE,mBAAmB,CAAC;gBAE7C,SAAS,EAAE,kBAAkB,EAAE,QAAQ,EAAE,WAAW,EAAE,EAAE,mBAAmB,EAAE,mBAAmB;IAM5G;;OAEG;IACH,IAAI,QAAQ,IAAI,WAAW,EAAE,CAI5B;CACD;AAED;;GAEG;AACH,qBAAa,UAAU;IACtB,iEAAiE;IACjE,SAAgB,UAAU,EAAE,MAAM,CAAC;IAEnC,oGAAoG;IACpG,SAAgB,QAAQ,EAAE,MAAM,CAAC;IAEjC,8DAA8D;IAC9D,SAAgB,mBAAmB,EAAE,MAAM,CAAC;IAE5C,uDAAuD;IACvD,SAAgB,mBAAmB,EAAE,MAAM,CAAC;IAE5C,sDAAsD;IACtD,SAAgB,WAAW,EAAE,MAAM,CAAC;IAEpC,6DAA6D;IAC7D,SAAgB,MAAM,EAAE,MAAM,CAAC;IAE/B,+EAA+E;IAC/E,SAAgB,QAAQ,EAAE,MAAM,CAAC;gBAGhC,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,mBAAmB,EAAE,MAAM,EAC3B,mBAAmB,EAAE,MAAM,EAC3B,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM;IAkBjB;;;;OAIG;IACI,aAAa,CAAC,KAAK,EAAE,UAAU,GAAG,UAAU;IAYnD;;OAEG;WACW,OAAO,IAAI,UAAU;IAInC;;;;OAIG;WACW,KAAK,CAAC,CAAC,EAAE,KAAK,GAAG,UAAU;IAKzC;;;;OAIG;WACW,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU;CAI9C;AAED;;GAEG;AACH,qBAAa,sBAAuB,SAAQ,kBAAkB;IAC7D,2CAA2C;IAC3C,SAAgB,iBAAiB,EAAE,MAAM,CAAC;gBAE9B,iBAAiB,EAAE,MAAM;CAIrC"}
@@ -18,11 +18,15 @@ var __importStar = (this && this.__importStar) || function (mod) {
18
18
  __setModuleDefault(result, mod);
19
19
  return result;
20
20
  };
21
+ var __importDefault = (this && this.__importDefault) || function (mod) {
22
+ return (mod && mod.__esModule) ? mod : { "default": mod };
23
+ };
21
24
  Object.defineProperty(exports, "__esModule", { value: true });
22
25
  exports.SourceMapFileReference = exports.TaskResult = exports.InstrumentationTask = exports.OriginSourcePattern = exports.CollectorSpecifier = exports.TaskElement = exports.SourceMapReference = void 0;
23
26
  const typescript_optional_1 = require("typescript-optional");
24
27
  const commons_1 = require("@cqse/commons");
25
28
  const matching = __importStar(require("micromatch"));
29
+ const path_1 = __importDefault(require("path"));
26
30
  /**
27
31
  * An abstract source map type.
28
32
  */
@@ -70,31 +74,52 @@ exports.CollectorSpecifier = CollectorSpecifier;
70
74
  */
71
75
  class OriginSourcePattern {
72
76
  constructor(include, exclude) {
73
- this.include = include;
74
- this.exclude = exclude;
77
+ this.include = OriginSourcePattern.normalizeGlobPattern(include);
78
+ this.exclude = OriginSourcePattern.normalizeGlobPattern(exclude);
75
79
  }
76
80
  /**
77
81
  * Does the given pattern require to include the given set of files?
78
82
  *
83
+ * For example, a JavaScript bundle is compiled from several (origin) source files.
84
+ * If one of the files in the bundle is needed, then the full bundle is needed, that is,
85
+ * this function is required to return `true`.
86
+ *
79
87
  * @param originFiles - The file set to decide for include or exclude.
80
88
  *
81
- * @returns `true` if (1) all of the given files are supposed to be excluded,
82
- * or (2) if one of the files is supposed to be included.
89
+ * @returns `false` if (1) all given files are supposed to be excluded,
90
+ * or (2) `true` if at least one of the files is supposed to be included.
83
91
  */
84
92
  isAnyIncluded(originFiles) {
85
93
  var _a;
94
+ const normalizedOriginFiles = originFiles.map(OriginSourcePattern.normalizePath);
86
95
  if (this.exclude) {
87
- const matchedToExclude = matching.match(originFiles, this.exclude);
96
+ const matchedToExclude = matching.match(normalizedOriginFiles, this.exclude);
88
97
  if (originFiles.length === matchedToExclude.length) {
89
98
  return false;
90
99
  }
91
100
  }
92
101
  if (this.include) {
93
- const matchedToInclude = matching.match(originFiles, (_a = this.include) !== null && _a !== void 0 ? _a : '**');
102
+ const matchedToInclude = matching.match(normalizedOriginFiles, (_a = this.include) !== null && _a !== void 0 ? _a : '**');
94
103
  return matchedToInclude.length > 0;
95
104
  }
96
105
  return true;
97
106
  }
107
+ static normalizeGlobPattern(pattern) {
108
+ if (!pattern) {
109
+ return pattern;
110
+ }
111
+ return OriginSourcePattern.removeTrailingCurrentWorkingDir(pattern);
112
+ }
113
+ static normalizePath(toNormalize) {
114
+ return OriginSourcePattern.removeTrailingCurrentWorkingDir(toNormalize);
115
+ }
116
+ static removeTrailingCurrentWorkingDir(removeFrom) {
117
+ const prefixToRemove = '.' + path_1.default.sep;
118
+ if (removeFrom.startsWith(prefixToRemove)) {
119
+ return removeFrom.substring(2);
120
+ }
121
+ return removeFrom;
122
+ }
98
123
  }
99
124
  exports.OriginSourcePattern = OriginSourcePattern;
100
125
  /**
@@ -120,14 +145,16 @@ exports.InstrumentationTask = InstrumentationTask;
120
145
  * A summary of executing the instrumentation task.
121
146
  */
122
147
  class TaskResult {
123
- constructor(translated, translatedFromCache, alreadyInstrumented, unsupported, failed, warnings) {
148
+ constructor(translated, excluded, translatedFromCache, alreadyInstrumented, unsupported, failed, warnings) {
124
149
  commons_1.Contract.require(translated > -1);
150
+ commons_1.Contract.require(excluded > -1);
125
151
  commons_1.Contract.require(translatedFromCache > -1);
126
152
  commons_1.Contract.require(alreadyInstrumented > -1);
127
153
  commons_1.Contract.require(unsupported > -1);
128
154
  commons_1.Contract.require(failed > -1);
129
155
  commons_1.Contract.require(warnings > -1);
130
156
  this.translated = translated;
157
+ this.excluded = excluded;
131
158
  this.translatedFromCache = translatedFromCache;
132
159
  this.alreadyInstrumented = alreadyInstrumented;
133
160
  this.unsupported = unsupported;
@@ -140,13 +167,13 @@ class TaskResult {
140
167
  * @param incBy - The task result to add (as delta).
141
168
  */
142
169
  withIncrement(incBy) {
143
- return new TaskResult(this.translated + incBy.translated, this.translatedFromCache + incBy.translatedFromCache, this.alreadyInstrumented + incBy.alreadyInstrumented, this.unsupported + incBy.unsupported, this.failed + incBy.failed, this.warnings + incBy.warnings);
170
+ return new TaskResult(this.translated + incBy.translated, this.excluded + incBy.excluded, this.translatedFromCache + incBy.translatedFromCache, this.alreadyInstrumented + incBy.alreadyInstrumented, this.unsupported + incBy.unsupported, this.failed + incBy.failed, this.warnings + incBy.warnings);
144
171
  }
145
172
  /**
146
173
  * @returns the neutral task element (adding it with {@code withIncrement} does not change the result).
147
174
  */
148
175
  static neutral() {
149
- return new TaskResult(0, 0, 0, 0, 0, 0);
176
+ return new TaskResult(0, 0, 0, 0, 0, 0, 0);
150
177
  }
151
178
  /**
152
179
  * @returns a task result signaling one error.
@@ -155,7 +182,7 @@ class TaskResult {
155
182
  */
156
183
  static error(e) {
157
184
  console.error(e);
158
- return new TaskResult(0, 0, 0, 0, 1, 0);
185
+ return new TaskResult(0, 0, 0, 0, 0, 1, 0);
159
186
  }
160
187
  /**
161
188
  * @returns a task result signaling one warning.
@@ -164,7 +191,7 @@ class TaskResult {
164
191
  */
165
192
  static warning(msg) {
166
193
  console.warn(msg);
167
- return new TaskResult(0, 0, 0, 0, 0, 1);
194
+ return new TaskResult(0, 0, 0, 0, 0, 0, 1);
168
195
  }
169
196
  }
170
197
  exports.TaskResult = TaskResult;
package/dist/src/main.js CHANGED
@@ -7,6 +7,7 @@ App_1.App.run()
7
7
  .then(result => {
8
8
  console.log('Instrumentation finished.');
9
9
  console.log(`\tInstrumented: ${result.translated}`);
10
+ console.log(`\tExcluded: ${result.excluded}`);
10
11
  console.log(`\tInstrumented from cache: ${result.translatedFromCache}`);
11
12
  console.log(`\tAlready instrumented: ${result.alreadyInstrumented}`);
12
13
  console.log(`\tUnsupported: ${result.unsupported}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@teamscale/javascript-instrumenter",
3
- "version": "0.0.1-beta.10",
3
+ "version": "0.0.1-beta.21",
4
4
  "description": "Istanbul-based coverage instrumenter with coverage forwarding via WebSockets",
5
5
  "main": "dist/src/main.js",
6
6
  "bin": "dist/src/main.js",