mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-16 07:13:45 -05:00
Combine the event manager testing
This commit is contained in:
@@ -5,9 +5,9 @@ namespace ts.projectSystem {
|
||||
describe("project telemetry", () => {
|
||||
it("does nothing for inferred project", () => {
|
||||
const file = makeFile("/a.js");
|
||||
const et = new EventTracker([file]);
|
||||
const et = new TestServerEventManager([file]);
|
||||
et.service.openClientFile(file.path);
|
||||
assert.equal(et.getEventsWithName(ts.server.ProjectInfoTelemetryEvent).length, 0);
|
||||
et.hasZeroEvent(ts.server.ProjectInfoTelemetryEvent);
|
||||
});
|
||||
|
||||
it("only sends an event once", () => {
|
||||
@@ -15,7 +15,7 @@ namespace ts.projectSystem {
|
||||
const file2 = makeFile("/b.ts");
|
||||
const tsconfig = makeFile("/a/tsconfig.json", {});
|
||||
|
||||
const et = new EventTracker([file, file2, tsconfig]);
|
||||
const et = new TestServerEventManager([file, file2, tsconfig]);
|
||||
et.service.openClientFile(file.path);
|
||||
et.assertProjectInfoTelemetryEvent({}, tsconfig.path);
|
||||
|
||||
@@ -25,12 +25,12 @@ namespace ts.projectSystem {
|
||||
et.service.openClientFile(file2.path);
|
||||
checkNumberOfProjects(et.service, { inferredProjects: 1 });
|
||||
|
||||
assert.equal(et.getEventsWithName(ts.server.ProjectInfoTelemetryEvent).length, 0);
|
||||
et.hasZeroEvent(ts.server.ProjectInfoTelemetryEvent);
|
||||
|
||||
et.service.openClientFile(file.path);
|
||||
checkNumberOfProjects(et.service, { configuredProjects: 1, inferredProjects: 1 });
|
||||
|
||||
assert.equal(et.getEventsWithName(ts.server.ProjectInfoTelemetryEvent).length, 0);
|
||||
et.hasZeroEvent(ts.server.ProjectInfoTelemetryEvent);
|
||||
});
|
||||
|
||||
it("counts files by extension", () => {
|
||||
@@ -39,7 +39,7 @@ namespace ts.projectSystem {
|
||||
const compilerOptions: ts.CompilerOptions = { allowJs: true };
|
||||
const tsconfig = makeFile("/tsconfig.json", { compilerOptions, include: ["src"] });
|
||||
|
||||
const et = new EventTracker([...files, notIncludedFile, tsconfig]);
|
||||
const et = new TestServerEventManager([...files, notIncludedFile, tsconfig]);
|
||||
et.service.openClientFile(files[0].path);
|
||||
et.assertProjectInfoTelemetryEvent({
|
||||
fileStats: { ts: 2, tsx: 1, js: 1, jsx: 1, dts: 1 },
|
||||
@@ -50,7 +50,7 @@ namespace ts.projectSystem {
|
||||
|
||||
it("works with external project", () => {
|
||||
const file1 = makeFile("/a.ts");
|
||||
const et = new EventTracker([file1]);
|
||||
const et = new TestServerEventManager([file1]);
|
||||
const compilerOptions: ts.server.protocol.CompilerOptions = { strict: true };
|
||||
|
||||
const projectFileName = "/hunter2/foo.csproj";
|
||||
@@ -148,7 +148,7 @@ namespace ts.projectSystem {
|
||||
(compilerOptions as any).unknownCompilerOption = "hunter2"; // These are always ignored.
|
||||
const tsconfig = makeFile("/tsconfig.json", { compilerOptions, files: ["/a.ts"] });
|
||||
|
||||
const et = new EventTracker([file, tsconfig]);
|
||||
const et = new TestServerEventManager([file, tsconfig]);
|
||||
et.service.openClientFile(file.path);
|
||||
|
||||
et.assertProjectInfoTelemetryEvent({
|
||||
@@ -168,7 +168,7 @@ namespace ts.projectSystem {
|
||||
compileOnSave: true,
|
||||
});
|
||||
|
||||
const et = new EventTracker([tsconfig, file]);
|
||||
const et = new TestServerEventManager([tsconfig, file]);
|
||||
et.service.openClientFile(file.path);
|
||||
et.assertProjectInfoTelemetryEvent({
|
||||
extends: true,
|
||||
@@ -198,7 +198,7 @@ namespace ts.projectSystem {
|
||||
exclude: [],
|
||||
},
|
||||
});
|
||||
const et = new EventTracker([jsconfig, file]);
|
||||
const et = new TestServerEventManager([jsconfig, file]);
|
||||
et.service.openClientFile(file.path);
|
||||
et.assertProjectInfoTelemetryEvent({
|
||||
projectId: Harness.mockHash("/jsconfig.json"),
|
||||
@@ -216,7 +216,7 @@ namespace ts.projectSystem {
|
||||
it("detects whether language service was disabled", () => {
|
||||
const file = makeFile("/a.js");
|
||||
const tsconfig = makeFile("/jsconfig.json", {});
|
||||
const et = new EventTracker([tsconfig, file]);
|
||||
const et = new TestServerEventManager([tsconfig, file]);
|
||||
et.host.getFileSize = () => server.maxProgramSizeForNonTsFiles + 1;
|
||||
et.service.openClientFile(file.path);
|
||||
et.getEvent<server.ProjectLanguageServiceStateEvent>(server.ProjectLanguageServiceStateEvent);
|
||||
@@ -235,83 +235,7 @@ namespace ts.projectSystem {
|
||||
});
|
||||
});
|
||||
|
||||
class EventTracker {
|
||||
private events: server.ProjectServiceEvent[] = [];
|
||||
readonly service: TestProjectService;
|
||||
readonly host: projectSystem.TestServerHost;
|
||||
|
||||
constructor(files: projectSystem.FileOrFolder[]) {
|
||||
this.host = createServerHost(files);
|
||||
this.service = createProjectService(this.host, {
|
||||
eventHandler: event => {
|
||||
this.events.push(event);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
getEvents(): ReadonlyArray<server.ProjectServiceEvent> {
|
||||
const events = this.events;
|
||||
this.events = [];
|
||||
return events;
|
||||
}
|
||||
|
||||
getEventsWithName<T extends server.ProjectServiceEvent>(eventName: T["eventName"]): ReadonlyArray<T> {
|
||||
let events: T[];
|
||||
filterMutate(this.events, event => {
|
||||
if (event.eventName === eventName) {
|
||||
(events || (events = [])).push(event as T);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
return events || emptyArray;
|
||||
}
|
||||
|
||||
assertProjectInfoTelemetryEvent(partial: Partial<server.ProjectInfoTelemetryEventData>, configFile?: string): void {
|
||||
assert.deepEqual(this.getEvent<server.ProjectInfoTelemetryEvent>(ts.server.ProjectInfoTelemetryEvent), {
|
||||
projectId: Harness.mockHash(configFile || "/tsconfig.json"),
|
||||
fileStats: fileStats({ ts: 1 }),
|
||||
compilerOptions: {},
|
||||
extends: false,
|
||||
files: false,
|
||||
include: false,
|
||||
exclude: false,
|
||||
compileOnSave: false,
|
||||
typeAcquisition: {
|
||||
enable: false,
|
||||
exclude: false,
|
||||
include: false,
|
||||
},
|
||||
configFileName: "tsconfig.json",
|
||||
projectType: "configured",
|
||||
languageServiceEnabled: true,
|
||||
version: ts.version,
|
||||
...partial,
|
||||
});
|
||||
}
|
||||
|
||||
getEvent<T extends server.ProjectServiceEvent>(eventName: T["eventName"]): T["data"] {
|
||||
let event: server.ProjectServiceEvent;
|
||||
filterMutate(this.events, e => {
|
||||
if (e.eventName === eventName) {
|
||||
if (event) {
|
||||
assert(false, "more than one event found");
|
||||
}
|
||||
event = e;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
assert.equal(event.eventName, eventName);
|
||||
return event.data;
|
||||
}
|
||||
}
|
||||
|
||||
function makeFile(path: string, content: {} = ""): projectSystem.FileOrFolder {
|
||||
return { path, content: isString(content) ? "" : JSON.stringify(content) };
|
||||
}
|
||||
|
||||
function fileStats(nonZeroStats: Partial<server.FileStats>): server.FileStats {
|
||||
return { ts: 0, tsx: 0, dts: 0, js: 0, jsx: 0, ...nonZeroStats };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,16 +132,78 @@ namespace ts.projectSystem {
|
||||
return map(fileNames, toExternalFile);
|
||||
}
|
||||
|
||||
class TestServerEventManager {
|
||||
public events: server.ProjectServiceEvent[] = [];
|
||||
export function fileStats(nonZeroStats: Partial<server.FileStats>): server.FileStats {
|
||||
return { ts: 0, tsx: 0, dts: 0, js: 0, jsx: 0, ...nonZeroStats };
|
||||
}
|
||||
|
||||
handler: server.ProjectServiceEventHandler = (event: server.ProjectServiceEvent) => {
|
||||
this.events.push(event);
|
||||
export class TestServerEventManager {
|
||||
private events: server.ProjectServiceEvent[] = [];
|
||||
readonly session: TestSession;
|
||||
readonly service: server.ProjectService;
|
||||
readonly host: projectSystem.TestServerHost;
|
||||
constructor(files: projectSystem.FileOrFolder[]) {
|
||||
this.host = createServerHost(files);
|
||||
this.session = createSession(this.host, {
|
||||
canUseEvents: true,
|
||||
eventHandler: event => this.events.push(event),
|
||||
});
|
||||
this.service = this.session.getProjectService();
|
||||
}
|
||||
|
||||
checkEventCountOfType(eventType: "configFileDiag", expectedCount: number) {
|
||||
const eventsOfType = filter(this.events, e => e.eventName === eventType);
|
||||
assert.equal(eventsOfType.length, expectedCount, `The actual event counts of type ${eventType} is ${eventsOfType.length}, while expected ${expectedCount}`);
|
||||
getEvents(): ReadonlyArray<server.ProjectServiceEvent> {
|
||||
const events = this.events;
|
||||
this.events = [];
|
||||
return events;
|
||||
}
|
||||
|
||||
getEvent<T extends server.ProjectServiceEvent>(eventName: T["eventName"]): T["data"] {
|
||||
let eventData: T["data"];
|
||||
filterMutate(this.events, e => {
|
||||
if (e.eventName === eventName) {
|
||||
if (eventData !== undefined) {
|
||||
assert(false, "more than one event found");
|
||||
}
|
||||
eventData = e.data;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
assert.isDefined(eventData);
|
||||
return eventData;
|
||||
}
|
||||
|
||||
hasZeroEvent<T extends server.ProjectServiceEvent>(eventName: T["eventName"]) {
|
||||
const eventCount = countWhere(this.events, event => event.eventName === eventName);
|
||||
assert.equal(eventCount, 0);
|
||||
}
|
||||
|
||||
checkSingleConfigFileDiagEvent(configFileName: string, triggerFile: string) {
|
||||
const eventData = this.getEvent<server.ConfigFileDiagEvent>(server.ConfigFileDiagEvent);
|
||||
assert.equal(eventData.configFileName, configFileName);
|
||||
assert.equal(eventData.triggerFile, triggerFile);
|
||||
}
|
||||
|
||||
assertProjectInfoTelemetryEvent(partial: Partial<server.ProjectInfoTelemetryEventData>, configFile?: string): void {
|
||||
assert.deepEqual(this.getEvent<server.ProjectInfoTelemetryEvent>(ts.server.ProjectInfoTelemetryEvent), {
|
||||
projectId: Harness.mockHash(configFile || "/tsconfig.json"),
|
||||
fileStats: fileStats({ ts: 1 }),
|
||||
compilerOptions: {},
|
||||
extends: false,
|
||||
files: false,
|
||||
include: false,
|
||||
exclude: false,
|
||||
compileOnSave: false,
|
||||
typeAcquisition: {
|
||||
enable: false,
|
||||
exclude: false,
|
||||
include: false,
|
||||
},
|
||||
configFileName: "tsconfig.json",
|
||||
projectType: "configured",
|
||||
languageServiceEnabled: true,
|
||||
version: ts.version,
|
||||
...partial,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3076,7 +3138,6 @@ namespace ts.projectSystem {
|
||||
describe("Configure file diagnostics events", () => {
|
||||
|
||||
it("are generated when the config file has errors", () => {
|
||||
const serverEventManager = new TestServerEventManager();
|
||||
const file = {
|
||||
path: "/a/b/app.ts",
|
||||
content: "let x = 10"
|
||||
@@ -3090,26 +3151,12 @@ namespace ts.projectSystem {
|
||||
}
|
||||
}`
|
||||
};
|
||||
|
||||
const host = createServerHost([file, configFile]);
|
||||
const session = createSession(host, {
|
||||
canUseEvents: true,
|
||||
eventHandler: serverEventManager.handler
|
||||
});
|
||||
openFilesForSession([file], session);
|
||||
serverEventManager.checkEventCountOfType("configFileDiag", 1);
|
||||
|
||||
for (const event of serverEventManager.events) {
|
||||
if (event.eventName === "configFileDiag") {
|
||||
assert.equal(event.data.configFileName, configFile.path);
|
||||
assert.equal(event.data.triggerFile, file.path);
|
||||
return;
|
||||
}
|
||||
}
|
||||
const serverEventManager = new TestServerEventManager([file, configFile]);
|
||||
openFilesForSession([file], serverEventManager.session);
|
||||
serverEventManager.checkSingleConfigFileDiagEvent(configFile.path, file.path);
|
||||
});
|
||||
|
||||
it("are generated when the config file doesn't have errors", () => {
|
||||
const serverEventManager = new TestServerEventManager();
|
||||
const file = {
|
||||
path: "/a/b/app.ts",
|
||||
content: "let x = 10"
|
||||
@@ -3120,18 +3167,12 @@ namespace ts.projectSystem {
|
||||
"compilerOptions": {}
|
||||
}`
|
||||
};
|
||||
|
||||
const host = createServerHost([file, configFile]);
|
||||
const session = createSession(host, {
|
||||
canUseEvents: true,
|
||||
eventHandler: serverEventManager.handler
|
||||
});
|
||||
openFilesForSession([file], session);
|
||||
serverEventManager.checkEventCountOfType("configFileDiag", 1);
|
||||
const serverEventManager = new TestServerEventManager([file, configFile]);
|
||||
openFilesForSession([file], serverEventManager.session);
|
||||
serverEventManager.checkSingleConfigFileDiagEvent(configFile.path, file.path);
|
||||
});
|
||||
|
||||
it("are generated when the config file changes", () => {
|
||||
const serverEventManager = new TestServerEventManager();
|
||||
const file = {
|
||||
path: "/a/b/app.ts",
|
||||
content: "let x = 10"
|
||||
@@ -3143,33 +3184,28 @@ namespace ts.projectSystem {
|
||||
}`
|
||||
};
|
||||
|
||||
const host = createServerHost([file, configFile]);
|
||||
const session = createSession(host, {
|
||||
canUseEvents: true,
|
||||
eventHandler: serverEventManager.handler
|
||||
});
|
||||
openFilesForSession([file], session);
|
||||
serverEventManager.checkEventCountOfType("configFileDiag", 1);
|
||||
const serverEventManager = new TestServerEventManager([file, configFile]);
|
||||
openFilesForSession([file], serverEventManager.session);
|
||||
serverEventManager.checkSingleConfigFileDiagEvent(configFile.path, file.path);
|
||||
|
||||
configFile.content = `{
|
||||
"compilerOptions": {
|
||||
"haha": 123
|
||||
}
|
||||
}`;
|
||||
host.reloadFS([file, configFile]);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
serverEventManager.checkEventCountOfType("configFileDiag", 2);
|
||||
serverEventManager.host.reloadFS([file, configFile]);
|
||||
serverEventManager.host.runQueuedTimeoutCallbacks();
|
||||
serverEventManager.checkSingleConfigFileDiagEvent(configFile.path, configFile.path);
|
||||
|
||||
configFile.content = `{
|
||||
"compilerOptions": {}
|
||||
}`;
|
||||
host.reloadFS([file, configFile]);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
serverEventManager.checkEventCountOfType("configFileDiag", 3);
|
||||
serverEventManager.host.reloadFS([file, configFile]);
|
||||
serverEventManager.host.runQueuedTimeoutCallbacks();
|
||||
serverEventManager.checkSingleConfigFileDiagEvent(configFile.path, configFile.path);
|
||||
});
|
||||
|
||||
it("are not generated when the config file doesnot include file opened and config file has errors", () => {
|
||||
const serverEventManager = new TestServerEventManager();
|
||||
const file = {
|
||||
path: "/a/b/app.ts",
|
||||
content: "let x = 10"
|
||||
@@ -3188,18 +3224,12 @@ namespace ts.projectSystem {
|
||||
"files": ["app.ts"]
|
||||
}`
|
||||
};
|
||||
|
||||
const host = createServerHost([file, file2, libFile, configFile]);
|
||||
const session = createSession(host, {
|
||||
canUseEvents: true,
|
||||
eventHandler: serverEventManager.handler
|
||||
});
|
||||
openFilesForSession([file2], session);
|
||||
serverEventManager.checkEventCountOfType("configFileDiag", 0);
|
||||
const serverEventManager = new TestServerEventManager([file, file2, libFile, configFile]);
|
||||
openFilesForSession([file2], serverEventManager.session);
|
||||
serverEventManager.hasZeroEvent("configFileDiag");
|
||||
});
|
||||
|
||||
it("are not generated when the config file doesnot include file opened and doesnt contain any errors", () => {
|
||||
const serverEventManager = new TestServerEventManager();
|
||||
const file = {
|
||||
path: "/a/b/app.ts",
|
||||
content: "let x = 10"
|
||||
@@ -3215,13 +3245,9 @@ namespace ts.projectSystem {
|
||||
}`
|
||||
};
|
||||
|
||||
const host = createServerHost([file, file2, libFile, configFile]);
|
||||
const session = createSession(host, {
|
||||
canUseEvents: true,
|
||||
eventHandler: serverEventManager.handler
|
||||
});
|
||||
openFilesForSession([file2], session);
|
||||
serverEventManager.checkEventCountOfType("configFileDiag", 0);
|
||||
const serverEventManager = new TestServerEventManager([file, file2, libFile, configFile]);
|
||||
openFilesForSession([file2], serverEventManager.session);
|
||||
serverEventManager.hasZeroEvent("configFileDiag");
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user