|
1 |
| -import { describe, it } from 'node:test'; |
| 1 | +import { describe, it, afterEach } from 'node:test'; |
2 | 2 | import assert from 'node:assert';
|
3 | 3 | import { join } from 'node:path';
|
4 | 4 | import { type Compilation } from 'webpack';
|
@@ -232,7 +232,7 @@ describe('ManifestPlugin', () => {
|
232 | 232 | function runTest(baseManifest: Combination<typeof manifestMatrix>) {
|
233 | 233 | const manifest = baseManifest as unknown as chrome.runtime.Manifest;
|
234 | 234 | const hasTabsPermission = (manifest.permissions || []).includes('tabs');
|
235 |
| - const transform = transformManifest(args); |
| 235 | + const transform = transformManifest(args, false); |
236 | 236 |
|
237 | 237 | if (args.test && hasTabsPermission) {
|
238 | 238 | it("throws in test mode when manifest already contains 'tabs' permission", () => {
|
@@ -281,4 +281,118 @@ describe('ManifestPlugin', () => {
|
281 | 281 | }
|
282 | 282 | }
|
283 | 283 | });
|
| 284 | + |
| 285 | + describe('manifest flags in development mode', () => { |
| 286 | + const emptyTestManifest = {} as chrome.runtime.Manifest; |
| 287 | + const notEmptyTestManifest = { |
| 288 | + _flags: { remoteFeatureFlags: { testFlag: false, testFlag2: 'value1' } }, |
| 289 | + } as unknown as chrome.runtime.Manifest; |
| 290 | + const mockFlags = { _flags: { remoteFeatureFlags: { testFlag: true } } }; |
| 291 | + const manifestOverridesPath = 'testManifestOverridesPath.json'; |
| 292 | + const fs = require('node:fs'); |
| 293 | + const { mock } = require('node:test'); |
| 294 | + const { resolve } = require('node:path'); |
| 295 | + |
| 296 | + afterEach(() => mock.restoreAll()); |
| 297 | + |
| 298 | + it('adds manifest flags in development mode with path provided and empty manifest', () => { |
| 299 | + mock.method(fs, 'readFileSync', (path: string, options: object) => { |
| 300 | + if (path === resolve(__dirname, '../../../', manifestOverridesPath)) { |
| 301 | + return JSON.stringify(mockFlags); |
| 302 | + } |
| 303 | + return fs.readFileSync.original(path, options); |
| 304 | + }); |
| 305 | + const transform = transformManifest( |
| 306 | + { lockdown: true, test: false }, |
| 307 | + true, |
| 308 | + manifestOverridesPath, |
| 309 | + ); |
| 310 | + assert(transform, 'transform should be truthy'); |
| 311 | + |
| 312 | + const transformed = transform(emptyTestManifest, 'chrome'); |
| 313 | + console.log('Transformed:', transformed); |
| 314 | + assert.deepStrictEqual( |
| 315 | + transformed, |
| 316 | + mockFlags, |
| 317 | + 'manifest should have flags in development mode', |
| 318 | + ); |
| 319 | + }); |
| 320 | + |
| 321 | + it('overwrites existing manifest properties with override values but keeps original properties', () => { |
| 322 | + mock.method(fs, 'readFileSync', (path: string, options: object) => { |
| 323 | + if (path === resolve(__dirname, '../../../', manifestOverridesPath)) { |
| 324 | + return JSON.stringify(mockFlags); |
| 325 | + } |
| 326 | + return fs.readFileSync.original(path, options); |
| 327 | + }); |
| 328 | + const transform = transformManifest( |
| 329 | + { lockdown: true, test: false }, |
| 330 | + true, |
| 331 | + manifestOverridesPath, |
| 332 | + ); |
| 333 | + assert(transform, 'transform should be truthy'); |
| 334 | + |
| 335 | + const transformed = transform(notEmptyTestManifest, 'chrome'); |
| 336 | + assert.deepStrictEqual( |
| 337 | + transformed, |
| 338 | + { |
| 339 | + _flags: { |
| 340 | + remoteFeatureFlags: { |
| 341 | + testFlag2: 'value1', |
| 342 | + testFlag: true, |
| 343 | + }, |
| 344 | + }, |
| 345 | + }, |
| 346 | + 'manifest should merge original properties with overrides, with overrides taking precedence', |
| 347 | + ); |
| 348 | + }); |
| 349 | + |
| 350 | + it('handles missing manifest flags file with path provided', () => { |
| 351 | + mock.method(fs, 'readFileSync', () => { |
| 352 | + const error = new Error('File not found') as NodeJS.ErrnoException; |
| 353 | + error.code = 'ENOENT'; |
| 354 | + throw error; |
| 355 | + }); |
| 356 | + |
| 357 | + const transform = transformManifest( |
| 358 | + { lockdown: true, test: false }, |
| 359 | + true, |
| 360 | + manifestOverridesPath, |
| 361 | + ); |
| 362 | + assert(transform, 'transform should be truthy'); |
| 363 | + |
| 364 | + assert.throws( |
| 365 | + () => transform(emptyTestManifest, 'chrome'), |
| 366 | + { |
| 367 | + message: `Manifest override file not found: ${manifestOverridesPath}`, |
| 368 | + }, |
| 369 | + 'should throw when manifest override file is not found', |
| 370 | + ); |
| 371 | + }); |
| 372 | + |
| 373 | + it('silently ignores non-ENOENT filesystem errors', () => { |
| 374 | + const transform = transformManifest( |
| 375 | + { lockdown: true, test: false }, |
| 376 | + true, |
| 377 | + manifestOverridesPath, |
| 378 | + ); |
| 379 | + assert(transform, 'transform should be truthy'); |
| 380 | + |
| 381 | + const originalError = new Error( |
| 382 | + 'Permission denied', |
| 383 | + ) as NodeJS.ErrnoException; |
| 384 | + originalError.code = 'EACCES'; |
| 385 | + |
| 386 | + mock.method(fs, 'readFileSync', () => { |
| 387 | + throw originalError; |
| 388 | + }); |
| 389 | + |
| 390 | + const transformed = transform(emptyTestManifest, 'chrome'); |
| 391 | + assert.deepStrictEqual( |
| 392 | + transformed._flags, |
| 393 | + undefined, |
| 394 | + 'should not have flags when file read fails with non-ENOENT error', |
| 395 | + ); |
| 396 | + }); |
| 397 | + }); |
284 | 398 | });
|
0 commit comments