mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-21 03:42:16 +00:00
test: Fix slow typescript editor tests by mocking typescript vfs (no-changelog) (#14631)
This commit is contained in:
@@ -1,6 +1,12 @@
|
|||||||
|
import { type ChangeSet, EditorState } from '@codemirror/state';
|
||||||
|
import * as tsvfs from '@typescript/vfs';
|
||||||
|
import ts from 'typescript';
|
||||||
|
import { mock } from 'vitest-mock-extended';
|
||||||
import type { WorkerInitOptions } from '../types';
|
import type { WorkerInitOptions } from '../types';
|
||||||
import { worker } from './typescript.worker';
|
import { worker } from './typescript.worker';
|
||||||
import { type ChangeSet, EditorState } from '@codemirror/state';
|
|
||||||
|
vi.mock('@typescript/vfs');
|
||||||
|
vi.mock('typescript');
|
||||||
|
|
||||||
async function createWorker({
|
async function createWorker({
|
||||||
doc,
|
doc,
|
||||||
@@ -16,6 +22,14 @@ function myFunction(){
|
|||||||
return $input.all();`;
|
return $input.all();`;
|
||||||
const state = EditorState.create({ doc: doc ?? defaultDoc });
|
const state = EditorState.create({ doc: doc ?? defaultDoc });
|
||||||
|
|
||||||
|
const mockEnv = mock<tsvfs.VirtualTypeScriptEnvironment>({
|
||||||
|
getSourceFile: vi.fn(() => mock<ts.SourceFile>({ getText: () => state.doc.toString() })),
|
||||||
|
languageService: mock<ts.LanguageService>(),
|
||||||
|
});
|
||||||
|
|
||||||
|
vi.spyOn(tsvfs, 'createDefaultMapFromCDN').mockResolvedValue(new Map());
|
||||||
|
vi.spyOn(tsvfs, 'createVirtualTypeScriptEnvironment').mockResolvedValue(mockEnv);
|
||||||
|
|
||||||
const tsWorker = worker.init(
|
const tsWorker = worker.init(
|
||||||
{
|
{
|
||||||
allNodeNames: [],
|
allNodeNames: [],
|
||||||
@@ -32,12 +46,32 @@ return $input.all();`;
|
|||||||
params: { path: '', type: 'string', value: '' },
|
params: { path: '', type: 'string', value: '' },
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
return await tsWorker;
|
return { tsWorker: await tsWorker, mockEnv };
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('Typescript Worker', () => {
|
describe('Typescript Worker', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
vi.resetAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
it('should return diagnostics', async () => {
|
it('should return diagnostics', async () => {
|
||||||
const tsWorker = await createWorker();
|
const { tsWorker, mockEnv } = await createWorker();
|
||||||
|
|
||||||
|
vi.mocked(mockEnv.languageService.getSemanticDiagnostics).mockReturnValue([
|
||||||
|
mock<ts.Diagnostic>({
|
||||||
|
start: 56,
|
||||||
|
length: 10,
|
||||||
|
code: 6133,
|
||||||
|
messageText: "'myFunction' is declared but its value is never read.",
|
||||||
|
}),
|
||||||
|
mock<ts.Diagnostic>({
|
||||||
|
start: 93,
|
||||||
|
length: 5,
|
||||||
|
code: 6133,
|
||||||
|
messageText: "'myObj' is declared but its value is never read.",
|
||||||
|
}),
|
||||||
|
]);
|
||||||
|
vi.mocked(mockEnv.languageService.getSyntacticDiagnostics).mockReturnValue([]);
|
||||||
|
|
||||||
expect(tsWorker.getDiagnostics()).toEqual([
|
expect(tsWorker.getDiagnostics()).toEqual([
|
||||||
{
|
{
|
||||||
@@ -55,10 +89,13 @@ describe('Typescript Worker', () => {
|
|||||||
to: 52,
|
to: 52,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
expect(mockEnv.languageService.getSemanticDiagnostics).toHaveBeenCalledWith('id.js');
|
||||||
|
expect(mockEnv.languageService.getSyntacticDiagnostics).toHaveBeenCalledWith('id.js');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should accept updates from the client and buffer them', async () => {
|
it('should accept updates from the client and buffer them', async () => {
|
||||||
const tsWorker = await createWorker();
|
const { tsWorker, mockEnv } = await createWorker();
|
||||||
// Add if statement and remove indentation
|
// Add if statement and remove indentation
|
||||||
const changes = [
|
const changes = [
|
||||||
[75, [0, '', ''], 22],
|
[75, [0, '', ''], 22],
|
||||||
@@ -68,49 +105,60 @@ describe('Typescript Worker', () => {
|
|||||||
];
|
];
|
||||||
|
|
||||||
vi.useFakeTimers({ toFake: ['setTimeout', 'queueMicrotask', 'nextTick'] });
|
vi.useFakeTimers({ toFake: ['setTimeout', 'queueMicrotask', 'nextTick'] });
|
||||||
|
vi.mocked(mockEnv.updateFile).mockReset();
|
||||||
for (const change of changes) {
|
for (const change of changes) {
|
||||||
tsWorker.updateFile(change as unknown as ChangeSet);
|
tsWorker.updateFile(change as unknown as ChangeSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
expect(tsWorker.getDiagnostics()).toHaveLength(2);
|
expect(mockEnv.updateFile).not.toHaveBeenCalled();
|
||||||
|
|
||||||
vi.advanceTimersByTime(1000);
|
vi.advanceTimersByTime(1000);
|
||||||
vi.runAllTicks();
|
vi.runAllTicks();
|
||||||
|
|
||||||
expect(tsWorker.getDiagnostics()).toHaveLength(3);
|
expect(mockEnv.updateFile).toHaveBeenCalledTimes(1);
|
||||||
expect(tsWorker.getDiagnostics()).toEqual([
|
expect(mockEnv.updateFile).toHaveBeenCalledWith(
|
||||||
|
'id.js',
|
||||||
|
'\n\nif (true){\n const myObj = {test: "value"}\n}',
|
||||||
{
|
{
|
||||||
from: 10,
|
length: 0,
|
||||||
markClass: 'cm-faded',
|
start: 121,
|
||||||
message: "'myFunction' is declared but its value is never read.",
|
|
||||||
severity: 'warning',
|
|
||||||
to: 20,
|
|
||||||
},
|
},
|
||||||
{
|
);
|
||||||
from: 47,
|
|
||||||
markClass: 'cm-faded',
|
|
||||||
message: "'myObj' is declared but its value is never read.",
|
|
||||||
severity: 'warning',
|
|
||||||
to: 52,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
from: 96,
|
|
||||||
markClass: 'cm-faded',
|
|
||||||
message: "'myObj' is declared but its value is never read.",
|
|
||||||
severity: 'warning',
|
|
||||||
to: 101,
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return completions', async () => {
|
it('should return completions', async () => {
|
||||||
const doc = 'return $input.';
|
const doc = 'return $input.';
|
||||||
const tsWorker = await createWorker({ doc });
|
const { tsWorker, mockEnv } = await createWorker({ doc });
|
||||||
|
|
||||||
|
vi.mocked(mockEnv.languageService.getCompletionsAtPosition).mockReturnValue(
|
||||||
|
mock<ts.CompletionInfo>({
|
||||||
|
isGlobalCompletion: false,
|
||||||
|
optionalReplacementSpan: '',
|
||||||
|
entries: [
|
||||||
|
mock<ts.CompletionEntry>({
|
||||||
|
name: 'all',
|
||||||
|
kind: ts.ScriptElementKind.functionElement,
|
||||||
|
sortText: '10',
|
||||||
|
}),
|
||||||
|
mock<ts.CompletionEntry>({
|
||||||
|
name: 'first',
|
||||||
|
kind: ts.ScriptElementKind.functionElement,
|
||||||
|
sortText: '10',
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
const completionResult = await tsWorker.getCompletionsAtPos(doc.length);
|
const completionResult = await tsWorker.getCompletionsAtPos(doc.length);
|
||||||
assert(completionResult !== null);
|
assert(completionResult !== null);
|
||||||
|
|
||||||
|
expect(completionResult).toEqual({
|
||||||
|
isGlobal: false,
|
||||||
|
result: expect.objectContaining({
|
||||||
|
from: 60,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
const completionLabels = completionResult.result.options.map((c) => c.label);
|
const completionLabels = completionResult.result.options.map((c) => c.label);
|
||||||
expect(completionLabels).toContain('all()');
|
expect(completionLabels).toContain('all()');
|
||||||
expect(completionLabels).toContain('first()');
|
expect(completionLabels).toContain('first()');
|
||||||
|
|||||||
Reference in New Issue
Block a user