Skip to content

Commit 910ca89

Browse files
committed
Add unit tests
1 parent 5b73b26 commit 910ca89

2 files changed

Lines changed: 171 additions & 1 deletion

File tree

src/solutions/solution-problems.test.ts

Lines changed: 138 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
import { describe, it, expect, beforeEach } from '@jest/globals';
1818
import * as vscode from 'vscode';
1919
import { ExtensionContext } from 'vscode';
20-
import { MANAGE_COMPONENTS_PACKS_COMMAND_ID } from '../manifest';
20+
import { MANAGE_COMPONENTS_PACKS_COMMAND_ID, MERGE_FILE_FROM_PATH_COMMAND_ID } from '../manifest';
2121
import * as fsUtils from '../utils/fs-utils';
2222
import * as vscodeUtils from '../utils/vscode-utils';
2323
import { solutionManagerFactory, MockSolutionManager } from './solution-manager.factories';
@@ -234,4 +234,141 @@ describe('SolutionProblems', () => {
234234
expect(command).toBe(`command:${MANAGE_COMPONENTS_PACKS_COMMAND_ID}`);
235235
expect(JSON.parse(decodeURIComponent(args))).toEqual([{ type: 'context', value: 'HID.Debug+STM32U585AIIx' }]);
236236
});
237+
238+
it('creates open merge view command link for absolute merge paths', async () => {
239+
await solutionProblems.activate({ subscriptions: [] } as unknown as ExtensionContext);
240+
const setSpy = jest.spyOn(vscode.languages.createDiagnosticCollection(), 'set');
241+
242+
await eventHub.fireConvertCompleted({
243+
severity: 'warning',
244+
detection: false,
245+
logMessages: {
246+
success: true,
247+
errors: [],
248+
warnings: ["mylayer.clayer.yml - file '/packs/Component/config.c' update required from component 'Arm::Device@2.3.4'"],
249+
info: [],
250+
},
251+
});
252+
await waitTimeout();
253+
254+
const [, diagnostics] = setSpy.mock.calls[0] as unknown as [vscode.Uri, readonly vscode.Diagnostic[] | undefined];
255+
const diagnostic = diagnostics?.[0];
256+
const code = diagnostic?.code as { value: string; target: vscode.Uri };
257+
const [command, args] = code.target.toString().split('?');
258+
259+
expect(diagnostic?.message).toBe("update required for config file 'config.c' from component 'Device'.");
260+
expect(code.value).toBe('Open in Merge View');
261+
expect(command).toBe(`command:${MERGE_FILE_FROM_PATH_COMMAND_ID}`);
262+
expect(JSON.parse(decodeURIComponent(args))).toEqual(['/packs/Component/config.c']);
263+
});
264+
265+
it('creates a merge command uri with encoded local path', () => {
266+
const result = solutionProblems['createMergeCommandUri']('/packs/Component/config.c');
267+
const [command, args] = result.toString().split('?');
268+
269+
expect(command).toBe(`command:${MERGE_FILE_FROM_PATH_COMMAND_ID}`);
270+
expect(JSON.parse(decodeURIComponent(args))).toEqual(['/packs/Component/config.c']);
271+
});
272+
273+
it('creates merge diagnostic action for merge messages with component context', () => {
274+
const result = solutionProblems['createMergeDiagnosticAction'](
275+
"file '/packs/Component/config.c' update required from component 'Arm::Device@2.3.4'",
276+
layerPath,
277+
);
278+
279+
expect(result).toEqual({
280+
message: "update required for config file 'config.c' from component 'Device'.",
281+
code: {
282+
value: 'Open in Merge View',
283+
target: vscode.Uri.parse(`command:${MERGE_FILE_FROM_PATH_COMMAND_ID}?${encodeURIComponent(JSON.stringify(['/packs/Component/config.c']))}`),
284+
},
285+
});
286+
});
287+
288+
it('returns undefined merge diagnostic action for non-merge messages', () => {
289+
const result = solutionProblems['createMergeDiagnosticAction'](
290+
"component 'Arm::Device@2.3.4' is missing",
291+
layerPath,
292+
);
293+
294+
expect(result).toBeUndefined();
295+
});
296+
297+
it('falls back to the diagnostic file path for relative merge paths', async () => {
298+
await solutionProblems.activate({ subscriptions: [] } as unknown as ExtensionContext);
299+
const setSpy = jest.spyOn(vscode.languages.createDiagnosticCollection(), 'set');
300+
301+
await eventHub.fireConvertCompleted({
302+
severity: 'warning',
303+
detection: false,
304+
logMessages: {
305+
success: true,
306+
errors: [],
307+
warnings: ["mylayer.clayer.yml - file 'relative-config.c' update recommended"],
308+
info: [],
309+
},
310+
});
311+
await waitTimeout();
312+
313+
const [uri, diagnostics] = setSpy.mock.calls[0] as unknown as [vscode.Uri, readonly vscode.Diagnostic[] | undefined];
314+
const diagnostic = diagnostics?.[0];
315+
const code = diagnostic?.code as { value: string; target: vscode.Uri };
316+
const [command, args] = code.target.toString().split('?');
317+
318+
expect(uri.fsPath).toContain('mylayer.clayer.yml');
319+
expect(diagnostic?.message).toBe("update recommended for config file 'mylayer.clayer.yml' has a new version available for merge.");
320+
expect(code.value).toBe('Open in Merge View');
321+
expect(command).toBe(`command:${MERGE_FILE_FROM_PATH_COMMAND_ID}`);
322+
expect(JSON.parse(decodeURIComponent(args))).toEqual([layerPath]);
323+
});
324+
325+
it.each(['required', 'recommended', 'suggested', 'mandatory'] as const)(
326+
'renders merge diagnostics for %s update levels',
327+
async updateLevel => {
328+
await solutionProblems.activate({ subscriptions: [] } as unknown as ExtensionContext);
329+
const setSpy = jest.spyOn(vscode.languages.createDiagnosticCollection(), 'set');
330+
331+
await eventHub.fireConvertCompleted({
332+
severity: 'warning',
333+
detection: false,
334+
logMessages: {
335+
success: true,
336+
errors: [],
337+
warnings: [`mylayer.clayer.yml - file '/packs/Component/${updateLevel}.c' update ${updateLevel}`],
338+
info: [],
339+
},
340+
});
341+
await waitTimeout();
342+
343+
const [, diagnostics] = setSpy.mock.calls[0] as unknown as [vscode.Uri, readonly vscode.Diagnostic[] | undefined];
344+
expect(diagnostics?.[0].message).toBe(
345+
`update ${updateLevel} for config file '${updateLevel}.c' has a new version available for merge.`
346+
);
347+
}
348+
);
349+
350+
it('keeps non-merge diagnostics on the generic action path', async () => {
351+
await solutionProblems.activate({ subscriptions: [] } as unknown as ExtensionContext);
352+
const setSpy = jest.spyOn(vscode.languages.createDiagnosticCollection(), 'set');
353+
354+
await eventHub.fireConvertCompleted({
355+
severity: 'error',
356+
detection: false,
357+
logMessages: {
358+
success: false,
359+
errors: ["mylayer.clayer.yml - component 'Arm::Device@2.3.4' is missing"],
360+
warnings: [],
361+
info: [],
362+
},
363+
});
364+
await waitTimeout();
365+
366+
const [, diagnostics] = setSpy.mock.calls[0] as unknown as [vscode.Uri, readonly vscode.Diagnostic[] | undefined];
367+
const diagnostic = diagnostics?.[0];
368+
const code = diagnostic?.code as { value: string; target: vscode.Uri };
369+
370+
expect(diagnostic?.message).toBe("component 'Arm::Device@2.3.4' is missing");
371+
expect(code.value).toBe('Find in Files');
372+
expect(code.target.toString()).toContain('command:workbench.action.findInFiles');
373+
});
237374
});

