Skip to content

Commit

Permalink
Covert some of the config testing to baselines for easy validation (#…
Browse files Browse the repository at this point in the history
…51063)

* Baseline config tests for easy validation

* Refactor

* Fix incorrect pick

* Dont print unnecessary plugin host not implemented msg in logs
  • Loading branch information
sheetalkamat committed Oct 5, 2022
1 parent fc5e72b commit 43c6fd4
Show file tree
Hide file tree
Showing 635 changed files with 42,505 additions and 42,961 deletions.
22 changes: 11 additions & 11 deletions src/server/project.ts
Expand Up @@ -1605,6 +1605,7 @@ namespace ts.server {
}

protected enableGlobalPlugins(options: CompilerOptions, pluginConfigOverrides: Map<any> | undefined): void {
if (!this.projectService.globalPlugins.length) return;
const host = this.projectService.host;

if (!host.require && !host.importPlugin) {
Expand All @@ -1619,20 +1620,18 @@ namespace ts.server {
combinePaths(this.projectService.getExecutingFilePath(), "../../.."),
];

if (this.projectService.globalPlugins) {
// Enable global plugins with synthetic configuration entries
for (const globalPluginName of this.projectService.globalPlugins) {
// Skip empty names from odd commandline parses
if (!globalPluginName) continue;
// Enable global plugins with synthetic configuration entries
for (const globalPluginName of this.projectService.globalPlugins) {
// Skip empty names from odd commandline parses
if (!globalPluginName) continue;

// Skip already-locally-loaded plugins
if (options.plugins && options.plugins.some(p => p.name === globalPluginName)) continue;
// Skip already-locally-loaded plugins
if (options.plugins && options.plugins.some(p => p.name === globalPluginName)) continue;

// Provide global: true so plugins can detect why they can't find their config
this.projectService.logger.info(`Loading global plugin ${globalPluginName}`);
// Provide global: true so plugins can detect why they can't find their config
this.projectService.logger.info(`Loading global plugin ${globalPluginName}`);

this.enablePlugin({ name: globalPluginName, global: true } as PluginImport, searchPaths, pluginConfigOverrides);
}
this.enablePlugin({ name: globalPluginName, global: true } as PluginImport, searchPaths, pluginConfigOverrides);
}
}

Expand Down Expand Up @@ -2521,6 +2520,7 @@ namespace ts.server {

/*@internal*/
enablePluginsWithOptions(options: CompilerOptions, pluginConfigOverrides: ESMap<string, any> | undefined): void {
if (!options.plugins?.length && !this.projectService.globalPlugins.length) return;
const host = this.projectService.host;
if (!host.require && !host.importPlugin) {
this.projectService.logger.info("Plugins were requested but not running in environment that supports 'require'. Nothing will be loaded");
Expand Down
1,107 changes: 147 additions & 960 deletions src/testRunner/unittests/config/commandLineParsing.ts

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/testRunner/unittests/config/initializeTSConfig.ts
Expand Up @@ -4,7 +4,7 @@ namespace ts {
describe(name, () => {
const commandLine = parseCommandLine(commandLinesArgs);
const initResult = generateTSConfig(commandLine.options, commandLine.fileNames, "\n");
const outputFileName = `tsConfig/${name.replace(/[^a-z0-9\-. ]/ig, "")}/tsconfig.json`;
const outputFileName = `config/initTSConfig/${name.replace(/[^a-z0-9\-. ]/ig, "")}/tsconfig.json`;

it(`Correct output for ${outputFileName}`, () => {
Harness.Baseline.runBaseline(outputFileName, initResult, { PrintDiff: true });
Expand Down
2 changes: 1 addition & 1 deletion src/testRunner/unittests/config/showConfig.ts
Expand Up @@ -2,7 +2,7 @@ namespace ts {
describe("unittests:: config:: showConfig", () => {
function showTSConfigCorrectly(name: string, commandLinesArgs: string[], configJson?: object) {
describe(name, () => {
const outputFileName = `showConfig/${name.replace(/[^a-z0-9\-./ ]/ig, "")}/tsconfig.json`;
const outputFileName = `config/showConfig/${name.replace(/[^a-z0-9\-./ ]/ig, "")}/tsconfig.json`;

it(`Correct output for ${outputFileName}`, () => {
const cwd = `/${name}`;
Expand Down
274 changes: 108 additions & 166 deletions src/testRunner/unittests/config/tsconfigParsingWatchOptions.ts
Expand Up @@ -42,190 +42,132 @@ namespace ts {

interface VerifyWatchOptions {
json: object;
expectedOptions: WatchOptions | undefined;
additionalFiles?: vfs.FileSet;
existingWatchOptions?: WatchOptions | undefined;
expectedErrors?: (sourceFile?: SourceFile) => Diagnostic[];
}

function verifyWatchOptions(scenario: () => VerifyWatchOptions[]) {
it("with json api", () => {
for (const { json, expectedOptions, additionalFiles, existingWatchOptions, expectedErrors } of scenario()) {
const parsed = getParsedCommandJson(json, additionalFiles, existingWatchOptions);
assert.deepEqual(parsed.watchOptions, expectedOptions, `With ${JSON.stringify(json)}`);
if (length(parsed.errors)) {
assert.deepEqual(parsed.errors, expectedErrors?.());
function verifyWatchOptions(subScenario: string, scenario: () => VerifyWatchOptions[]) {
describe(subScenario, () => {
it("with json api", () => {
const baseline: string[] = [];
for (const { json, additionalFiles, existingWatchOptions } of scenario()) {
addToBaseLine(baseline, json, getParsedCommandJson(json, additionalFiles, existingWatchOptions));
}
else {
assert.equal(0, length(expectedErrors?.()), `Expected no errors`);
}
}
});
runBaseline(`${subScenario} with json api`, baseline);
});

it("with json source file api", () => {
for (const { json, expectedOptions, additionalFiles, existingWatchOptions, expectedErrors } of scenario()) {
const parsed = getParsedCommandJsonNode(json, additionalFiles, existingWatchOptions);
assert.deepEqual(parsed.watchOptions, expectedOptions);
if (length(parsed.errors)) {
assert.deepEqual(parsed.errors, expectedErrors?.(parsed.options.configFile));
}
else {
assert.equal(0, length(expectedErrors?.(parsed.options.configFile)), `Expected no errors`);
it("with json source file api", () => {
const baseline: string[] = [];
for (const { json, additionalFiles, existingWatchOptions, } of scenario()) {
addToBaseLine(baseline, json, getParsedCommandJsonNode(json, additionalFiles, existingWatchOptions));
}
}
runBaseline(`${subScenario} with jsonSourceFile api`, baseline);
});
});
function addToBaseLine(baseline: string[], json: object, parsed: ParsedCommandLine) {
baseline.push(`Input:: ${JSON.stringify(json, /*replacer*/ undefined, " ")}`);
baseline.push(`Result: WatchOptions::`);
baseline.push(JSON.stringify(parsed.watchOptions, /*replacer*/ undefined, " "));
baseline.push(`Result: Errors::`);
baseline.push(formatDiagnosticsWithColorAndContext(parsed.errors, {
getCurrentDirectory: () => "/",
getCanonicalFileName: identity,
getNewLine: () => "\n"
}));
}
function runBaseline(subScenario: string, baseline: readonly string[]) {
Harness.Baseline.runBaseline(`config/tsconfigParsingWatchOptions/${subScenario}.js`, baseline.join("\n"));
}
}

describe("no watchOptions specified option", () => {
verifyWatchOptions(() => [{
json: {},
expectedOptions: undefined
}]);
});
verifyWatchOptions("no watchOptions specified option", () => [{
json: {},
}]);

describe("empty watchOptions specified option", () => {
verifyWatchOptions(() => [{
json: { watchOptions: {} },
expectedOptions: undefined
}]);
});
verifyWatchOptions("empty watchOptions specified option", () => [{
json: { watchOptions: {} },
}]);

describe("extending config file", () => {
describe("when extending config file without watchOptions", () => {
verifyWatchOptions(() => [
{
json: {
extends: "./base.json",
watchOptions: { watchFile: "UseFsEvents" }
},
expectedOptions: { watchFile: WatchFileKind.UseFsEvents },
additionalFiles: { "/base.json": "{}" }
},
{
json: { extends: "./base.json", },
expectedOptions: undefined,
additionalFiles: { "/base.json": "{}" }
}
]);
});
verifyWatchOptions("when extending config file without watchOptions", () => [
{
json: {
extends: "./base.json",
watchOptions: { watchFile: "UseFsEvents" }
},
additionalFiles: { "/base.json": "{}" }
},
{
json: { extends: "./base.json", },
additionalFiles: { "/base.json": "{}" }
}
]);

describe("when extending config file with watchOptions", () => {
verifyWatchOptions(() => [
{
json: {
extends: "./base.json",
watchOptions: {
watchFile: "UseFsEvents",
}
},
expectedOptions: {
watchFile: WatchFileKind.UseFsEvents,
watchDirectory: WatchDirectoryKind.FixedPollingInterval
},
additionalFiles: {
"/base.json": JSON.stringify({
watchOptions: {
watchFile: "UseFsEventsOnParentDirectory",
watchDirectory: "FixedPollingInterval"
}
})
}
},
{
json: {
extends: "./base.json",
},
expectedOptions: {
watchFile: WatchFileKind.UseFsEventsOnParentDirectory,
watchDirectory: WatchDirectoryKind.FixedPollingInterval
},
additionalFiles: {
"/base.json": JSON.stringify({
watchOptions: {
watchFile: "UseFsEventsOnParentDirectory",
watchDirectory: "FixedPollingInterval"
}
})
}
verifyWatchOptions("when extending config file with watchOptions", () => [
{
json: {
extends: "./base.json",
watchOptions: {
watchFile: "UseFsEvents",
}
]);
});
});

describe("different options", () => {
verifyWatchOptions(() => [
{
json: { watchOptions: { watchFile: "UseFsEvents" } },
expectedOptions: { watchFile: WatchFileKind.UseFsEvents }
},
{
json: { watchOptions: { watchDirectory: "UseFsEvents" } },
expectedOptions: { watchDirectory: WatchDirectoryKind.UseFsEvents }
},
{
json: { watchOptions: { fallbackPolling: "DynamicPriority" } },
expectedOptions: { fallbackPolling: PollingWatchKind.DynamicPriority }
},
{
json: { watchOptions: { synchronousWatchDirectory: true } },
expectedOptions: { synchronousWatchDirectory: true }
},
{
json: { watchOptions: { excludeDirectories: ["**/temp"] } },
expectedOptions: { excludeDirectories: ["/**/temp"] }
},
{
json: { watchOptions: { excludeFiles: ["**/temp/*.ts"] } },
expectedOptions: { excludeFiles: ["/**/temp/*.ts"] }
},
{
json: { watchOptions: { excludeDirectories: ["**/../*"] } },
expectedOptions: { excludeDirectories: [] },
expectedErrors: sourceFile => [
{
messageText: `File specification cannot contain a parent directory ('..') that appears after a recursive directory wildcard ('**'): '**/../*'.`,
category: Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0.category,
code: Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0.code,
file: sourceFile,
start: sourceFile && sourceFile.text.indexOf(`"**/../*"`),
length: sourceFile && `"**/../*"`.length,
reportsDeprecated: undefined,
reportsUnnecessary: undefined
additionalFiles: {
"/base.json": JSON.stringify({
watchOptions: {
watchFile: "UseFsEventsOnParentDirectory",
watchDirectory: "FixedPollingInterval"
}
]
})
}
},
{
json: {
extends: "./base.json",
},
{
json: { watchOptions: { excludeFiles: ["**/../*"] } },
expectedOptions: { excludeFiles: [] },
expectedErrors: sourceFile => [
{
messageText: `File specification cannot contain a parent directory ('..') that appears after a recursive directory wildcard ('**'): '**/../*'.`,
category: Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0.category,
code: Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0.code,
file: sourceFile,
start: sourceFile && sourceFile.text.indexOf(`"**/../*"`),
length: sourceFile && `"**/../*"`.length,
reportsDeprecated: undefined,
reportsUnnecessary: undefined
additionalFiles: {
"/base.json": JSON.stringify({
watchOptions: {
watchFile: "UseFsEventsOnParentDirectory",
watchDirectory: "FixedPollingInterval"
}
]
},
]);
});
})
}
}
]);

describe("watch options extending passed in watch options", () => {
verifyWatchOptions(() => [
{
json: { watchOptions: { watchFile: "UseFsEvents" } },
expectedOptions: { watchFile: WatchFileKind.UseFsEvents, watchDirectory: WatchDirectoryKind.FixedPollingInterval },
existingWatchOptions: { watchDirectory: WatchDirectoryKind.FixedPollingInterval }
},
{
json: {},
expectedOptions: { watchDirectory: WatchDirectoryKind.FixedPollingInterval },
existingWatchOptions: { watchDirectory: WatchDirectoryKind.FixedPollingInterval }
},
]);
});
verifyWatchOptions("different options", () => [
{
json: { watchOptions: { watchFile: "UseFsEvents" } },
},
{
json: { watchOptions: { watchDirectory: "UseFsEvents" } },
},
{
json: { watchOptions: { fallbackPolling: "DynamicPriority" } },
},
{
json: { watchOptions: { synchronousWatchDirectory: true } },
},
{
json: { watchOptions: { excludeDirectories: ["**/temp"] } },
},
{
json: { watchOptions: { excludeFiles: ["**/temp/*.ts"] } },
},
{
json: { watchOptions: { excludeDirectories: ["**/../*"] } },
},
{
json: { watchOptions: { excludeFiles: ["**/../*"] } },
},
]);

verifyWatchOptions("watch options extending passed in watch options", () => [
{
json: { watchOptions: { watchFile: "UseFsEvents" } },
},
{
json: {},
},
]);
});
}
2 changes: 1 addition & 1 deletion src/testRunner/unittests/tsserver/configuredProjects.ts
Expand Up @@ -577,7 +577,7 @@ namespace ts.projectSystem {
content: "let zz = 1;"
};
host.writeFile(file5.path, file5.content);
projectService.baselineHost("File5 written");
projectService.testhost.baselineHost("File5 written");
projectService.openClientFile(file5.path);

baselineTsserverLogs("configuredProjects", "Open ref of configured project when open file gets added to the project as part of configured file update", projectService);
Expand Down

0 comments on commit 43c6fd4

Please sign in to comment.