Skip to content

Commit db489cc

Browse files
committed
test: add more llm-provider ui tests
1 parent 413fe12 commit db489cc

File tree

4 files changed

+129
-9
lines changed

4 files changed

+129
-9
lines changed

frontend_omni/playwright.config.ts

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,10 @@ export default defineConfig({
1919
{
2020
name: "chromium",
2121
use: { ...devices["Desktop Chrome"] },
22-
testIgnore: "**/mock-openai-server.spec.ts",
2322
},
2423
{
2524
name: "firefox",
2625
use: { ...devices["Desktop Firefox"] },
27-
testIgnore: "**/mock-openai-server.spec.ts",
28-
},
29-
{
30-
name: "mock-tests",
31-
testMatch: "**/mock-openai-server.spec.ts",
32-
use: { ...devices["Desktop Chrome"] },
33-
workers: 1, // Run serially
3426
},
3527
// Support this later at some point
3628
// {

frontend_omni/src/modules/llm-provider-management/llm-provider-management.spec.ts

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,122 @@ test.describe("LLM Provider Management", () => {
4040
page.locator('input[value="http://localhost:3001"]'),
4141
).toBeVisible();
4242
});
43+
44+
test("should add two providers", async ({ page }) => {
45+
await expect(page).toHaveTitle(/modAI/);
46+
await page.getByText("Global Settings").click();
47+
await page.getByText("LLM Providers").click();
48+
49+
// Add first provider
50+
await page.getByText("Add Provider").click();
51+
await page.getByLabel("Provider Name").fill("Provider One");
52+
await page.getByLabel("Base URL").fill("http://localhost:3001");
53+
await page.getByLabel("API Key").fill("key1");
54+
await page.getByText("Create Provider").click();
55+
await expect(page.getByText("Add Provider")).toBeVisible();
56+
await expect(page.getByText("Provider One")).toBeVisible();
57+
58+
// Add second provider
59+
await page.getByText("Add Provider").click();
60+
await page.getByLabel("Provider Name").fill("Provider Two");
61+
await page.getByLabel("Base URL").fill("http://localhost:3002");
62+
await page.getByLabel("API Key").fill("key2");
63+
await page.getByText("Create Provider").click();
64+
await expect(page.getByText("Add Provider")).toBeVisible();
65+
await expect(page.getByText("Provider Two")).toBeVisible();
66+
67+
// Verify both are there
68+
await expect(page.getByText("Provider One")).toBeVisible();
69+
await expect(page.getByText("Provider Two")).toBeVisible();
70+
});
71+
72+
test("should not add provider with duplicate name", async ({ page }) => {
73+
await expect(page).toHaveTitle(/modAI/);
74+
await page.getByText("Global Settings").click();
75+
await page.getByText("LLM Providers").click();
76+
77+
// Add first provider
78+
await page.getByText("Add Provider").click();
79+
await page.getByLabel("Provider Name").fill("Duplicate Provider");
80+
await page.getByLabel("Base URL").fill("http://localhost:3001");
81+
await page.getByLabel("API Key").fill("key1");
82+
await page.getByText("Create Provider").click();
83+
await expect(page.getByText("Add Provider")).toBeVisible();
84+
await expect(page.getByText("Duplicate Provider")).toBeVisible();
85+
86+
// Add another with same name (should work in no-backend mode)
87+
await page.getByText("Add Provider").click();
88+
await page.getByLabel("Provider Name").fill("Duplicate Provider");
89+
await page.getByLabel("Base URL").fill("http://localhost:3002");
90+
await page.getByLabel("API Key").fill("key2");
91+
await page.getByText("Create Provider").click();
92+
93+
// Expect two providers with same name
94+
await expect(page.getByText("Provider with name 'Duplicate Provider' already exists")).toBeVisible();
95+
});
96+
97+
test("should update a provider", async ({ page }) => {
98+
await expect(page).toHaveTitle(/modAI/);
99+
await page.getByText("Global Settings").click();
100+
await page.getByText("LLM Providers").click();
101+
102+
// Add provider
103+
await page.getByText("Add Provider").click();
104+
await page.getByLabel("Provider Name").fill("Update Provider");
105+
await page.getByLabel("Base URL").fill("http://localhost:3001");
106+
await page.getByLabel("API Key").fill("key1");
107+
await page.getByText("Create Provider").click();
108+
await expect(page.getByText("Add Provider")).toBeVisible();
109+
await expect(page.getByText("Update Provider")).toBeVisible();
110+
111+
// Click on the provider to edit
112+
await page.getByText("Update Provider").click();
113+
114+
// Modify fields
115+
await page.getByLabel("Base URL").fill("http://localhost:3003");
116+
await page.getByLabel("API Key").fill("updated-key");
117+
118+
// Click update button
119+
await page.getByText("Save").click();
120+
121+
// Verify updated - go back and check
122+
await expect(page.getByText("Add Provider")).toBeVisible();
123+
await page.getByText("Update Provider").click();
124+
await expect(
125+
page.locator('input[value="http://localhost:3003"]'),
126+
).toBeVisible();
127+
});
128+
129+
test("should delete a provider", async ({ page }) => {
130+
await expect(page).toHaveTitle(/modAI/);
131+
await page.getByText("Global Settings").click();
132+
await page.getByText("LLM Providers").click();
133+
134+
// Add provider
135+
await page.getByText("Add Provider").click();
136+
await page.getByLabel("Provider Name").fill("Delete Provider");
137+
await page.getByLabel("Base URL").fill("http://localhost:3001");
138+
await page.getByLabel("API Key").fill("key1");
139+
await page.getByText("Create Provider").click();
140+
await expect(page.getByText("Add Provider")).toBeVisible();
141+
await expect(page.getByText("Delete Provider")).toBeVisible();
142+
143+
// Click on provider to see delete option
144+
await page.getByText("Delete Provider").click();
145+
146+
// Click delete button (the one with trash icon)
147+
await page
148+
.locator("button")
149+
.filter({ has: page.locator(".lucide-trash2") })
150+
.click();
151+
152+
// Click the delete button in the confirmation dialog
153+
await page
154+
.getByRole("alertdialog")
155+
.getByText("Delete", { exact: true })
156+
.click();
157+
158+
// Verify gone
159+
await expect(page.getByText("Delete Provider")).not.toBeVisible();
160+
});
43161
});