src/views/solution-outline/commands/merge-command.test.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,42 @@ describe('MergeCommand', () => {
104104
expect(commandsProvider.registerCommand).toHaveBeenCalledWith(MergeCommand.mergeFile, expect.any(Function), expect.anything());
105105
expect(commandsProvider.registerCommand).toHaveBeenCalledWith(MergeCommand.mergeFileFromPath, expect.any(Function), expect.anything());
106106
});
107+
108+
it('forwards the mergeFileFromPath command argument to the merge handler', async () => {
109+
const runVSCodeMergeFromPathSpy = jest.spyOn(
110+
command as unknown as { runVSCodeMergeFromPath: (localPath: string) => Promise<void> },
111+
'runVSCodeMergeFromPath',
112+
).mockResolvedValue();
113+
const localPath = path.join(tmpDir, 'component.c');
114+
115+
await command.activate(extensionContextFactory());
116+
await commandsProvider.mockRunRegistered(MergeCommand.mergeFileFromPath, localPath);
117+
118+
expect(runVSCodeMergeFromPathSpy).toHaveBeenCalledWith(localPath);
119+
});
107120
});
108121

109122
describe('merge file discovery', () => {
123+
it('shows error if merge path is missing when invoked from path', async () => {
124+
const showErrorMessageSpy = jest.spyOn(vscode.window, 'showErrorMessage');
125+
126+
await command['runVSCodeMergeFromPath']('');
127+
128+
expect(showErrorMessageSpy).toHaveBeenCalledWith('Cannot open merge view: merge file path is missing.');
129+
});
130+
131+
it('normalizes the merge path before opening merge view from path', async () => {
132+
const commandPrivate = command as unknown as {
133+
runVSCodeMergeForPath: (localPath: string) => Promise<void>;
134+
};
135+
const runVSCodeMergeForPathSpy = jest.spyOn(commandPrivate, 'runVSCodeMergeForPath').mockResolvedValue();
136+
const localPath = path.join(tmpDir, '.', 'component.c');
137+
138+
await command['runVSCodeMergeFromPath'](localPath);
139+
140+
expect(runVSCodeMergeForPathSpy).toHaveBeenCalledWith(path.normalize(localPath));
141+
});
142+
110143
it('shows error if node is not passed', async () => {
111144
const showErrorMessageSpy = jest.spyOn(vscode.window, 'showErrorMessage');
112145
// @ts-expect-error - testing behavior when `runVSCodeMerge` receives null

0 commit comments

Comments
 (0)