Skip to content

Commit a862f05

Browse files
committed
test: add unit tests for config-fallback utility function
resolveButtonsWithFallback was the only function without dedicated test coverage. While indirectly tested through config-manager and store-sync, the fallback logic itself was not explicitly verified. Added 12 test cases covering all branches of 3-tier fallback logic (Local → Workspace → Global).
1 parent 7f132ad commit a862f05

1 file changed

Lines changed: 219 additions & 0 deletions

File tree

Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
import * as vscode from "vscode";
2+
import { CONFIGURATION_TARGETS } from "../../pkg/config-constants";
3+
import { ButtonConfig } from "../../shared/types";
4+
import { resolveButtonsWithFallback } from "./config-fallback";
5+
6+
const createMockConfigReader = (
7+
workspaceButtons: ButtonConfig[],
8+
globalButtons: ButtonConfig[]
9+
) => ({
10+
getButtonsFromScope: vi.fn((target: vscode.ConfigurationTarget) => {
11+
if (target === vscode.ConfigurationTarget.Workspace) {
12+
return workspaceButtons;
13+
}
14+
return globalButtons;
15+
}),
16+
});
17+
18+
const createMockLocalStorage = (buttons: ButtonConfig[]) => ({
19+
getButtons: vi.fn(() => buttons),
20+
});
21+
22+
const sampleButton: ButtonConfig = {
23+
command: "echo test",
24+
id: "test-id",
25+
name: "Test Button",
26+
};
27+
28+
describe("resolveButtonsWithFallback", () => {
29+
describe("LOCAL scope", () => {
30+
it("should return LOCAL buttons when localStorage has buttons", () => {
31+
const localButtons = [{ ...sampleButton, name: "Local Button" }];
32+
const configReader = createMockConfigReader([], []);
33+
const localStorage = createMockLocalStorage(localButtons);
34+
35+
const result = resolveButtonsWithFallback({
36+
configReader,
37+
currentTarget: CONFIGURATION_TARGETS.LOCAL,
38+
localStorage,
39+
});
40+
41+
expect(result.buttons).toEqual(localButtons);
42+
expect(result.scope).toBe(CONFIGURATION_TARGETS.LOCAL);
43+
expect(localStorage.getButtons).toHaveBeenCalled();
44+
});
45+
46+
it("should fallback to WORKSPACE when localStorage is empty", () => {
47+
const workspaceButtons = [{ ...sampleButton, name: "Workspace Button" }];
48+
const configReader = createMockConfigReader(workspaceButtons, []);
49+
const localStorage = createMockLocalStorage([]);
50+
51+
const result = resolveButtonsWithFallback({
52+
configReader,
53+
currentTarget: CONFIGURATION_TARGETS.LOCAL,
54+
localStorage,
55+
});
56+
57+
expect(result.buttons).toEqual(workspaceButtons);
58+
expect(result.scope).toBe(CONFIGURATION_TARGETS.WORKSPACE);
59+
});
60+
61+
it("should fallback to GLOBAL when localStorage and workspace are empty", () => {
62+
const globalButtons = [{ ...sampleButton, name: "Global Button" }];
63+
const configReader = createMockConfigReader([], globalButtons);
64+
const localStorage = createMockLocalStorage([]);
65+
66+
const result = resolveButtonsWithFallback({
67+
configReader,
68+
currentTarget: CONFIGURATION_TARGETS.LOCAL,
69+
localStorage,
70+
});
71+
72+
expect(result.buttons).toEqual(globalButtons);
73+
expect(result.scope).toBe(CONFIGURATION_TARGETS.GLOBAL);
74+
});
75+
76+
it("should fallback to WORKSPACE when localStorage is undefined", () => {
77+
const workspaceButtons = [{ ...sampleButton, name: "Workspace Button" }];
78+
const configReader = createMockConfigReader(workspaceButtons, []);
79+
80+
const result = resolveButtonsWithFallback({
81+
configReader,
82+
currentTarget: CONFIGURATION_TARGETS.LOCAL,
83+
localStorage: undefined,
84+
});
85+
86+
expect(result.buttons).toEqual(workspaceButtons);
87+
expect(result.scope).toBe(CONFIGURATION_TARGETS.WORKSPACE);
88+
});
89+
});
90+
91+
describe("WORKSPACE scope", () => {
92+
it("should return WORKSPACE buttons when workspace has buttons", () => {
93+
const workspaceButtons = [{ ...sampleButton, name: "Workspace Button" }];
94+
const configReader = createMockConfigReader(workspaceButtons, []);
95+
96+
const result = resolveButtonsWithFallback({
97+
configReader,
98+
currentTarget: CONFIGURATION_TARGETS.WORKSPACE,
99+
});
100+
101+
expect(result.buttons).toEqual(workspaceButtons);
102+
expect(result.scope).toBe(CONFIGURATION_TARGETS.WORKSPACE);
103+
});
104+
105+
it("should fallback to GLOBAL when workspace is empty", () => {
106+
const globalButtons = [{ ...sampleButton, name: "Global Button" }];
107+
const configReader = createMockConfigReader([], globalButtons);
108+
109+
const result = resolveButtonsWithFallback({
110+
configReader,
111+
currentTarget: CONFIGURATION_TARGETS.WORKSPACE,
112+
});
113+
114+
expect(result.buttons).toEqual(globalButtons);
115+
expect(result.scope).toBe(CONFIGURATION_TARGETS.GLOBAL);
116+
});
117+
118+
it("should not check localStorage even if provided", () => {
119+
const localButtons = [{ ...sampleButton, name: "Local Button" }];
120+
const workspaceButtons = [{ ...sampleButton, name: "Workspace Button" }];
121+
const configReader = createMockConfigReader(workspaceButtons, []);
122+
const localStorage = createMockLocalStorage(localButtons);
123+
124+
const result = resolveButtonsWithFallback({
125+
configReader,
126+
currentTarget: CONFIGURATION_TARGETS.WORKSPACE,
127+
localStorage,
128+
});
129+
130+
expect(result.buttons).toEqual(workspaceButtons);
131+
expect(result.scope).toBe(CONFIGURATION_TARGETS.WORKSPACE);
132+
expect(localStorage.getButtons).not.toHaveBeenCalled();
133+
});
134+
});
135+
136+
describe("GLOBAL scope", () => {
137+
it("should always return GLOBAL buttons", () => {
138+
const globalButtons = [{ ...sampleButton, name: "Global Button" }];
139+
const workspaceButtons = [{ ...sampleButton, name: "Workspace Button" }];
140+
const configReader = createMockConfigReader(workspaceButtons, globalButtons);
141+
142+
const result = resolveButtonsWithFallback({
143+
configReader,
144+
currentTarget: CONFIGURATION_TARGETS.GLOBAL,
145+
});
146+
147+
expect(result.buttons).toEqual(globalButtons);
148+
expect(result.scope).toBe(CONFIGURATION_TARGETS.GLOBAL);
149+
});
150+
151+
it("should return empty array when GLOBAL has no buttons", () => {
152+
const configReader = createMockConfigReader([], []);
153+
154+
const result = resolveButtonsWithFallback({
155+
configReader,
156+
currentTarget: CONFIGURATION_TARGETS.GLOBAL,
157+
});
158+
159+
expect(result.buttons).toEqual([]);
160+
expect(result.scope).toBe(CONFIGURATION_TARGETS.GLOBAL);
161+
});
162+
163+
it("should not check localStorage or workspace", () => {
164+
const localButtons = [{ ...sampleButton, name: "Local Button" }];
165+
const workspaceButtons = [{ ...sampleButton, name: "Workspace Button" }];
166+
const configReader = createMockConfigReader(workspaceButtons, []);
167+
const localStorage = createMockLocalStorage(localButtons);
168+
169+
const result = resolveButtonsWithFallback({
170+
configReader,
171+
currentTarget: CONFIGURATION_TARGETS.GLOBAL,
172+
localStorage,
173+
});
174+
175+
expect(result.buttons).toEqual([]);
176+
expect(result.scope).toBe(CONFIGURATION_TARGETS.GLOBAL);
177+
expect(localStorage.getButtons).not.toHaveBeenCalled();
178+
expect(configReader.getButtonsFromScope).toHaveBeenCalledTimes(1);
179+
expect(configReader.getButtonsFromScope).toHaveBeenCalledWith(
180+
vscode.ConfigurationTarget.Global
181+
);
182+
});
183+
});
184+
185+
describe("edge cases", () => {
186+
it("should return empty GLOBAL when all scopes are empty", () => {
187+
const configReader = createMockConfigReader([], []);
188+
const localStorage = createMockLocalStorage([]);
189+
190+
const result = resolveButtonsWithFallback({
191+
configReader,
192+
currentTarget: CONFIGURATION_TARGETS.LOCAL,
193+
localStorage,
194+
});
195+
196+
expect(result.buttons).toEqual([]);
197+
expect(result.scope).toBe(CONFIGURATION_TARGETS.GLOBAL);
198+
});
199+
200+
it("should handle multiple buttons in returned scope", () => {
201+
const localButtons = [
202+
{ ...sampleButton, id: "1", name: "Button 1" },
203+
{ ...sampleButton, id: "2", name: "Button 2" },
204+
{ ...sampleButton, id: "3", name: "Button 3" },
205+
];
206+
const configReader = createMockConfigReader([], []);
207+
const localStorage = createMockLocalStorage(localButtons);
208+
209+
const result = resolveButtonsWithFallback({
210+
configReader,
211+
currentTarget: CONFIGURATION_TARGETS.LOCAL,
212+
localStorage,
213+
});
214+
215+
expect(result.buttons).toHaveLength(3);
216+
expect(result.buttons).toEqual(localButtons);
217+
});
218+
});
219+
});

0 commit comments

Comments
 (0)