frontend_omni/src/modules/llm-provider-service/LLMNoBackendProviderService.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,11 @@ class LLMNoBackendProviderService implements ProviderService {
139139
? providerType
140140
: providerType.value;
141141

142+
// Check if a provider with the same name already exists
143+
if (this.providers.some((provider) => provider.name === data.name)) {
144+
throw new Error(`Provider with name '${data.name}' already exists`);
145+
}
146+
142147
const now = new Date().toISOString();
143148
const newProvider: Provider = {
144149
id: `llm_${typeValue}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
@@ -179,6 +184,11 @@ class LLMNoBackendProviderService implements ProviderService {
179184
throw new Error(`Provider not found: ${providerId}`);
180185
}
181186

187+
// Check if another provider with the same name already exists
188+
if (this.providers.some((provider) => provider.name === data.name && provider.id !== providerId)) {
189+
throw new Error(`Provider with name '${data.name}' already exists`);
190+
}
191+
182192
const provider = this.providers[providerIndex];
183193
const updatedProvider: Provider = {
184194
...provider,

frontend_omni/vitest.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export default defineConfig({
2020
test: {
2121
environment: "jsdom",
2222
// Include only unit/integration test files from src directory
23-
include: ["src/**/*.{test,spec}.{ts,tsx}"],
23+
include: ["src/**/*.test.{ts,tsx}"],
2424
// Explicitly exclude playwright test files
2525
exclude: ["tests/**", "playwright-report/**", "test-results/**"],
2626
},

0 commit comments

Comments
 (0)