diff --git a/src/cli/run.ts b/src/cli/run.ts index 73b59254a8e..18a33780e3f 100644 --- a/src/cli/run.ts +++ b/src/cli/run.ts @@ -15,7 +15,7 @@ import { taskServe } from './task-serve'; import { taskTest } from './task-test'; import { taskTelemetry } from './task-telemetry'; import { telemetryAction } from './telemetry/telemetry'; -import { ValidatedConfig } from '../declarations'; +import { createLogger } from '../compiler/sys/logger/console-logger'; export const run = async (init: d.CliInitOptions) => { const { args, logger, sys } = init; @@ -72,7 +72,7 @@ export const run = async (init: d.CliInitOptions) => { loadedCompilerLog(sys, logger, flags, coreCompiler); if (task === 'info') { - await telemetryAction(sys, { flags: { task: 'info' }, outputTargets: [] }, logger, coreCompiler, async () => { + await telemetryAction(sys, { flags: { task: 'info' }, logger }, coreCompiler, async () => { await taskInfo(coreCompiler, sys, logger); }); return; @@ -100,7 +100,7 @@ export const run = async (init: d.CliInitOptions) => { await sys.ensureResources({ rootDir: validated.config.rootDir, logger, dependencies: dependencies as any }); - await telemetryAction(sys, validated.config, logger, coreCompiler, async () => { + await telemetryAction(sys, validated.config, coreCompiler, async () => { await runTask(coreCompiler, validated.config, task, sys); }); } catch (e) { @@ -118,7 +118,9 @@ export const runTask = async ( task: d.TaskCommand, sys?: d.CompilerSystem ) => { - const strictConfig: ValidatedConfig = { ...config, flags: { ...config.flags } ?? { task } }; + const logger = config.logger ?? createLogger(); + const strictConfig: d.ValidatedConfig = { ...config, flags: { ...config.flags } ?? { task }, logger }; + strictConfig.outputTargets = strictConfig.outputTargets || []; switch (task) { @@ -136,7 +138,7 @@ export const runTask = async ( break; case 'help': - await taskHelp(strictConfig.flags, config.logger, sys); + await taskHelp(strictConfig.flags, strictConfig.logger, sys); break; case 'prerender': @@ -150,7 +152,7 @@ export const runTask = async ( case 'telemetry': // TODO(STENCIL-148) make this parameter no longer optional, remove the surrounding if statement if (sys) { - await taskTelemetry(strictConfig.flags, sys, config.logger); + await taskTelemetry(strictConfig.flags, sys, strictConfig.logger); } break; @@ -163,8 +165,10 @@ export const runTask = async ( break; default: - config.logger.error(`${config.logger.emoji('❌ ')}Invalid stencil command, please see the options below:`); - await taskHelp(strictConfig.flags, config.logger, sys); + strictConfig.logger.error( + `${strictConfig.logger.emoji('❌ ')}Invalid stencil command, please see the options below:` + ); + await taskHelp(strictConfig.flags, strictConfig.logger, sys); return config.sys.exit(1); } }; diff --git a/src/cli/task-build.ts b/src/cli/task-build.ts index 255d812062c..c1caad97297 100644 --- a/src/cli/task-build.ts +++ b/src/cli/task-build.ts @@ -26,7 +26,7 @@ export const taskBuild = async (coreCompiler: CoreCompiler, config: d.ValidatedC // TODO(STENCIL-148) make this parameter no longer optional, remove the surrounding if statement if (sys) { - await telemetryBuildFinishedAction(sys, config, config.logger, coreCompiler, results); + await telemetryBuildFinishedAction(sys, config, coreCompiler, results); } await compiler.destroy(); diff --git a/src/cli/telemetry/telemetry.ts b/src/cli/telemetry/telemetry.ts index 9824c561cd5..ea143633138 100644 --- a/src/cli/telemetry/telemetry.ts +++ b/src/cli/telemetry/telemetry.ts @@ -10,14 +10,12 @@ import { isOutputTargetHydrate, WWW } from '../../compiler/output-targets/output * * @param sys The system where the command is invoked * @param config The config passed into the Stencil command - * @param logger The tool used to do logging * @param coreCompiler The compiler used to do builds * @param result The results of a compiler build. */ export async function telemetryBuildFinishedAction( sys: d.CompilerSystem, config: d.ValidatedConfig, - logger: d.Logger, coreCompiler: CoreCompiler, result: d.CompilerBuildResults ) { @@ -32,7 +30,8 @@ export async function telemetryBuildFinishedAction( const data = await prepareData(coreCompiler, config, sys, result.duration, component_count); await sendMetric(sys, config, 'stencil_cli_command', data); - logger.debug(`${logger.blue('Telemetry')}: ${logger.gray(JSON.stringify(data))}`); + + config.logger.debug(`${config.logger.blue('Telemetry')}: ${config.logger.gray(JSON.stringify(data))}`); } /** @@ -40,7 +39,6 @@ export async function telemetryBuildFinishedAction( * * @param sys The system where the command is invoked * @param config The config passed into the Stencil command - * @param logger The tool used to do logging * @param coreCompiler The compiler used to do builds * @param action A Promise-based function to call in order to get the duration of any given command. * @returns void @@ -48,7 +46,6 @@ export async function telemetryBuildFinishedAction( export async function telemetryAction( sys: d.CompilerSystem, config: d.ValidatedConfig, - logger: d.Logger, coreCompiler: CoreCompiler, action?: d.TelemetryCallback ) { @@ -78,7 +75,7 @@ export async function telemetryAction( const data = await prepareData(coreCompiler, config, sys, duration); await sendMetric(sys, config, 'stencil_cli_command', data); - logger.debug(`${logger.blue('Telemetry')}: ${logger.gray(JSON.stringify(data))}`); + config.logger.debug(`${config.logger.blue('Telemetry')}: ${config.logger.gray(JSON.stringify(data))}`); if (error) { throw error; diff --git a/src/cli/telemetry/test/telemetry.spec.ts b/src/cli/telemetry/test/telemetry.spec.ts index cf16b9d36bf..67a938c819a 100644 --- a/src/cli/telemetry/test/telemetry.spec.ts +++ b/src/cli/telemetry/test/telemetry.spec.ts @@ -2,7 +2,7 @@ import type * as d from '../../../declarations'; import * as telemetry from '../telemetry'; import * as shouldTrack from '../shouldTrack'; import { createSystem } from '../../../compiler/sys/stencil-sys'; -import { mockValidatedConfig } from '@stencil/core/testing'; +import { mockLogger, mockValidatedConfig } from '@stencil/core/testing'; import * as coreCompiler from '@stencil/core/compiler'; import { anonymizeConfigForTelemetry } from '../telemetry'; import { DIST, DIST_CUSTOM_ELEMENTS, DIST_HYDRATE_SCRIPT, WWW } from '../../../compiler/output-targets/output-utils'; @@ -31,7 +31,7 @@ describe('telemetryBuildFinishedAction', () => { duration: 100, } as d.CompilerBuildResults; - await telemetry.telemetryBuildFinishedAction(sys, config, config.logger, coreCompiler, results); + await telemetry.telemetryBuildFinishedAction(sys, config, coreCompiler, results); expect(spyShouldTrack).toHaveBeenCalled(); spyShouldTrack.mockRestore(); @@ -57,7 +57,7 @@ describe('telemetryAction', () => { }) ); - await telemetry.telemetryAction(sys, config, config.logger, coreCompiler, () => {}); + await telemetry.telemetryAction(sys, config, coreCompiler, () => {}); expect(spyShouldTrack).toHaveBeenCalled(); spyShouldTrack.mockRestore(); @@ -71,7 +71,7 @@ describe('telemetryAction', () => { }) ); - await telemetry.telemetryAction(sys, config, config.logger, coreCompiler, async () => { + await telemetry.telemetryAction(sys, config, coreCompiler, async () => { new Promise((resolve) => { setTimeout(() => { resolve(true); @@ -142,6 +142,7 @@ describe('prepareData', () => { flags: { args: [], }, + logger: mockLogger(), }; sys = createSystem(); @@ -182,6 +183,7 @@ describe('prepareData', () => { flags: { args: [], }, + logger: mockLogger(), outputTargets: [{ type: 'www', baseUrl: 'https://example.com', serviceWorker: { swDest: './tmp' } }], }; @@ -228,6 +230,7 @@ describe('prepareData', () => { flags: { args: [], }, + logger: mockLogger(), outputTargets: [{ type: 'www', baseUrl: 'https://example.com', serviceWorker: { swDest: './tmp' } }], }; diff --git a/src/compiler/config/load-config.ts b/src/compiler/config/load-config.ts index 9df2fbe971f..0d3735afeeb 100644 --- a/src/compiler/config/load-config.ts +++ b/src/compiler/config/load-config.ts @@ -6,7 +6,6 @@ import type { UnvalidatedConfig, } from '../../declarations'; import { buildError, catchError, hasError, isString, normalizePath } from '@utils'; -import { createLogger } from '../sys/logger/console-logger'; import { createSystem } from '../sys/stencil-sys'; import { dirname } from 'path'; import { IS_NODE_ENV } from '../sys/environment'; @@ -71,7 +70,7 @@ export const loadConfig = async (init: LoadConfigInit = {}): Promise { const configPath = require.resolve('./fixtures/stencil.config.ts'); @@ -11,7 +12,7 @@ describe('stencil config - sourceMap option', () => { /** * Test helper for generating default `d.LoadConfigInit` objects. * - * This function assumes the fields in the enclosing scope have ben initialized. + * This function assumes the fields in the enclosing scope have been initialized. * @param overrides the properties on the default `d.LoadConfigInit` entity to manually override * @returns the default configuration initialization object, with any overrides applied */ @@ -22,7 +23,8 @@ describe('stencil config - sourceMap option', () => { config: {}, initTsConfig: true, }; - return { ...defaults, ...overrides }; + + return mockLoadConfigInit({ ...defaults, ...overrides }); }; beforeEach(() => { diff --git a/src/compiler/config/test/validate-config.spec.ts b/src/compiler/config/test/validate-config.spec.ts index 50a3e6fdf1c..f78864ee994 100644 --- a/src/compiler/config/test/validate-config.spec.ts +++ b/src/compiler/config/test/validate-config.spec.ts @@ -1,11 +1,12 @@ import type * as d from '@stencil/core/declarations'; -import { mockLogger, mockCompilerSystem } from '@stencil/core/testing'; +import { mockLogger, mockCompilerSystem, mockLoadConfigInit } from '@stencil/core/testing'; import { isWatchIgnorePath } from '../../fs-watch/fs-watch-rebuild'; import { DOCS_JSON, DOCS_CUSTOM, DOCS_README, DOCS_VSCODE } from '../../output-targets/output-utils'; import { validateConfig } from '../validate-config'; describe('validation', () => { let userConfig: d.UnvalidatedConfig; + let bootstrapConfig: d.LoadConfigInit; const logger = mockLogger(); const sys = mockCompilerSystem(); @@ -16,37 +17,38 @@ describe('validation', () => { rootDir: '/User/some/path/', namespace: 'Testing', }; + bootstrapConfig = mockLoadConfigInit(); }); describe('flags', () => { it('adds a default "flags" object if none is provided', () => { userConfig.flags = undefined; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, bootstrapConfig); expect(config.flags).toEqual({}); }); it('serializes a provided "flags" object', () => { userConfig.flags = { dev: false }; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, bootstrapConfig); expect(config.flags).toEqual({ dev: false }); }); describe('devMode', () => { it('defaults "devMode" to false when "flag.prod" is truthy', () => { userConfig.flags = { prod: true }; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, bootstrapConfig); expect(config.devMode).toBe(false); }); it('defaults "devMode" to true when "flag.dev" is truthy', () => { userConfig.flags = { dev: true }; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, bootstrapConfig); expect(config.devMode).toBe(true); }); it('defaults "devMode" to false when "flag.prod" & "flag.dev" are truthy', () => { userConfig.flags = { dev: true, prod: true }; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, bootstrapConfig); expect(config.devMode).toBe(false); }); @@ -54,7 +56,7 @@ describe('validation', () => { // the branch under test explicitly requires a value whose type is not allowed by the type system const devMode = 'not-a-bool' as unknown as boolean; userConfig = { devMode }; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, bootstrapConfig); expect(config.devMode).toBe(false); }); }); @@ -63,18 +65,18 @@ describe('validation', () => { describe('allowInlineScripts', () => { it('set allowInlineScripts true', () => { userConfig.allowInlineScripts = true; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, bootstrapConfig); expect(config.allowInlineScripts).toBe(true); }); it('set allowInlineScripts false', () => { userConfig.allowInlineScripts = false; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, bootstrapConfig); expect(config.allowInlineScripts).toBe(false); }); it('default allowInlineScripts true', () => { - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, bootstrapConfig); expect(config.allowInlineScripts).toBe(true); }); }); @@ -82,18 +84,18 @@ describe('validation', () => { describe('enableCache', () => { it('set enableCache true', () => { userConfig.enableCache = true; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, bootstrapConfig); expect(config.enableCache).toBe(true); }); it('set enableCache false', () => { userConfig.enableCache = false; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, bootstrapConfig); expect(config.enableCache).toBe(false); }); it('default enableCache true', () => { - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, bootstrapConfig); expect(config.enableCache).toBe(true); }); }); @@ -101,18 +103,18 @@ describe('validation', () => { describe('buildAppCore', () => { it('set buildAppCore true', () => { userConfig.buildAppCore = true; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, bootstrapConfig); expect(config.buildAppCore).toBe(true); }); it('set buildAppCore false', () => { userConfig.buildAppCore = false; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, bootstrapConfig); expect(config.buildAppCore).toBe(false); }); it('default buildAppCore true', () => { - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, bootstrapConfig); expect(config.buildAppCore).toBe(true); }); }); @@ -120,47 +122,47 @@ describe('validation', () => { describe('es5 build', () => { it('set buildEs5 false', () => { userConfig.buildEs5 = false; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, bootstrapConfig); expect(config.buildEs5).toBe(false); }); it('set buildEs5 true', () => { userConfig.buildEs5 = true; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, bootstrapConfig); expect(config.buildEs5).toBe(true); }); it('set buildEs5 true, dev mode', () => { userConfig.devMode = true; userConfig.buildEs5 = true; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, bootstrapConfig); expect(config.buildEs5).toBe(true); }); it('prod mode, set modern and es5', () => { userConfig.devMode = false; userConfig.buildEs5 = true; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, bootstrapConfig); expect(config.buildEs5).toBe(true); }); it('build es5 when set to "prod" and in prod', () => { userConfig.devMode = false; userConfig.buildEs5 = 'prod'; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, bootstrapConfig); expect(config.buildEs5).toBe(true); }); it('do not build es5 when set to "prod" and in dev', () => { userConfig.devMode = true; userConfig.buildEs5 = 'prod'; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, bootstrapConfig); expect(config.buildEs5).toBe(false); }); it('prod mode default to only modern and not es5', () => { userConfig.devMode = false; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, bootstrapConfig); expect(config.buildEs5).toBe(false); }); }); @@ -168,55 +170,55 @@ describe('validation', () => { describe('hashed filenames', () => { it('should error when hashedFileNameLength too large', () => { userConfig.hashedFileNameLength = 33; - const validated = validateConfig(userConfig); + const validated = validateConfig(userConfig, bootstrapConfig); expect(validated.diagnostics).toHaveLength(1); }); it('should error when hashedFileNameLength too small', () => { userConfig.hashedFileNameLength = 3; - const validated = validateConfig(userConfig); + const validated = validateConfig(userConfig, bootstrapConfig); expect(validated.diagnostics).toHaveLength(1); }); it('should set from hashedFileNameLength', () => { userConfig.hashedFileNameLength = 28; - const validated = validateConfig(userConfig); + const validated = validateConfig(userConfig, bootstrapConfig); expect(validated.config.hashedFileNameLength).toBe(28); }); it('should set hashedFileNameLength', () => { userConfig.hashedFileNameLength = 6; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, bootstrapConfig); expect(config.hashedFileNameLength).toBe(6); }); it('should default hashedFileNameLength', () => { - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, bootstrapConfig); expect(config.hashedFileNameLength).toBe(8); }); it('should default hashFileNames to false in watch mode despite prod mode', () => { userConfig.watch = true; userConfig.devMode = false; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, bootstrapConfig); expect(config.hashFileNames).toBe(true); }); it('should default hashFileNames to true in prod mode', () => { userConfig.devMode = false; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, bootstrapConfig); expect(config.hashFileNames).toBe(true); }); it('should default hashFileNames to false in dev mode', () => { userConfig.devMode = true; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, bootstrapConfig); expect(config.hashFileNames).toBe(false); }); it.each([true, false])('should set hashFileNames when hashFileNames===%b', (hashFileNames) => { userConfig.hashFileNames = hashFileNames; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, bootstrapConfig); expect(config.hashFileNames).toBe(hashFileNames); }); @@ -224,7 +226,7 @@ describe('validation', () => { (userConfig as any).hashFileNames = () => { return true; }; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, bootstrapConfig); expect(config.hashFileNames).toBe(true); }); }); @@ -233,19 +235,19 @@ describe('validation', () => { it('should set minifyJs to true', () => { userConfig.devMode = true; userConfig.minifyJs = true; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, bootstrapConfig); expect(config.minifyJs).toBe(true); }); it('should default minifyJs to true in prod mode', () => { userConfig.devMode = false; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, bootstrapConfig); expect(config.minifyJs).toBe(true); }); it('should default minifyJs to false in dev mode', () => { userConfig.devMode = true; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, bootstrapConfig); expect(config.minifyJs).toBe(false); }); }); @@ -254,79 +256,79 @@ describe('validation', () => { it('should set minifyCss to true', () => { userConfig.devMode = true; userConfig.minifyCss = true; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, bootstrapConfig); expect(config.minifyCss).toBe(true); }); it('should default minifyCss to true in prod mode', () => { userConfig.devMode = false; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, bootstrapConfig); expect(config.minifyCss).toBe(true); }); it('should default minifyCss to false in dev mode', () => { userConfig.devMode = true; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, bootstrapConfig); expect(config.minifyCss).toBe(false); }); }); it('should default watch to false', () => { - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, bootstrapConfig); expect(config.watch).toBe(false); }); it('should set devMode to false', () => { userConfig.devMode = false; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, bootstrapConfig); expect(config.devMode).toBe(false); }); it('should set devMode to true', () => { userConfig.devMode = true; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, bootstrapConfig); expect(config.devMode).toBe(true); }); it('should default devMode to false', () => { - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, bootstrapConfig); expect(config.devMode).toBe(false); }); it.each([DOCS_JSON, DOCS_CUSTOM, DOCS_README, DOCS_VSCODE])( 'should not add "%s" output target by default', (targetType) => { - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, bootstrapConfig); expect(config.outputTargets.some((o) => o.type === targetType)).toBe(false); } ); it('should set devInspector false', () => { userConfig.devInspector = false; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, bootstrapConfig); expect(config.devInspector).toBe(false); }); it('should set devInspector true', () => { userConfig.devInspector = true; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, bootstrapConfig); expect(config.devInspector).toBe(true); }); it('should default devInspector false when devMode is false', () => { userConfig.devMode = false; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, bootstrapConfig); expect(config.devInspector).toBe(false); }); it('should default devInspector true when devMode is true', () => { userConfig.devMode = true; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, bootstrapConfig); expect(config.devInspector).toBe(true); }); it('should default dist false and www true', () => { - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, bootstrapConfig); expect(config.outputTargets.some((o) => o.type === 'dist')).toBe(false); expect(config.outputTargets.some((o) => o.type === 'www')).toBe(true); }); @@ -337,7 +339,7 @@ describe('validation', () => { type: 'whatever', } as any, ]; - const validated = validateConfig(userConfig); + const validated = validateConfig(userConfig, bootstrapConfig); expect(validated.diagnostics).toHaveLength(1); }); @@ -347,7 +349,7 @@ describe('validation', () => { type: 'dist-custom-elements-bundle', }, ]; - const validated = validateConfig(userConfig); + const validated = validateConfig(userConfig, bootstrapConfig); expect(validated.diagnostics).toHaveLength(1); expect(validated.diagnostics[0].messageText).toBe( 'dist-custom-elements-bundle is deprecated and will be removed in a future major version release. Use "dist-custom-elements" instead. If "dist-custom-elements" does not meet your needs, please add a comment to https://github.com/ionic-team/stencil/issues/3136.' @@ -355,12 +357,12 @@ describe('validation', () => { }); it('should default outputTargets with www', () => { - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, bootstrapConfig); expect(config.outputTargets.some((o) => o.type === 'www')).toBe(true); }); it('should set extras defaults', () => { - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, bootstrapConfig); expect(config.extras.appendChildSlotFix).toBe(false); expect(config.extras.cloneNodeFix).toBe(false); expect(config.extras.cssVarsShim).toBe(false); @@ -375,18 +377,18 @@ describe('validation', () => { }); it('should set taskQueue "async" by default', () => { - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, bootstrapConfig); expect(config.taskQueue).toBe('async'); }); it('should set taskQueue', () => { userConfig.taskQueue = 'congestionAsync'; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, bootstrapConfig); expect(config.taskQueue).toBe('congestionAsync'); }); it('empty watchIgnoredRegex, all valid', () => { - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, bootstrapConfig); expect(config.watchIgnoredRegex).toEqual([]); expect(isWatchIgnorePath(config, '/some/image.gif')).toBe(false); expect(isWatchIgnorePath(config, '/some/typescript.ts')).toBe(false); @@ -394,7 +396,7 @@ describe('validation', () => { it('should change a single watchIgnoredRegex to an array', () => { userConfig.watchIgnoredRegex = /\.(gif|jpe?g|png)$/i; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, bootstrapConfig); expect(config.watchIgnoredRegex).toHaveLength(1); expect((config.watchIgnoredRegex as any[])[0]).toEqual(/\.(gif|jpe?g|png)$/i); expect(isWatchIgnorePath(config, '/some/image.gif')).toBe(true); @@ -403,7 +405,7 @@ describe('validation', () => { it('should clean up valid watchIgnoredRegex', () => { userConfig.watchIgnoredRegex = [/\.(gif|jpe?g)$/i, null, 'me-regex' as any, /\.(png)$/i]; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, bootstrapConfig); expect(config.watchIgnoredRegex).toHaveLength(2); expect((config.watchIgnoredRegex as any[])[0]).toEqual(/\.(gif|jpe?g)$/i); expect((config.watchIgnoredRegex as any[])[1]).toEqual(/\.(png)$/i); @@ -416,18 +418,18 @@ describe('validation', () => { describe('sourceMap', () => { it('sets the field to true when the set to true in the config', () => { userConfig.sourceMap = true; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, bootstrapConfig); expect(config.sourceMap).toBe(true); }); it('sets the field to false when set to false in the config', () => { userConfig.sourceMap = false; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, bootstrapConfig); expect(config.sourceMap).toBe(false); }); it('defaults the field to false when not set in the config', () => { - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, bootstrapConfig); expect(config.sourceMap).toBe(false); }); }); @@ -435,20 +437,20 @@ describe('validation', () => { describe('buildDist', () => { it.each([true, false])('should set the field based on the config flag (%p)', (flag) => { userConfig.flags = { esm: flag }; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, bootstrapConfig); expect(config.buildDist).toBe(flag); }); it.each([true, false])('should fallback to !devMode', (devMode) => { userConfig.devMode = devMode; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, bootstrapConfig); expect(config.buildDist).toBe(!devMode); }); it.each([true, false])('should fallback to buildEs5 in devMode', (buildEs5) => { userConfig.devMode = true; userConfig.buildEs5 = buildEs5; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, bootstrapConfig); expect(config.buildDist).toBe(config.buildEs5); }); }); diff --git a/src/compiler/config/test/validate-custom.spec.ts b/src/compiler/config/test/validate-custom.spec.ts index d9b02b31773..c5d4513dbad 100644 --- a/src/compiler/config/test/validate-custom.spec.ts +++ b/src/compiler/config/test/validate-custom.spec.ts @@ -1,5 +1,5 @@ import type * as d from '@stencil/core/declarations'; -import { mockConfig } from '@stencil/core/testing'; +import { mockConfig, mockLoadConfigInit } from '@stencil/core/testing'; import { validateConfig } from '../validate-config'; import { buildWarn } from '@utils'; @@ -24,7 +24,7 @@ describe('validateCustom', () => { }, }, ]; - const { diagnostics } = validateConfig(userConfig); + const { diagnostics } = validateConfig(userConfig, mockLoadConfigInit()); expect(diagnostics.length).toBe(1); }); }); diff --git a/src/compiler/config/test/validate-dev-server.spec.ts b/src/compiler/config/test/validate-dev-server.spec.ts index 63bd22761a2..7655e776a7c 100644 --- a/src/compiler/config/test/validate-dev-server.spec.ts +++ b/src/compiler/config/test/validate-dev-server.spec.ts @@ -3,6 +3,7 @@ import { normalizePath } from '../../../utils'; import { validateConfig } from '../validate-config'; import path from 'path'; import { ConfigFlags } from '../../../cli/config-flags'; +import { mockLoadConfigInit } from '@stencil/core/testing'; describe('validateDevServer', () => { const root = path.resolve('/'); @@ -21,7 +22,7 @@ describe('validateDevServer', () => { }); it('should default address', () => { - const { config } = validateConfig(inputConfig); + const { config } = validateConfig(inputConfig, mockLoadConfigInit()); expect(config.devServer.address).toBe('0.0.0.0'); }); @@ -29,20 +30,20 @@ describe('validateDevServer', () => { 'should remove extraneous stuff from address %p', (address) => { inputConfig.devServer.address = address; - const { config } = validateConfig(inputConfig); + const { config } = validateConfig(inputConfig, mockLoadConfigInit()); expect(config.devServer.address).toBe('localhost'); } ); it('should set address', () => { inputConfig.devServer.address = '123.123.123.123'; - const { config } = validateConfig(inputConfig); + const { config } = validateConfig(inputConfig, mockLoadConfigInit()); expect(config.devServer.address).toBe('123.123.123.123'); }); it('should set address from flags', () => { inputConfig.flags = { ...flags, address: '123.123.123.123' }; - const { config } = validateConfig(inputConfig); + const { config } = validateConfig(inputConfig, mockLoadConfigInit()); expect(config.devServer.address).toBe('123.123.123.123'); }); @@ -53,7 +54,7 @@ describe('validateDevServer', () => { baseUrl: '/my-base-url', } as d.OutputTargetWww, ]; - const { config } = validateConfig(inputConfig); + const { config } = validateConfig(inputConfig, mockLoadConfigInit()); expect(config.devServer.basePath).toBe('/my-base-url/'); }); @@ -64,45 +65,45 @@ describe('validateDevServer', () => { baseUrl: 'http://stenciljs.com/my-base-url', } as d.OutputTargetWww, ]; - const { config } = validateConfig(inputConfig); + const { config } = validateConfig(inputConfig, mockLoadConfigInit()); expect(config.devServer.basePath).toBe('/my-base-url/'); }); it('should default basePath', () => { - const { config } = validateConfig(inputConfig); + const { config } = validateConfig(inputConfig, mockLoadConfigInit()); expect(config.devServer.basePath).toBe('/'); }); it('should default root', () => { - const { config } = validateConfig(inputConfig); + const { config } = validateConfig(inputConfig, mockLoadConfigInit()); expect(config.devServer.root).toBe(normalizePath(path.join(root, 'some', 'path', 'www'))); }); it('should set relative root', () => { inputConfig.devServer.root = 'my-rel-root'; - const { config } = validateConfig(inputConfig); + const { config } = validateConfig(inputConfig, mockLoadConfigInit()); expect(config.devServer.root).toBe(normalizePath(path.join(root, 'some', 'path', 'my-rel-root'))); }); it('should set absolute root', () => { inputConfig.devServer.root = normalizePath(path.join(root, 'some', 'path', 'my-abs-root')); - const { config } = validateConfig(inputConfig); + const { config } = validateConfig(inputConfig, mockLoadConfigInit()); expect(config.devServer.root).toBe(normalizePath(path.join(root, 'some', 'path', 'my-abs-root'))); }); it('should default gzip', () => { - const { config } = validateConfig(inputConfig); + const { config } = validateConfig(inputConfig, mockLoadConfigInit()); expect(config.devServer.gzip).toBe(true); }); it('should set gzip', () => { inputConfig.devServer.gzip = false; - const { config } = validateConfig(inputConfig); + const { config } = validateConfig(inputConfig, mockLoadConfigInit()); expect(config.devServer.gzip).toBe(false); }); it.each(['localhost', '192.12.12.10', '127.0.0.1'])('should default port with address %p', () => { - const { config } = validateConfig(inputConfig); + const { config } = validateConfig(inputConfig, mockLoadConfigInit()); expect(config.devServer.port).toBe(3333); }); @@ -111,27 +112,27 @@ describe('validateDevServer', () => { (address) => { inputConfig.devServer.port = 1234; inputConfig.devServer.address = address; - const { config } = validateConfig(inputConfig); + const { config } = validateConfig(inputConfig, mockLoadConfigInit()); expect(config.devServer.port).toBe(1234); } ); it('should not set default port if null', () => { inputConfig.devServer.port = null; - const { config } = validateConfig(inputConfig); + const { config } = validateConfig(inputConfig, mockLoadConfigInit()); expect(config.devServer.port).toBe(null); }); it.each(['localhost:20/', 'localhost:20'])('should set port from address %p if no port prop', (address) => { inputConfig.devServer.address = address; - const { config } = validateConfig(inputConfig); + const { config } = validateConfig(inputConfig, mockLoadConfigInit()); expect(config.devServer.port).toBe(20); expect(config.devServer.address).toBe('localhost'); }); it('should set address, port null, protocol', () => { inputConfig.devServer.address = 'https://subdomain.stenciljs.com/'; - const { config } = validateConfig(inputConfig); + const { config } = validateConfig(inputConfig, mockLoadConfigInit()); expect(config.devServer.port).toBe(undefined); expect(config.devServer.address).toBe('subdomain.stenciljs.com'); expect(config.devServer.protocol).toBe('https'); @@ -139,99 +140,99 @@ describe('validateDevServer', () => { it('should set port', () => { inputConfig.devServer.port = 4444; - const { config } = validateConfig(inputConfig); + const { config } = validateConfig(inputConfig, mockLoadConfigInit()); expect(config.devServer.port).toBe(4444); }); it('should set port from flags', () => { inputConfig.flags = { ...flags, port: 4444 }; - const { config } = validateConfig(inputConfig); + const { config } = validateConfig(inputConfig, mockLoadConfigInit()); expect(config.devServer.port).toBe(4444); }); it('should default historyApiFallback', () => { - const { config } = validateConfig(inputConfig); + const { config } = validateConfig(inputConfig, mockLoadConfigInit()); expect(config.devServer.historyApiFallback).toBeDefined(); expect(config.devServer.historyApiFallback.index).toBe('index.html'); }); it('should set historyApiFallback', () => { inputConfig.devServer.historyApiFallback = {}; - const { config } = validateConfig(inputConfig); + const { config } = validateConfig(inputConfig, mockLoadConfigInit()); expect(config.devServer.historyApiFallback).toBeDefined(); expect(config.devServer.historyApiFallback.index).toBe('index.html'); }); it('should disable historyApiFallback', () => { inputConfig.devServer.historyApiFallback = null; - const { config } = validateConfig(inputConfig); + const { config } = validateConfig(inputConfig, mockLoadConfigInit()); expect(config.devServer.historyApiFallback).toBe(null); }); it('should default reloadStrategy hmr', () => { - const { config } = validateConfig(inputConfig); + const { config } = validateConfig(inputConfig, mockLoadConfigInit()); expect(config.devServer.reloadStrategy).toBe('hmr'); }); it('should set reloadStrategy pageReload', () => { inputConfig.devServer.reloadStrategy = 'pageReload'; - const { config } = validateConfig(inputConfig); + const { config } = validateConfig(inputConfig, mockLoadConfigInit()); expect(config.devServer.reloadStrategy).toBe('pageReload'); }); it('should default openBrowser', () => { - const { config } = validateConfig(inputConfig); + const { config } = validateConfig(inputConfig, mockLoadConfigInit()); expect(config.devServer.openBrowser).toBe(true); }); it('should set openBrowser', () => { inputConfig.devServer.openBrowser = false; - const { config } = validateConfig(inputConfig); + const { config } = validateConfig(inputConfig, mockLoadConfigInit()); expect(config.devServer.openBrowser).toBe(false); }); it('should set openBrowser from flag', () => { inputConfig.flags = { open: false }; - const { config } = validateConfig(inputConfig); + const { config } = validateConfig(inputConfig, mockLoadConfigInit()); expect(config.devServer.openBrowser).toBe(false); }); it('should default http protocol', () => { - const { config } = validateConfig(inputConfig); + const { config } = validateConfig(inputConfig, mockLoadConfigInit()); expect(config.devServer.protocol).toBe('http'); }); it('should set https protocol if credentials are set', () => { inputConfig.devServer.https = { key: 'fake-key', cert: 'fake-cert' }; - const { config } = validateConfig(inputConfig); + const { config } = validateConfig(inputConfig, mockLoadConfigInit()); expect(config.devServer.protocol).toBe('https'); }); it('should set ssr true', () => { inputConfig.devServer.ssr = true; - const { config } = validateConfig(inputConfig); + const { config } = validateConfig(inputConfig, mockLoadConfigInit()); expect(config.devServer.ssr).toBe(true); }); it('should set ssr false', () => { inputConfig.devServer.ssr = false; - const { config } = validateConfig(inputConfig); + const { config } = validateConfig(inputConfig, mockLoadConfigInit()); expect(config.devServer.ssr).toBe(false); }); it('should set ssr from flag', () => { inputConfig.flags = { ...flags, ssr: true }; - const { config } = validateConfig(inputConfig); + const { config } = validateConfig(inputConfig, mockLoadConfigInit()); expect(config.devServer.ssr).toBe(true); }); it('should set ssr false by default', () => { - const { config } = validateConfig(inputConfig); + const { config } = validateConfig(inputConfig, mockLoadConfigInit()); expect(config.devServer.ssr).toBe(false); }); it('should set default srcIndexHtml from config', () => { - const { config } = validateConfig(inputConfig); + const { config } = validateConfig(inputConfig, mockLoadConfigInit()); expect(config.devServer.srcIndexHtml).toBe(normalizePath(path.join(root, 'some', 'path', 'src', 'index.html'))); }); @@ -242,7 +243,7 @@ describe('validateDevServer', () => { }; inputConfig.outputTargets = [wwwOutputTarget]; inputConfig.flags = { ...flags, ssr: true }; - const { config } = validateConfig(inputConfig); + const { config } = validateConfig(inputConfig, mockLoadConfigInit()); expect(config.devServer.prerenderConfig).toBe(wwwOutputTarget.prerenderConfig); }); }); diff --git a/src/compiler/config/test/validate-docs.spec.ts b/src/compiler/config/test/validate-docs.spec.ts index 9218dfdcea6..c67b0d8264f 100644 --- a/src/compiler/config/test/validate-docs.spec.ts +++ b/src/compiler/config/test/validate-docs.spec.ts @@ -1,5 +1,5 @@ import type * as d from '@stencil/core/declarations'; -import { mockConfig } from '@stencil/core/testing'; +import { mockConfig, mockLoadConfigInit } from '@stencil/core/testing'; import { validateConfig } from '../validate-config'; describe('validateDocs', () => { @@ -17,19 +17,19 @@ describe('validateDocs', () => { dir: 'my-dir', } as d.OutputTargetDocsReadme, ]; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); const o = config.outputTargets.find((o) => o.type === 'docs-readme') as d.OutputTargetDocsReadme; expect(o.dir).toContain('my-dir'); }); it('default no docs, not remove docs output target', () => { userConfig.outputTargets = [{ type: 'docs-readme' }]; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); expect(config.outputTargets.some((o) => o.type === 'docs-readme')).toBe(true); }); it('default no docs, no output target', () => { - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); expect(config.outputTargets.some((o) => o.type === 'docs-readme')).toBe(false); }); }); diff --git a/src/compiler/config/test/validate-output-dist-custom-element.spec.ts b/src/compiler/config/test/validate-output-dist-custom-element.spec.ts index 9bc679ffef5..6926cf00459 100644 --- a/src/compiler/config/test/validate-output-dist-custom-element.spec.ts +++ b/src/compiler/config/test/validate-output-dist-custom-element.spec.ts @@ -1,5 +1,5 @@ import type * as d from '@stencil/core/declarations'; -import { mockConfig } from '@stencil/core/testing'; +import { mockConfig, mockLoadConfigInit } from '@stencil/core/testing'; import { COPY, DIST_CUSTOM_ELEMENTS, DIST_TYPES } from '../../output-targets/output-utils'; import { validateConfig } from '../validate-config'; import path from 'path'; @@ -21,7 +21,7 @@ describe('validate-output-dist-custom-element', () => { }; userConfig.outputTargets = [outputTarget]; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); expect(config.outputTargets).toEqual([ { type: DIST_CUSTOM_ELEMENTS, @@ -40,7 +40,7 @@ describe('validate-output-dist-custom-element', () => { }; userConfig.outputTargets = [outputTarget]; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); expect(config.outputTargets).toEqual([ { type: DIST_CUSTOM_ELEMENTS, @@ -60,7 +60,7 @@ describe('validate-output-dist-custom-element', () => { }; userConfig.outputTargets = [outputTarget]; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); expect(config.outputTargets).toEqual([ { type: DIST_CUSTOM_ELEMENTS, @@ -80,7 +80,7 @@ describe('validate-output-dist-custom-element', () => { }; userConfig.outputTargets = [outputTarget]; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); expect(config.outputTargets).toEqual([ { type: DIST_CUSTOM_ELEMENTS, @@ -101,7 +101,7 @@ describe('validate-output-dist-custom-element', () => { }; userConfig.outputTargets = [outputTarget]; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); expect(config.outputTargets).toEqual([ { type: DIST_CUSTOM_ELEMENTS, @@ -121,7 +121,7 @@ describe('validate-output-dist-custom-element', () => { }; userConfig.outputTargets = [outputTarget]; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); expect(config.outputTargets).toEqual([ { type: DIST_CUSTOM_ELEMENTS, @@ -144,7 +144,7 @@ describe('validate-output-dist-custom-element', () => { }; userConfig.outputTargets = [outputTarget]; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); expect(config.outputTargets).toEqual([ { type: DIST_TYPES, @@ -172,7 +172,7 @@ describe('validate-output-dist-custom-element', () => { }; userConfig.outputTargets = [outputTarget]; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); expect(config.outputTargets).toEqual([ { type: DIST_TYPES, @@ -199,7 +199,7 @@ describe('validate-output-dist-custom-element', () => { }; userConfig.outputTargets = [outputTarget]; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); expect(config.outputTargets).toEqual([ { type: DIST_CUSTOM_ELEMENTS, @@ -233,7 +233,7 @@ describe('validate-output-dist-custom-element', () => { }; userConfig.outputTargets = [outputTarget]; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); expect(config.outputTargets).toEqual([ { type: COPY, diff --git a/src/compiler/config/test/validate-output-dist.spec.ts b/src/compiler/config/test/validate-output-dist.spec.ts index 8803ec028d3..b9951dca25f 100644 --- a/src/compiler/config/test/validate-output-dist.spec.ts +++ b/src/compiler/config/test/validate-output-dist.spec.ts @@ -1,6 +1,6 @@ import type * as d from '@stencil/core/declarations'; import { validateConfig } from '../validate-config'; -import { mockConfig } from '@stencil/core/testing'; +import { mockConfig, mockLoadConfigInit } from '@stencil/core/testing'; import path from 'path'; describe('validateDistOutputTarget', () => { @@ -20,7 +20,7 @@ describe('validateDistOutputTarget', () => { }; userConfig.outputTargets = [outputTarget]; userConfig.buildDist = true; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); expect(config.outputTargets).toEqual([ { buildDir: path.join(rootDir, 'my-dist', 'my-build'), @@ -94,7 +94,7 @@ describe('validateDistOutputTarget', () => { it('should set defaults when outputTargets dist is empty', () => { userConfig.outputTargets = [{ type: 'dist' }]; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); const outputTarget = config.outputTargets.find((o) => o.type === 'dist') as d.OutputTargetDist; expect(outputTarget).toBeDefined(); expect(outputTarget.dir).toBe(path.join(rootDir, 'dist')); @@ -104,7 +104,7 @@ describe('validateDistOutputTarget', () => { it('should default to not add dist when outputTargets exists, but without dist', () => { userConfig.outputTargets = []; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); expect(config.outputTargets.some((o) => o.type === 'dist')).toBe(false); }); }); diff --git a/src/compiler/config/test/validate-output-www.spec.ts b/src/compiler/config/test/validate-output-www.spec.ts index ab82ecee410..46cac16cf3d 100644 --- a/src/compiler/config/test/validate-output-www.spec.ts +++ b/src/compiler/config/test/validate-output-www.spec.ts @@ -3,6 +3,7 @@ import { isOutputTargetCopy, isOutputTargetHydrate, isOutputTargetWww } from '.. import { validateConfig } from '../validate-config'; import path from 'path'; import { ConfigFlags } from '../../../cli/config-flags'; +import { mockLoadConfigInit } from '@stencil/core/testing'; describe('validateOutputTargetWww', () => { const rootDir = path.resolve('/'); @@ -24,7 +25,7 @@ describe('validateOutputTargetWww', () => { }; userConfig.outputTargets = [outputTarget]; userConfig.buildEs5 = false; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); expect(config.outputTargets).toEqual([ { @@ -92,7 +93,7 @@ describe('validateOutputTargetWww', () => { dir: path.join('www', 'docs'), }; userConfig.outputTargets = [outputTarget]; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); const www = config.outputTargets.find(isOutputTargetWww); expect(www.dir).toBe(path.join(rootDir, 'www', 'docs')); @@ -110,7 +111,7 @@ describe('validateOutputTargetWww', () => { empty: false, }; userConfig.outputTargets = [outputTarget]; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); const www = config.outputTargets.find(isOutputTargetWww); expect(www.type).toBe('www'); @@ -121,7 +122,7 @@ describe('validateOutputTargetWww', () => { }); it('should default to add www when outputTargets is undefined', () => { - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); expect(config.outputTargets).toHaveLength(5); const outputTarget = config.outputTargets.find(isOutputTargetWww); @@ -139,7 +140,7 @@ describe('validateOutputTargetWww', () => { baseUrl: '/docs', }; userConfig.outputTargets = [outputTarget]; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); const www = config.outputTargets.find(isOutputTargetWww); expect(www.type).toBe('www'); @@ -157,7 +158,7 @@ describe('validateOutputTargetWww', () => { baseUrl: '/docs', }; userConfig.outputTargets = [outputTarget]; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); const www = config.outputTargets.find(isOutputTargetWww); expect(www.type).toBe('www'); @@ -175,7 +176,7 @@ describe('validateOutputTargetWww', () => { baseUrl: 'https://example.com/docs', }; userConfig.outputTargets = [outputTarget]; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); const www = config.outputTargets.find(isOutputTargetWww); expect(www.type).toBe('www'); @@ -201,7 +202,7 @@ describe('validateOutputTargetWww', () => { ], }; userConfig.outputTargets = [outputTarget]; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); const copyTargets = config.outputTargets.filter(isOutputTargetCopy); expect(copyTargets).toEqual([ @@ -243,7 +244,7 @@ describe('validateOutputTargetWww', () => { ], }; userConfig.outputTargets = [outputTarget]; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); const copyTargets = config.outputTargets.filter(isOutputTargetCopy); expect(copyTargets).toEqual([ @@ -276,7 +277,7 @@ describe('validateOutputTargetWww', () => { copy: null, }; userConfig.outputTargets = [outputTarget]; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); const copyTargets = config.outputTargets.filter(isOutputTargetCopy); expect(copyTargets).toEqual([ @@ -296,7 +297,7 @@ describe('validateOutputTargetWww', () => { describe('dist-hydrate-script', () => { it('should not add hydrate by default', () => { - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); expect(config.outputTargets.some((o) => o.type === 'dist-hydrate-script')).toBe(false); expect(config.outputTargets.some((o) => o.type === 'www')).toBe(true); }); @@ -306,7 +307,7 @@ describe('validateOutputTargetWww', () => { type: 'www', }; userConfig.outputTargets = [wwwOutputTarget]; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); expect(config.outputTargets.some((o) => o.type === 'dist-hydrate-script')).toBe(false); expect(config.outputTargets.some((o) => o.type === 'www')).toBe(true); }); @@ -319,21 +320,21 @@ describe('validateOutputTargetWww', () => { type: 'dist-hydrate-script', }; userConfig.outputTargets = [wwwOutputTarget, hydrateOutputTarget]; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); expect(config.outputTargets.some((o) => o.type === 'dist-hydrate-script')).toBe(true); expect(config.outputTargets.some((o) => o.type === 'www')).toBe(true); }); it('should add hydrate with --prerender flag', () => { userConfig.flags = { ...flags, prerender: true }; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); expect(config.outputTargets.some((o) => o.type === 'dist-hydrate-script')).toBe(true); expect(config.outputTargets.some((o) => o.type === 'www')).toBe(true); }); it('should add hydrate with --ssr flag', () => { userConfig.flags = { ...flags, ssr: true }; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); expect(config.outputTargets.some((o) => o.type === 'dist-hydrate-script')).toBe(true); expect(config.outputTargets.some((o) => o.type === 'www')).toBe(true); }); @@ -344,7 +345,7 @@ describe('validateOutputTargetWww', () => { external: ['lodash', 'left-pad'], }; userConfig.outputTargets = [hydrateOutputTarget]; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); const o = config.outputTargets.find(isOutputTargetHydrate); expect(o.external).toContain('lodash'); expect(o.external).toContain('left-pad'); @@ -356,7 +357,7 @@ describe('validateOutputTargetWww', () => { it('should add node builtins to external by default', () => { userConfig.flags = { ...flags, prerender: true }; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); const o = config.outputTargets.find(isOutputTargetHydrate); expect(o.external).toContain('fs'); expect(o.external).toContain('path'); diff --git a/src/compiler/config/test/validate-paths.spec.ts b/src/compiler/config/test/validate-paths.spec.ts index 9c3500705fc..9e59466d44d 100644 --- a/src/compiler/config/test/validate-paths.spec.ts +++ b/src/compiler/config/test/validate-paths.spec.ts @@ -1,5 +1,5 @@ import type * as d from '@stencil/core/declarations'; -import { mockLogger, mockCompilerSystem } from '@stencil/core/testing'; +import { mockLogger, mockCompilerSystem, mockLoadConfigInit } from '@stencil/core/testing'; import { validateConfig } from '../validate-config'; import path from 'path'; @@ -21,23 +21,23 @@ describe('validatePaths', () => { it('should set absolute cacheDir', () => { userConfig.cacheDir = path.join(ROOT, 'some', 'custom', 'cache'); - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); expect(config.cacheDir).toBe(path.join(ROOT, 'some', 'custom', 'cache')); }); it('should set relative cacheDir', () => { userConfig.cacheDir = 'custom-cache'; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); expect(config.cacheDir).toBe(path.join(ROOT, 'User', 'my-app', 'custom-cache')); }); it('should set default cacheDir', () => { - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); expect(config.cacheDir).toBe(path.join(ROOT, 'User', 'my-app', '.stencil')); }); it('should set default wwwIndexHtml and convert to absolute path', () => { - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); expect(path.basename((config.outputTargets as d.OutputTargetWww[])[0].indexHtml)).toBe('index.html'); expect(path.isAbsolute((config.outputTargets as d.OutputTargetWww[])[0].indexHtml)).toBe(true); }); @@ -49,13 +49,13 @@ describe('validatePaths', () => { indexHtml: path.join('assets', 'custom-index.html'), }, ] as d.OutputTargetWww[]; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); expect(path.basename((config.outputTargets as d.OutputTargetWww[])[0].indexHtml)).toBe('custom-index.html'); expect(path.isAbsolute((config.outputTargets as d.OutputTargetWww[])[0].indexHtml)).toBe(true); }); it('should set default indexHtmlSrc and convert to absolute path', () => { - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); expect(path.basename(config.srcIndexHtml)).toBe('index.html'); expect(path.isAbsolute(config.srcIndexHtml)).toBe(true); }); @@ -67,12 +67,12 @@ describe('validatePaths', () => { empty: false, }, ] as d.OutputTargetWww[]; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); expect((config.outputTargets as d.OutputTargetWww[])[0].empty).toBe(false); }); it('should set default emptyWWW to true', () => { - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); expect((config.outputTargets as d.OutputTargetWww[])[0].empty).toBe(true); }); @@ -83,7 +83,7 @@ describe('validatePaths', () => { empty: false, }, ] as d.OutputTargetWww[]; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); expect((config.outputTargets as d.OutputTargetWww[])[0].empty).toBe(false); }); @@ -93,7 +93,7 @@ describe('validatePaths', () => { type: 'dist', }, ]; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); expect(path.basename((config.outputTargets as d.OutputTargetDist[])[0].collectionDir)).toBe('collection'); expect(path.isAbsolute((config.outputTargets as d.OutputTargetDist[])[0].collectionDir)).toBe(true); }); @@ -104,13 +104,13 @@ describe('validatePaths', () => { type: 'dist', }, ]; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); expect(path.basename((config.outputTargets as d.OutputTargetDist[])[0].typesDir)).toBe('types'); expect(path.isAbsolute((config.outputTargets as d.OutputTargetDist[])[0].typesDir)).toBe(true); }); it('should set default build dir and convert to absolute path', () => { - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); const normalizedPathSep = path.sep; const parts = (config.outputTargets as d.OutputTargetDist[])[0].buildDir.split(normalizedPathSep); expect(parts[parts.length - 1]).toBe('build'); @@ -125,7 +125,7 @@ describe('validatePaths', () => { dir: 'custom-www', }, ] as d.OutputTargetWww[]; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); const normalizedPathSep = path.sep; const parts = (config.outputTargets as d.OutputTargetDist[])[0].buildDir.split(normalizedPathSep); expect(parts[parts.length - 1]).toBe('build'); @@ -134,28 +134,28 @@ describe('validatePaths', () => { }); it('should set default src dir and convert to absolute path', () => { - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); expect(path.basename(config.srcDir)).toBe('src'); expect(path.isAbsolute(config.srcDir)).toBe(true); }); it('should set src dir and convert to absolute path', () => { userConfig.srcDir = 'app'; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); expect(path.basename(config.srcDir)).toBe('app'); expect(path.isAbsolute(config.srcDir)).toBe(true); }); it('should convert globalScript to absolute path, if a globalScript property was provided', () => { userConfig.globalScript = path.join('src', 'global', 'index.ts'); - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); expect(path.basename(config.globalScript)).toBe('index.ts'); expect(path.isAbsolute(config.globalScript)).toBe(true); }); it('should convert globalStyle string to absolute path array, if a globalStyle property was provided', () => { userConfig.globalStyle = path.join('src', 'global', 'styles.css'); - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); expect(path.basename(config.globalStyle)).toBe('styles.css'); expect(path.isAbsolute(config.globalStyle)).toBe(true); }); diff --git a/src/compiler/config/test/validate-service-worker.spec.ts b/src/compiler/config/test/validate-service-worker.spec.ts index 93b01d56f62..590819248fa 100644 --- a/src/compiler/config/test/validate-service-worker.spec.ts +++ b/src/compiler/config/test/validate-service-worker.spec.ts @@ -1,18 +1,22 @@ import type * as d from '@stencil/core/declarations'; import { OutputTargetWww } from '@stencil/core/declarations'; -import { mockCompilerSystem } from '@stencil/core/testing'; +import { mockCompilerSystem, mockLogger } from '@stencil/core/testing'; import { validateServiceWorker } from '../validate-service-worker'; describe('validateServiceWorker', () => { - const config: d.ValidatedConfig = { - fsNamespace: 'app', - sys: mockCompilerSystem(), - devMode: false, - flags: {}, - }; - + let config: d.ValidatedConfig; let outputTarget: d.OutputTargetWww; + beforeEach(() => { + config = { + fsNamespace: 'app', + sys: mockCompilerSystem(), + devMode: false, + flags: {}, + logger: mockLogger(), + }; + }); + /** * A little util to work around a typescript annoyance. Because * `outputTarget.serviceWorker` is typed as @@ -126,15 +130,6 @@ describe('validateServiceWorker', () => { expect(outputTarget.serviceWorker).toBe(null); }); - it('should not create default sw config when not www type', () => { - outputTarget = { - type: 'www', - appDir: '/www', - }; - validateServiceWorker(config, outputTarget); - expect(outputTarget.serviceWorker).toBe(null); - }); - it('should create default sw config when true boolean, even if devMode', () => { outputTarget = { type: 'www', diff --git a/src/compiler/config/test/validate-stats.spec.ts b/src/compiler/config/test/validate-stats.spec.ts index 767035cd26e..a263fd6d989 100644 --- a/src/compiler/config/test/validate-stats.spec.ts +++ b/src/compiler/config/test/validate-stats.spec.ts @@ -1,5 +1,5 @@ import type * as d from '@stencil/core/declarations'; -import { mockConfig } from '@stencil/core/testing'; +import { mockConfig, mockLoadConfigInit } from '@stencil/core/testing'; import { validateConfig } from '../validate-config'; describe('validateStats', () => { @@ -12,7 +12,7 @@ describe('validateStats', () => { it('adds stats from flags, w/ no outputTargets', () => { userConfig.flags = { ...(userConfig.flags ?? {}), stats: true }; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); const o = config.outputTargets.find((o) => o.type === 'stats') as d.OutputTargetStats; expect(o).toBeDefined(); expect(o.file).toContain('stencil-stats.json'); @@ -25,7 +25,7 @@ describe('validateStats', () => { file: 'custom-path.json', } as d.OutputTargetStats, ]; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); const o = config.outputTargets.find((o) => o.type === 'stats') as d.OutputTargetStats; expect(o).toBeDefined(); expect(o.file).toContain('custom-path.json'); @@ -37,14 +37,14 @@ describe('validateStats', () => { type: 'stats', }, ]; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); const o = config.outputTargets.find((o) => o.type === 'stats') as d.OutputTargetStats; expect(o).toBeDefined(); expect(o.file).toContain('stencil-stats.json'); }); it('default no stats', () => { - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); expect(config.outputTargets.some((o) => o.type === 'stats')).toBe(false); }); }); diff --git a/src/compiler/config/test/validate-testing.spec.ts b/src/compiler/config/test/validate-testing.spec.ts index 99d7238f04e..4dde7974378 100644 --- a/src/compiler/config/test/validate-testing.spec.ts +++ b/src/compiler/config/test/validate-testing.spec.ts @@ -1,5 +1,5 @@ import type * as d from '@stencil/core/declarations'; -import { mockLogger, mockCompilerSystem } from '@stencil/core/testing'; +import { mockLogger, mockCompilerSystem, mockLoadConfigInit } from '@stencil/core/testing'; import { validateConfig } from '../validate-config'; import path from 'path'; import { ConfigFlags } from '../../../cli/config-flags'; @@ -32,31 +32,31 @@ describe('validateTesting', () => { it('set headless false w/ flag', () => { userConfig.flags = { ...flags, e2e: true, headless: false }; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); expect(config.testing.browserHeadless).toBe(false); }); it('set headless true w/ flag', () => { userConfig.flags = { ...flags, e2e: true, headless: true }; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); expect(config.testing.browserHeadless).toBe(true); }); it('default headless true', () => { userConfig.flags = { ...flags, e2e: true }; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); expect(config.testing.browserHeadless).toBe(true); }); it('force headless with ci flag', () => { userConfig.flags = { ...flags, ci: true, e2e: true, headless: false }; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); expect(config.testing.browserHeadless).toBe(true); }); it('default to no-sandbox browser args with ci flag', () => { userConfig.flags = { ...flags, ci: true, e2e: true }; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); expect(config.testing.browserArgs).toEqual([ '--font-render-hinting=medium', '--incognito', @@ -68,13 +68,13 @@ describe('validateTesting', () => { it('default browser args', () => { userConfig.flags = { ...flags, e2e: true }; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); expect(config.testing.browserArgs).toEqual(['--font-render-hinting=medium', '--incognito']); }); it('set default testPathIgnorePatterns', () => { userConfig.flags = { ...flags, e2e: true }; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); expect(config.testing.testPathIgnorePatterns).toEqual([ path.join(ROOT, 'User', 'some', 'path', '.vscode'), path.join(ROOT, 'User', 'some', 'path', '.stencil'), @@ -90,7 +90,7 @@ describe('validateTesting', () => { { type: 'www', dir: 'www-folder' }, { type: 'docs-readme', dir: 'docs' }, ]; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); expect(config.testing.testPathIgnorePatterns).toEqual([ path.join(ROOT, 'User', 'some', 'path', '.vscode'), path.join(ROOT, 'User', 'some', 'path', '.stencil'), @@ -105,7 +105,7 @@ describe('validateTesting', () => { userConfig.testing = { testEnvironment: './rel-path.js', }; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); expect(path.isAbsolute(config.testing.testEnvironment)).toBe(true); expect(path.basename(config.testing.testEnvironment)).toEqual('rel-path.js'); }); @@ -115,12 +115,12 @@ describe('validateTesting', () => { userConfig.testing = { testEnvironment: 'jsdom', }; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); expect(config.testing.testEnvironment).toEqual('jsdom'); }); it('do nothing for empty testEnvironment', () => { - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); expect(config.testing.testEnvironment).toBeUndefined(); }); @@ -130,7 +130,7 @@ describe('validateTesting', () => { beforeEach(() => { userConfig.flags = { ...flags, spec: true }; - const { testing: testConfig } = validateConfig(userConfig).config; + const { testing: testConfig } = validateConfig(userConfig, mockLoadConfigInit()).config; const testRegexSetting = testConfig?.testRegex; if (!testRegexSetting) { diff --git a/src/compiler/config/test/validate-workers.spec.ts b/src/compiler/config/test/validate-workers.spec.ts index 07d98f87370..f1c1e472199 100644 --- a/src/compiler/config/test/validate-workers.spec.ts +++ b/src/compiler/config/test/validate-workers.spec.ts @@ -1,6 +1,6 @@ import type * as d from '@stencil/core/declarations'; import { validateConfig } from '../validate-config'; -import { mockLogger } from '@stencil/core/testing'; +import { mockLoadConfigInit, mockLogger } from '@stencil/core/testing'; import path from 'path'; describe('validate-workers', () => { @@ -20,7 +20,7 @@ describe('validate-workers', () => { it('set maxConcurrentWorkers, but dont let it go under 0', () => { userConfig.maxConcurrentWorkers = -1; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); expect(config.maxConcurrentWorkers).toBe(0); }); @@ -29,7 +29,7 @@ describe('validate-workers', () => { ci: true, }; userConfig.maxConcurrentWorkers = 2; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); expect(config.maxConcurrentWorkers).toBe(4); }); @@ -38,13 +38,13 @@ describe('validate-workers', () => { maxWorkers: 1, }; userConfig.maxConcurrentWorkers = 4; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); expect(config.maxConcurrentWorkers).toBe(1); }); it('set maxConcurrentWorkers', () => { userConfig.maxConcurrentWorkers = 4; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); expect(config.maxConcurrentWorkers).toBe(4); }); }); diff --git a/src/compiler/config/validate-config.ts b/src/compiler/config/validate-config.ts index 2d725b738bb..0b1784a84a4 100644 --- a/src/compiler/config/validate-config.ts +++ b/src/compiler/config/validate-config.ts @@ -1,4 +1,4 @@ -import { ConfigBundle, Diagnostic, ValidatedConfig, UnvalidatedConfig } from '../../declarations'; +import { ConfigBundle, Diagnostic, ValidatedConfig, UnvalidatedConfig, LoadConfigInit } from '../../declarations'; import { buildError, isBoolean, isNumber, isString, sortBy } from '@utils'; import { setBooleanConfig } from './config-utils'; import { validateDevServer } from './validate-dev-server'; @@ -11,6 +11,7 @@ import { validatePlugins } from './validate-plugins'; import { validateRollupConfig } from './validate-rollup-config'; import { validateTesting } from './validate-testing'; import { validateWorkers } from './validate-workers'; +import { createLogger } from '../sys/logger/console-logger'; /** * Represents the results of validating a previously unvalidated configuration @@ -32,16 +33,24 @@ type ConfigValidationResults = { * `UnvalidatedConfig` to a `Config`. * * @param userConfig an unvalidated config that we've gotten from a user + * @param bootstrapConfig the initial configuration provided by the user (or generated by Stencil) used to bootstrap + * configuration loading and validation * @returns an object with config and diagnostics props */ -export const validateConfig = (userConfig: UnvalidatedConfig = {}): ConfigValidationResults => { +export const validateConfig = ( + userConfig: UnvalidatedConfig = {}, + bootstrapConfig: LoadConfigInit +): ConfigValidationResults => { const config = Object.assign({}, userConfig || {}); // not positive it's json safe const diagnostics: Diagnostic[] = []; + const logger = bootstrapConfig.logger || config.logger || createLogger(); + const validatedConfig: ValidatedConfig = { ...config, // flags _should_ be JSON safe flags: JSON.parse(JSON.stringify(config.flags || {})), + logger, }; // default devMode false diff --git a/src/compiler/output-targets/test/build-conditionals.spec.ts b/src/compiler/output-targets/test/build-conditionals.spec.ts index 1acac251482..3f5bf503208 100644 --- a/src/compiler/output-targets/test/build-conditionals.spec.ts +++ b/src/compiler/output-targets/test/build-conditionals.spec.ts @@ -1,7 +1,7 @@ import type * as d from '../../../declarations'; import { getLazyBuildConditionals } from '../dist-lazy/lazy-build-conditionals'; import { getCustomElementsBuildConditionals } from '../dist-custom-elements-bundle/custom-elements-build-conditionals'; -import { mockConfig } from '@stencil/core/testing'; +import { mockConfig, mockLoadConfigInit } from '@stencil/core/testing'; import { validateConfig } from '../../config/validate-config'; describe('build-conditionals', () => { @@ -16,7 +16,7 @@ describe('build-conditionals', () => { describe('getCustomElementsBuildConditionals', () => { it('taskQueue async', () => { userConfig.taskQueue = 'async'; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); const bc = getCustomElementsBuildConditionals(config, cmps); expect(bc.asyncQueue).toBe(false); expect(bc.taskQueue).toBe(true); @@ -25,7 +25,7 @@ describe('build-conditionals', () => { it('taskQueue immediate', () => { userConfig.taskQueue = 'immediate'; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); const bc = getCustomElementsBuildConditionals(config, cmps); expect(bc.asyncQueue).toBe(false); expect(bc.taskQueue).toBe(false); @@ -34,7 +34,7 @@ describe('build-conditionals', () => { it('taskQueue congestionAsync', () => { userConfig.taskQueue = 'congestionAsync'; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); const bc = getCustomElementsBuildConditionals(config, cmps); expect(bc.asyncQueue).toBe(true); expect(bc.taskQueue).toBe(true); @@ -42,7 +42,7 @@ describe('build-conditionals', () => { }); it('taskQueue defaults', () => { - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); const bc = getCustomElementsBuildConditionals(config, cmps); expect(bc.asyncQueue).toBe(false); expect(bc.taskQueue).toBe(true); @@ -53,7 +53,7 @@ describe('build-conditionals', () => { describe('getLazyBuildConditionals', () => { it('taskQueue async', () => { userConfig.taskQueue = 'async'; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); const bc = getLazyBuildConditionals(config, cmps); expect(bc.asyncQueue).toBe(false); expect(bc.taskQueue).toBe(true); @@ -62,7 +62,7 @@ describe('build-conditionals', () => { it('taskQueue immediate', () => { userConfig.taskQueue = 'immediate'; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); const bc = getLazyBuildConditionals(config, cmps); expect(bc.asyncQueue).toBe(false); expect(bc.taskQueue).toBe(false); @@ -71,7 +71,7 @@ describe('build-conditionals', () => { it('taskQueue congestionAsync', () => { userConfig.taskQueue = 'congestionAsync'; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); const bc = getLazyBuildConditionals(config, cmps); expect(bc.asyncQueue).toBe(true); expect(bc.taskQueue).toBe(true); @@ -79,7 +79,7 @@ describe('build-conditionals', () => { }); it('taskQueue defaults', () => { - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); const bc = getLazyBuildConditionals(config, cmps); expect(bc.asyncQueue).toBe(false); expect(bc.taskQueue).toBe(true); @@ -87,14 +87,14 @@ describe('build-conditionals', () => { }); it('tagNameTransform default', () => { - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); const bc = getLazyBuildConditionals(config, cmps); expect(bc.transformTagName).toBe(false); }); it('tagNameTransform true', () => { userConfig.extras = { tagNameTransform: true }; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); const bc = getLazyBuildConditionals(config, cmps); expect(bc.transformTagName).toBe(true); }); diff --git a/src/compiler/service-worker/test/service-worker-util.spec.ts b/src/compiler/service-worker/test/service-worker-util.spec.ts index 3268b19c790..77903ea5a6c 100644 --- a/src/compiler/service-worker/test/service-worker-util.spec.ts +++ b/src/compiler/service-worker/test/service-worker-util.spec.ts @@ -1,7 +1,7 @@ import type * as d from '@stencil/core/declarations'; import { generateServiceWorkerUrl } from '../service-worker-util'; import { validateConfig } from '../../config/validate-config'; -import { mockConfig } from '@stencil/core/testing'; +import { mockConfig, mockLoadConfigInit } from '@stencil/core/testing'; describe('generateServiceWorkerUrl', () => { let userConfig: d.Config; @@ -16,7 +16,7 @@ describe('generateServiceWorkerUrl', () => { baseUrl: '/docs', } as d.OutputTargetWww, ]; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); outputTarget = config.outputTargets[0] as d.OutputTargetWww; const swUrl = generateServiceWorkerUrl(outputTarget, outputTarget.serviceWorker as d.ServiceWorkerConfig); expect(swUrl).toBe('/docs/sw.js'); @@ -25,7 +25,7 @@ describe('generateServiceWorkerUrl', () => { it('default sw url', () => { userConfig = mockConfig(); userConfig.devMode = false; - const { config } = validateConfig(userConfig); + const { config } = validateConfig(userConfig, mockLoadConfigInit()); outputTarget = config.outputTargets[0] as d.OutputTargetWww; const swUrl = generateServiceWorkerUrl(outputTarget, outputTarget.serviceWorker as d.ServiceWorkerConfig); expect(swUrl).toBe('/sw.js'); diff --git a/src/compiler/style/test/style-rebuild.spec.ts b/src/compiler/style/test/style-rebuild.spec.ts index 94b6985911f..172b649c52f 100644 --- a/src/compiler/style/test/style-rebuild.spec.ts +++ b/src/compiler/style/test/style-rebuild.spec.ts @@ -2,7 +2,7 @@ // TODO(STENCIL-487): Investigate reviving this test file import type * as d from '@stencil/core/declarations'; import { createCompiler } from '@stencil/core/compiler'; -import { mockCompilerSystem } from '@stencil/core/testing'; +import { mockCompilerSystem, mockLoadConfigInit } from '@stencil/core/testing'; import path from 'path'; import { validateConfig } from '../../config/validate-config'; @@ -34,10 +34,13 @@ xdescribe('component-styles', () => { ` ); - const { config } = validateConfig({ - rootDir: '/', - tsconfig: '/tsconfig.json', - }); + const { config } = validateConfig( + { + rootDir: '/', + tsconfig: '/tsconfig.json', + }, + mockLoadConfigInit() + ); config.sys = sys; compiler = await createCompiler(config); diff --git a/src/compiler/sys/config.ts b/src/compiler/sys/config.ts index aa5a3383ce1..70f85675feb 100644 --- a/src/compiler/sys/config.ts +++ b/src/compiler/sys/config.ts @@ -4,11 +4,10 @@ import { createSystem } from './stencil-sys'; import { setPlatformPath } from '../sys/modules/path'; export const getConfig = (userConfig: d.Config): d.ValidatedConfig => { - const config: d.ValidatedConfig = { ...userConfig, flags: { ...(userConfig.flags ?? {}) } }; + const flags = userConfig.flags ?? {}; + const logger = userConfig.logger ?? createLogger(); + const config: d.ValidatedConfig = { ...userConfig, flags, logger }; - if (!config.logger) { - config.logger = createLogger(); - } if (!config.sys) { config.sys = createSystem({ logger: config.logger }); } diff --git a/src/compiler/sys/logger/console-logger.ts b/src/compiler/sys/logger/console-logger.ts index f5af8b1161c..f68ddc7cb8c 100644 --- a/src/compiler/sys/logger/console-logger.ts +++ b/src/compiler/sys/logger/console-logger.ts @@ -1,11 +1,15 @@ import type * as d from '../../../declarations'; import { IS_BROWSER_ENV } from '../environment'; -export const createLogger = () => { +/** + * Creates an instance of a logger + * @returns the new logger instance + */ +export const createLogger = (): d.Logger => { let useColors = IS_BROWSER_ENV; let level: d.LogLevel = 'info'; - const logger: d.Logger = { + return { enableColors: (uc) => (useColors = uc), getLevel: () => level, setLevel: (l) => (level = l), @@ -32,7 +36,6 @@ export const createLogger = () => { diagnostics.forEach((diagnostic) => logDiagnostic(diagnostic, useColors)); }, }; - return logger; }; const logDiagnostic = (diagnostic: d.Diagnostic, useColors: boolean) => { diff --git a/src/declarations/stencil-public-compiler.ts b/src/declarations/stencil-public-compiler.ts index 4bd3427735d..9856924e0c3 100644 --- a/src/declarations/stencil-public-compiler.ts +++ b/src/declarations/stencil-public-compiler.ts @@ -409,7 +409,7 @@ type RequireFields = T & { [P in K]-?: T[P] }; /** * Fields in {@link Config} to make required for {@link ValidatedConfig} */ -type StrictConfigFields = 'flags'; +type StrictConfigFields = 'flags' | 'logger'; /** * A version of {@link Config} that makes certain fields required. This type represents a valid configuration entity. diff --git a/src/dev-server/test/req-handler.spec.ts b/src/dev-server/test/req-handler.spec.ts index 5a9eb933904..14e95294e01 100644 --- a/src/dev-server/test/req-handler.spec.ts +++ b/src/dev-server/test/req-handler.spec.ts @@ -3,7 +3,7 @@ import { appendDevServerClientIframe } from '../serve-file'; import { createRequestHandler } from '../request-handler'; import { createServerContext } from '../server-context'; import { createSystem } from '../../compiler/sys/stencil-sys'; -import { mockConfig } from '@stencil/core/testing'; +import { mockConfig, mockLoadConfigInit } from '@stencil/core/testing'; import { normalizePath } from '@utils'; import { validateConfig } from '../../compiler/config/validate-config'; import { validateDevServer } from '../../compiler/config/validate-dev-server'; @@ -25,7 +25,7 @@ describe('request-handler', () => { beforeEach(async () => { sys = createSystem(); - const validated = validateConfig(mockConfig()); + const validated = validateConfig(mockConfig(), mockLoadConfigInit()); const stencilConfig = validated.config; stencilConfig.flags.serve = true; diff --git a/src/testing/index.ts b/src/testing/index.ts index ec7ba6606c3..6c35dd1530f 100644 --- a/src/testing/index.ts +++ b/src/testing/index.ts @@ -8,6 +8,7 @@ export { mockConfig, mockCompilerCtx, mockDocument, + mockLoadConfigInit, mockValidatedConfig, mockLogger, mockCompilerSystem, diff --git a/src/testing/mocks.ts b/src/testing/mocks.ts index 8af4228e2ee..2b10fd213d9 100644 --- a/src/testing/mocks.ts +++ b/src/testing/mocks.ts @@ -4,6 +4,7 @@ import type { CompilerCtx, CompilerSystem, Config, + LoadConfigInit, ValidatedConfig, Module, UnvalidatedConfig, @@ -29,7 +30,7 @@ import { buildEvents } from '../compiler/events'; export function mockValidatedConfig(sys?: CompilerSystem): ValidatedConfig { const baseConfig = mockConfig(sys); - return { ...baseConfig, flags: {} }; + return { ...baseConfig, flags: {}, logger: mockLogger() }; } // TODO(STENCIL-486): Update `mockConfig` to accept any property found on `UnvalidatedConfig` @@ -82,6 +83,28 @@ export function mockConfig(sys?: CompilerSystem): UnvalidatedConfig { }; } +/** + * Creates a configuration object used to bootstrap a Stencil task invocation + * + * Several fields are intentionally undefined for this entity. While it would be trivial to stub them out, this mock + * generation function operates under the assumption that entities like loggers and compiler system abstractions will + * be shared by multiple entities in a test suite, who should provide those entities to this function + * + * @param overrides the properties on the default entity to manually override + * @returns the default configuration initialization object, with any overrides applied + */ +export const mockLoadConfigInit = (overrides?: Partial): LoadConfigInit => { + const defaults: LoadConfigInit = { + config: {}, + configPath: undefined, + initTsConfig: true, + logger: undefined, + sys: undefined, + }; + + return { ...defaults, ...overrides }; +}; + export function mockCompilerCtx(config?: Config) { if (!config) { config = mockConfig(); diff --git a/src/testing/testing.ts b/src/testing/testing.ts index eb6b93d6f66..6b29e80f034 100644 --- a/src/testing/testing.ts +++ b/src/testing/testing.ts @@ -2,7 +2,6 @@ import type { CompilerBuildResults, Compiler, CompilerWatcher, - Config, DevServer, E2EProcessEnv, ValidatedConfig, @@ -184,8 +183,16 @@ export const createTesting = async (config: ValidatedConfig): Promise = }; }; -function setupTestingConfig(config: Config): ValidatedConfig { - const validatedConfig: ValidatedConfig = { ...config, flags: { ...config.flags } }; +/** + * Create a Stencil configuration for testing purposes. + * + * This function accepts an internal, validated configuration entity and modifies fields on the object to be more + * conducive to testing. + * + * @param validatedConfig the configuration to modify + * @returns the modified testing configuration + */ +function setupTestingConfig(validatedConfig: ValidatedConfig): ValidatedConfig { validatedConfig.buildEs5 = false; validatedConfig.devMode = true; validatedConfig.minifyCss = false;