@shopgate/webpack 7.32.2-alpha.6 → 7.32.2-alpha.7

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/locales/en.json CHANGED
@@ -25,14 +25,6 @@
25
25
  "INVALID": "... invalid:",
26
26
  "VALID": "... theme configuration is valid"
27
27
  },
28
- "plugins/ShopgateTypeCheckPlugin": {
29
- "CHECKING": "Type checking {name} ...",
30
- "ERRORS": "Type errors: {count}",
31
- "NO_ERRORS": "No type errors",
32
- "NO_TYPESCRIPT": "Type check skipped for {name}: TypeScript is not installed there",
33
- "FAILED": "Type check of {name} could not be started: {message}",
34
- "STOPPED": "Type check of {name} stopped unexpectedly ({reason}). Restart the frontend to check it again. Its last output:"
35
- },
36
28
  "webpack.config": {
37
29
  "WEBPACK_PROGRESS": "building [{bar}] [{message}] {percent} ({elapsed} seconds)"
38
30
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shopgate/webpack",
3
- "version": "7.32.2-alpha.6",
3
+ "version": "7.32.2-alpha.7",
4
4
  "description": "The webpack configuration for Shopgate's Engage.",
5
5
  "main": "webpack.config.js",
6
6
  "license": "Apache-2.0",
package/webpack.config.js CHANGED
@@ -13,7 +13,6 @@ const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin'
13
13
  const rxPaths = require('rxjs/_esm5/path-mapping');
14
14
  const ShopgateIndexerPlugin = require('./plugins/ShopgateIndexerPlugin');
15
15
  const ShopgateThemeConfigValidatorPlugin = require('./plugins/ShopgateThemeConfigValidatorPlugin');
16
- const ShopgateTypeCheckPlugin = require('./plugins/ShopgateTypeCheckPlugin');
17
16
  const { ENV, isDev, PUBLIC_FOLDER } = require('./lib/variables');
18
17
  const getAppSettings = require('./lib/getAppSettings');
19
18
  const convertLanguageToISO = require('./lib/convertLanguageToISO');
@@ -36,10 +35,6 @@ const t = i18n(__filename);
36
35
  const devtool = isDev ? sourceMap : (process.env.SOURCE_MAPS || false);
37
36
  const fileSuffix = devtool ? '.sm' : '';
38
37
  const addBundleAnalyzer = !!process.env.BUNDLE_ANALYZER;
39
- const typeCheck = ['0', 'false'].includes(process.env.TYPE_CHECK) ? '' : process.env.TYPE_CHECK;
40
- const typeCheckPlugin = isDev && typeCheck
41
- ? new ShopgateTypeCheckPlugin({ overlay: typeCheck === 'overlay' })
42
- : null;
43
38
 
44
39
  /**
45
40
  * @type {import('webpack').Configuration}
@@ -218,7 +213,6 @@ const config = {
218
213
  ...(isDev ? [new ReactRefreshWebpackPlugin({
219
214
  overlay: false,
220
215
  })] : []),
221
- ...(typeCheckPlugin ? [typeCheckPlugin] : []),
222
216
  ...(!isDev ? [
223
217
  new CompressionWebpackPlugin({
224
218
  filename: '[path][base].gz[query]',
@@ -312,15 +306,9 @@ const config = {
312
306
  directory: path.resolve(themePath, PUBLIC_FOLDER),
313
307
  },
314
308
  client: {
315
- overlay: typeCheckPlugin && typeCheckPlugin.overlay ? {
316
- errors: true,
317
- warnings: false,
318
- runtimeErrors: false,
319
- } : false,
309
+ // Deactivate full-screen error overlay in dev server
310
+ overlay: false,
320
311
  },
321
- ...(typeCheckPlugin ? {
322
- onListening: devServer => typeCheckPlugin.setDevServer(devServer),
323
- } : {}),
324
312
  host: '0.0.0.0',
325
313
  port: process.env.optionsPort,
326
314
  historyApiFallback: true,
@@ -1,67 +0,0 @@
1
- const ERROR_IN_FILE = /^(.+?)\((\d+),(\d+)\): error (TS\d+): (.*)$/;
2
- const ERROR_WITHOUT_FILE = /^error (TS\d+): (.*)$/;
3
- const CHECK_STARTED = /Starting (incremental )?compilation/;
4
- const CHECK_FINISHED = /Found \d+ errors?\. Watching for file changes/;
5
-
6
- /**
7
- * @typedef {Object} TypeCheckError
8
- * @property {string|null} file The file as the compiler printed it, relative to the project.
9
- * @property {number|null} line The line of the error.
10
- * @property {number|null} column The column of the error.
11
- * @property {string} code The error code, e.g. "TS2322".
12
- * @property {string} message The error message.
13
- */
14
-
15
- /**
16
- * @typedef {Object} TypeCheckEvent
17
- * @property {'started'|'finished'} type Whether a check started or finished.
18
- * @property {TypeCheckError[]} [errors] The errors of a finished check.
19
- */
20
-
21
- /**
22
- * Creates a parser for the output of "tsc --watch --pretty false". It takes the output line by
23
- * line and returns an event when a check starts or finishes.
24
- * @return {function(string): TypeCheckEvent|null}
25
- */
26
- module.exports = function createTypeCheckParser() {
27
- let errors = [];
28
-
29
- return (line) => {
30
- if (CHECK_STARTED.test(line)) {
31
- errors = [];
32
- return { type: 'started' };
33
- }
34
-
35
- if (CHECK_FINISHED.test(line)) {
36
- return {
37
- type: 'finished',
38
- errors,
39
- };
40
- }
41
-
42
- const inFile = line.match(ERROR_IN_FILE);
43
- const withoutFile = line.match(ERROR_WITHOUT_FILE);
44
-
45
- if (inFile) {
46
- errors.push({
47
- file: inFile[1],
48
- line: Number(inFile[2]),
49
- column: Number(inFile[3]),
50
- code: inFile[4],
51
- message: inFile[5],
52
- });
53
- } else if (withoutFile) {
54
- errors.push({
55
- file: null,
56
- line: null,
57
- column: null,
58
- code: withoutFile[1],
59
- message: withoutFile[2],
60
- });
61
- } else if (/^\s+\S/.test(line) && errors.length > 0) {
62
- errors[errors.length - 1].message += `\n${line}`;
63
- }
64
-
65
- return null;
66
- };
67
- };
@@ -1,76 +0,0 @@
1
- const createTypeCheckParser = require('./createTypeCheckParser');
2
-
3
- /**
4
- * Feeds lines to a new parser and returns the events it emits.
5
- * @param {string[]} lines The compiler output.
6
- * @return {Object[]}
7
- */
8
- const parseLines = (lines) => {
9
- const parse = createTypeCheckParser();
10
-
11
- return lines.map(line => parse(line)).filter(Boolean);
12
- };
13
-
14
- describe('createTypeCheckParser', () => {
15
- it('reports the start and the errors of a check', () => {
16
- expect(parseLines([
17
- '2:36:55 PM - Starting compilation in watch mode...',
18
- '',
19
- "portals/Banner/index.tsx(33,68): error TS2322: Type 'false' is not assignable to type 'true'.",
20
- 'error TS6053: File not found.',
21
- '',
22
- '2:36:58 PM - Found 2 errors. Watching for file changes.',
23
- ])).toEqual([
24
- { type: 'started' },
25
- {
26
- type: 'finished',
27
- errors: [
28
- {
29
- file: 'portals/Banner/index.tsx',
30
- line: 33,
31
- column: 68,
32
- code: 'TS2322',
33
- message: "Type 'false' is not assignable to type 'true'.",
34
- },
35
- {
36
- file: null,
37
- line: null,
38
- column: null,
39
- code: 'TS6053',
40
- message: 'File not found.',
41
- },
42
- ],
43
- },
44
- ]);
45
- });
46
-
47
- it('adds indented lines to the message of the error before', () => {
48
- const [, finished] = parseLines([
49
- '02:36:48 PM - Starting compilation in watch mode...',
50
- "a.ts(1,14): error TS2345: Argument of type 'A' is not assignable to parameter of type 'B'.",
51
- " Property 'id' is missing in type 'A'.",
52
- '02:36:49 PM - Found 1 error. Watching for file changes.',
53
- ]);
54
-
55
- expect(finished.errors).toHaveLength(1);
56
- expect(finished.errors[0].message).toBe([
57
- "Argument of type 'A' is not assignable to parameter of type 'B'.",
58
- " Property 'id' is missing in type 'A'.",
59
- ].join('\n'));
60
- });
61
-
62
- it('forgets the errors of the check before when a new one starts', () => {
63
- const events = parseLines([
64
- '2:36:55 PM - Starting compilation in watch mode...',
65
- "a.ts(1,14): error TS2322: Type 'string' is not assignable to type 'number'.",
66
- '2:36:58 PM - Found 1 error. Watching for file changes.',
67
- '2:37:10 PM - File change detected. Starting incremental compilation...',
68
- '2:37:11 PM - Found 0 errors. Watching for file changes.',
69
- ]);
70
-
71
- expect(events[3]).toEqual({
72
- type: 'finished',
73
- errors: [],
74
- });
75
- });
76
- });
@@ -1,55 +0,0 @@
1
- const fs = require('fs');
2
- const path = require('path');
3
-
4
- /**
5
- * @typedef {Object} TypeCheckProject
6
- * @property {string} name The name that is shown in front of the output of the project.
7
- * @property {string} path The folder that contains the tsconfig.json of the project.
8
- * @property {boolean} isTheme Whether the project is the theme.
9
- * @property {string|null} tsc The TypeScript compiler of the project, when it has one installed.
10
- */
11
-
12
- /**
13
- * Resolves the TypeScript compiler that a project has installed.
14
- * @param {string} projectPath The folder of the project.
15
- * @return {string|null}
16
- */
17
- function resolveCompiler(projectPath) {
18
- try {
19
- const packagePath = require.resolve('typescript/package.json', { paths: [projectPath] });
20
- // eslint-disable-next-line global-require, import/no-dynamic-require
21
- const { bin } = require(packagePath);
22
-
23
- return path.resolve(path.dirname(packagePath), bin.tsc);
24
- } catch (error) {
25
- return null;
26
- }
27
- }
28
-
29
- /**
30
- * Returns the theme and the frontends of the attached extensions that have a tsconfig.json.
31
- * @param {string} themePath The folder of the theme.
32
- * @param {Object} [extensions={}] The attached extensions.
33
- * @return {TypeCheckProject[]}
34
- */
35
- module.exports = function getTypeCheckProjects(themePath, extensions = {}) {
36
- const extensionsPath = path.resolve(themePath, '..', '..', 'extensions');
37
-
38
- return [
39
- {
40
- name: path.basename(themePath),
41
- path: themePath,
42
- isTheme: true,
43
- },
44
- ...Object.keys(extensions).map(id => ({
45
- name: id,
46
- path: path.resolve(extensionsPath, extensions[id].path, 'frontend'),
47
- isTheme: false,
48
- })),
49
- ]
50
- .filter(project => fs.existsSync(path.join(project.path, 'tsconfig.json')))
51
- .map(project => ({
52
- ...project,
53
- tsc: resolveCompiler(project.path),
54
- }));
55
- };
@@ -1,83 +0,0 @@
1
- const fs = require('fs');
2
- const os = require('os');
3
- const path = require('path');
4
- const getTypeCheckProjects = require('./getTypeCheckProjects');
5
-
6
- describe('getTypeCheckProjects', () => {
7
- let root;
8
- let themePath;
9
-
10
- const write = (file, content = '{}') => {
11
- const target = path.join(root, file);
12
- fs.mkdirSync(path.dirname(target), { recursive: true });
13
- fs.writeFileSync(target, content);
14
- };
15
-
16
- beforeEach(() => {
17
- root = fs.realpathSync(fs.mkdtempSync(path.join(os.tmpdir(), 'type-check-')));
18
- themePath = path.join(root, 'themes', 'theme-test');
19
- fs.mkdirSync(themePath, { recursive: true });
20
- });
21
-
22
- afterEach(() => {
23
- fs.rmSync(root, {
24
- recursive: true,
25
- force: true,
26
- });
27
- });
28
-
29
- it('returns the theme and the attached extensions that have a tsconfig', () => {
30
- write('themes/theme-test/tsconfig.json');
31
- write('extensions/typed/frontend/tsconfig.json');
32
- write('extensions/untyped/frontend/index.js', '');
33
- write('extensions/detached/frontend/tsconfig.json');
34
-
35
- const projects = getTypeCheckProjects(themePath, {
36
- '@acme/typed': { path: 'typed' },
37
- '@acme/untyped': { path: 'untyped' },
38
- });
39
-
40
- expect(projects.map(({ name, path: projectPath, isTheme }) => ({
41
- name,
42
- path: projectPath,
43
- isTheme,
44
- }))).toEqual([
45
- {
46
- name: 'theme-test',
47
- path: themePath,
48
- isTheme: true,
49
- },
50
- {
51
- name: '@acme/typed',
52
- path: path.join(root, 'extensions', 'typed', 'frontend'),
53
- isTheme: false,
54
- },
55
- ]);
56
- });
57
-
58
- it('leaves out a theme without a tsconfig', () => {
59
- expect(getTypeCheckProjects(themePath)).toEqual([]);
60
- });
61
-
62
- it('resolves the compiler that the project has installed', () => {
63
- write('extensions/typed/frontend/tsconfig.json');
64
- write(
65
- 'extensions/typed/frontend/node_modules/typescript/package.json',
66
- JSON.stringify({ bin: { tsc: './bin/tsc' } })
67
- );
68
-
69
- const [project] = getTypeCheckProjects(themePath, { '@acme/typed': { path: 'typed' } });
70
-
71
- expect(project.tsc).toBe(path.join(
72
- root, 'extensions', 'typed', 'frontend', 'node_modules', 'typescript', 'bin', 'tsc'
73
- ));
74
- });
75
-
76
- it('reports no compiler when the project has none installed', () => {
77
- write('extensions/typed/frontend/tsconfig.json');
78
-
79
- const [project] = getTypeCheckProjects(themePath, { '@acme/typed': { path: 'typed' } });
80
-
81
- expect(project.tsc).toBeNull();
82
- });
83
- });
@@ -1,48 +0,0 @@
1
- const { spawn, spawnSync } = require('child_process');
2
-
3
- const isWindows = process.platform === 'win32';
4
- const STOP_SIGNALS = ['SIGINT', 'SIGTERM', 'SIGHUP'];
5
-
6
- const child = spawn(process.execPath, process.argv.slice(2), {
7
- stdio: ['ignore', 'inherit', 'inherit'],
8
- detached: !isWindows,
9
- windowsHide: true,
10
- });
11
-
12
- /**
13
- * Stops the compiler together with every process it started, then exits without an error.
14
- */
15
- function stop() {
16
- try {
17
- if (isWindows) {
18
- const { error, status } = spawnSync('taskkill', ['/pid', String(child.pid), '/T', '/F'], {
19
- windowsHide: true,
20
- });
21
-
22
- if (error || status !== 0) {
23
- child.kill();
24
- }
25
- } else {
26
- process.kill(-child.pid, 'SIGTERM');
27
- }
28
- } catch (error) {
29
- child.kill();
30
- }
31
-
32
- process.exit(0);
33
- }
34
-
35
- process.stdin.on('end', stop);
36
- process.stdin.on('error', stop);
37
- process.stdin.resume();
38
- STOP_SIGNALS.forEach(signal => process.on(signal, stop));
39
-
40
- child.on('exit', (code, signal) => {
41
- if (signal) {
42
- process.removeAllListeners(signal);
43
- process.kill(process.pid, signal);
44
- return;
45
- }
46
-
47
- process.exit(code || 1);
48
- });
@@ -1,242 +0,0 @@
1
- const { spawn } = require('child_process');
2
- const fs = require('fs');
3
- const path = require('path');
4
- const readline = require('readline');
5
- const {
6
- blue, cyan, green, grey, red, yellow,
7
- } = require('chalk');
8
- const logger = require('../lib/logger');
9
- const i18n = require('../lib/i18n');
10
- const getTypeCheckProjects = require('../lib/getTypeCheckProjects');
11
- const createTypeCheckParser = require('../lib/createTypeCheckParser');
12
-
13
- const t = i18n(__filename);
14
- const LAST_LINES = 20;
15
- const WATCHER = path.resolve(__dirname, '..', 'lib', 'typeCheckWatcher.js');
16
- const NODE_MODULES = `${path.sep}node_modules${path.sep}`;
17
-
18
- /**
19
- * Reads the attached extensions from the environment.
20
- * @return {Object}
21
- */
22
- function getAttachedExtensions() {
23
- try {
24
- return JSON.parse(process.env.extensions);
25
- } catch (error) {
26
- return {};
27
- }
28
- }
29
-
30
- /**
31
- * Prints the result of a check to the console.
32
- * @param {Object} project The project.
33
- * @param {Object[]} errors The errors of the project.
34
- */
35
- function report(project, errors) {
36
- const prefix = blue(`[${project.name}]`);
37
-
38
- errors.forEach((error) => {
39
- const location = error.file
40
- ? `${cyan(path.relative(process.cwd(), error.file))}:${error.line}:${error.column} - `
41
- : '';
42
-
43
- logger.log(`${prefix} ${location}${red('error')} ${grey(`${error.code}:`)} ${error.message}`);
44
- });
45
-
46
- logger.log(`${prefix} ${errors.length > 0
47
- ? red(t('ERRORS', { count: errors.length }))
48
- : green(t('NO_ERRORS'))}`);
49
- }
50
-
51
- /**
52
- * Type checks the theme and the attached extensions next to a watching build. The errors are
53
- * printed to the console and optionally shown in the overlay of the dev server; they never fail
54
- * the build.
55
- */
56
- class ShopgateTypeCheckPlugin {
57
- /**
58
- * @param {Object} [options={}] The plugin options.
59
- * @param {boolean} [options.overlay=false] Whether the errors are also shown in the browser.
60
- */
61
- constructor({ overlay = false } = {}) {
62
- this.overlay = overlay;
63
- this.started = false;
64
- this.results = new Map();
65
- this.buildErrors = [];
66
- this.devServer = null;
67
- this.overlayShown = false;
68
- }
69
-
70
- /**
71
- * @param {Object} compiler The webpack compiler
72
- */
73
- apply(compiler) {
74
- compiler.hooks.watchRun.tap('ShopgateTypeCheckPlugin', () => {
75
- if (this.started) {
76
- return;
77
- }
78
-
79
- this.started = true;
80
- this.start();
81
- });
82
-
83
- compiler.hooks.done.tap('ShopgateTypeCheckPlugin', (stats) => {
84
- this.buildErrors = stats.toJson({
85
- all: false,
86
- errors: true,
87
- }).errors || [];
88
- setImmediate(() => this.updateOverlay());
89
- });
90
- }
91
-
92
- /**
93
- * Connects the plugin with the dev server, so that it can show the errors in the browser.
94
- * @param {Object} devServer The dev server.
95
- */
96
- setDevServer(devServer) {
97
- if (!this.overlay || !devServer.webSocketServer) {
98
- return;
99
- }
100
-
101
- this.devServer = devServer;
102
- devServer.webSocketServer.implementation.on('connection', (client) => {
103
- setImmediate(() => this.updateOverlay([client]));
104
- });
105
- }
106
-
107
- /**
108
- * Starts a TypeScript compiler in watch mode for every project.
109
- */
110
- start() {
111
- const projects = getTypeCheckProjects(process.cwd(), getAttachedExtensions());
112
-
113
- projects.forEach((project) => {
114
- if (!project.tsc) {
115
- logger.warn(yellow(` ${t('NO_TYPESCRIPT', { name: project.name })}`));
116
- return;
117
- }
118
-
119
- logger.log(blue(` ${t('CHECKING', { name: project.name })}`));
120
- this.watch(project);
121
- });
122
- }
123
-
124
- /**
125
- * Runs the TypeScript compiler of a project in watch mode and collects its errors.
126
- * @param {Object} project The project.
127
- */
128
- watch(project) {
129
- const projectPath = fs.realpathSync(project.path);
130
- const child = spawn(process.execPath, [
131
- WATCHER,
132
- project.tsc,
133
- '--project',
134
- projectPath,
135
- '--noEmit',
136
- '--watch',
137
- '--preserveWatchOutput',
138
- '--pretty',
139
- 'false',
140
- ], {
141
- cwd: projectPath,
142
- stdio: ['pipe', 'pipe', 'pipe'],
143
- });
144
- const parse = createTypeCheckParser();
145
- const lastLines = [];
146
-
147
- [child.stdout, child.stderr].forEach((stream) => {
148
- readline.createInterface({ input: stream }).on('line', (line) => {
149
- if (line.trim()) {
150
- lastLines.push(line);
151
- lastLines.splice(0, lastLines.length - LAST_LINES);
152
- }
153
-
154
- const event = parse(line);
155
-
156
- if (!event) {
157
- return;
158
- }
159
-
160
- if (event.type === 'started') {
161
- this.results.delete(project.name);
162
- return;
163
- }
164
-
165
- const errors = event.errors
166
- .map(error => ({
167
- ...error,
168
- file: error.file && path.resolve(projectPath, error.file),
169
- }))
170
- .filter(error => project.isTheme || !error.file || (
171
- error.file.startsWith(`${projectPath}${path.sep}`)
172
- && !error.file.slice(projectPath.length).includes(NODE_MODULES)
173
- ));
174
-
175
- this.results.set(project.name, errors);
176
- report(project, errors);
177
- this.updateOverlay();
178
- });
179
- });
180
-
181
- child.on('error', (error) => {
182
- logger.warn(yellow(` ${t('FAILED', {
183
- name: project.name,
184
- message: error.message,
185
- })}`));
186
- });
187
-
188
- child.on('exit', (code, signal) => {
189
- if (code === 0) {
190
- return;
191
- }
192
-
193
- logger.warn(yellow(` ${t('STOPPED', {
194
- name: project.name,
195
- reason: signal || code,
196
- })}`));
197
- lastLines.forEach(line => logger.warn(`${blue(`[${project.name}]`)} ${line}`));
198
- this.results.delete(project.name);
199
- this.updateOverlay();
200
- });
201
- }
202
-
203
- /**
204
- * Shows the errors of all finished checks in the overlay of the dev server, together with the
205
- * errors of the build, since the overlay only holds one set of errors. Without type errors the
206
- * overlay is handed back to the dev server.
207
- * @param {Object[]} [clients] The browser connections to update. Defaults to all.
208
- */
209
- updateOverlay(clients) {
210
- if (!this.devServer) {
211
- return;
212
- }
213
-
214
- const receivers = clients || this.devServer.webSocketServer.clients;
215
- const typeErrors = [];
216
-
217
- this.results.forEach((errors, name) => {
218
- errors.forEach((error) => {
219
- typeErrors.push({
220
- moduleName: error.file ? path.relative(process.cwd(), error.file) : name,
221
- loc: error.file ? `${error.line}:${error.column}` : '',
222
- message: `${error.code}: ${error.message}`,
223
- });
224
- });
225
- });
226
-
227
- if (typeErrors.length > 0) {
228
- this.overlayShown = true;
229
- this.devServer.sendMessage(receivers, 'errors', [...this.buildErrors, ...typeErrors]);
230
- } else if (this.overlayShown && !clients) {
231
- this.overlayShown = false;
232
-
233
- if (this.buildErrors.length > 0) {
234
- this.devServer.sendMessage(receivers, 'errors', this.buildErrors);
235
- } else {
236
- this.devServer.sendMessage(receivers, 'still-ok');
237
- }
238
- }
239
- }
240
- }
241
-
242
- module.exports = ShopgateTypeCheckPlugin;
@@ -1,77 +0,0 @@
1
- const ShopgateTypeCheckPlugin = require('./ShopgateTypeCheckPlugin');
2
-
3
- const TYPE_ERROR = {
4
- file: null,
5
- line: null,
6
- column: null,
7
- code: 'TS2322',
8
- message: 'Wrong type.',
9
- };
10
- const BUILD_ERROR = { message: 'Module not found.' };
11
-
12
- describe('ShopgateTypeCheckPlugin', () => {
13
- let plugin;
14
- let devServer;
15
-
16
- beforeEach(() => {
17
- devServer = {
18
- sendMessage: jest.fn(),
19
- webSocketServer: {
20
- clients: ['tab'],
21
- implementation: { on: jest.fn() },
22
- },
23
- };
24
- plugin = new ShopgateTypeCheckPlugin({ overlay: true });
25
- plugin.setDevServer(devServer);
26
- });
27
-
28
- it('sends nothing as long as there are no type errors', () => {
29
- plugin.buildErrors = [BUILD_ERROR];
30
- plugin.updateOverlay();
31
-
32
- expect(devServer.sendMessage).not.toHaveBeenCalled();
33
- });
34
-
35
- it('shows type errors together with the errors of the build', () => {
36
- plugin.buildErrors = [BUILD_ERROR];
37
- plugin.results.set('theme', [TYPE_ERROR]);
38
- plugin.updateOverlay();
39
-
40
- expect(devServer.sendMessage).toHaveBeenCalledWith(['tab'], 'errors', [
41
- BUILD_ERROR,
42
- {
43
- moduleName: 'theme',
44
- loc: '',
45
- message: 'TS2322: Wrong type.',
46
- },
47
- ]);
48
- });
49
-
50
- it('removes the overlay when the last type error is fixed', () => {
51
- plugin.results.set('theme', [TYPE_ERROR]);
52
- plugin.updateOverlay();
53
- plugin.results.set('theme', []);
54
- plugin.updateOverlay();
55
-
56
- expect(devServer.sendMessage).toHaveBeenLastCalledWith(['tab'], 'still-ok');
57
- });
58
-
59
- it('keeps the errors of the build in the overlay when the last type error is fixed', () => {
60
- plugin.results.set('theme', [TYPE_ERROR]);
61
- plugin.updateOverlay();
62
- plugin.results.set('theme', []);
63
- plugin.buildErrors = [BUILD_ERROR];
64
- plugin.updateOverlay();
65
-
66
- expect(devServer.sendMessage).toHaveBeenLastCalledWith(['tab'], 'errors', [BUILD_ERROR]);
67
- });
68
-
69
- it('does not show anything without the overlay option', () => {
70
- plugin = new ShopgateTypeCheckPlugin();
71
- plugin.setDevServer(devServer);
72
- plugin.results.set('theme', [TYPE_ERROR]);
73
- plugin.updateOverlay();
74
-
75
- expect(devServer.sendMessage).not.toHaveBeenCalled();
76
- });
77
- });