Skip to content

Commit 5e92ccb

Browse files
committed
tests update
1 parent 3f500db commit 5e92ccb

File tree

6 files changed

+884
-45
lines changed

6 files changed

+884
-45
lines changed

e2e/admin-settings.spec.ts

Lines changed: 0 additions & 33 deletions
This file was deleted.

e2e/app-config.spec.ts

Lines changed: 261 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,261 @@
1+
import { expect, test } from '@playwright/test'
2+
import { assertAndDismissNoty, login, navigateToAppSettings } from './helpers.js'
3+
4+
test.describe('OMDB Settings', () => {
5+
test.beforeEach(async ({ page }) => {
6+
await page.goto('/')
7+
await login(page)
8+
await navigateToAppSettings(page)
9+
// Wait for the OMDB settings page to load
10+
await page.waitForSelector('text=OMDB Settings')
11+
})
12+
13+
test('should display OMDB settings form', async ({ page }) => {
14+
// Verify OMDB settings heading is visible (using text selector to pierce shadow DOM)
15+
await expect(page.locator('text=OMDB Settings').first()).toBeVisible()
16+
17+
// Verify form fields are present (use locator chain through shadow DOM)
18+
const omdbPage = page.locator('omdb-settings-page')
19+
const apiKeyInput = omdbPage.locator('input[name="apiKey"]')
20+
await expect(apiKeyInput).toBeVisible()
21+
22+
const searchCheckbox = omdbPage.locator('input[name="trySearchMovieFromTitle"]')
23+
await expect(searchCheckbox).toBeVisible()
24+
25+
const autoDownloadCheckbox = omdbPage.locator('input[name="autoDownloadMetadata"]')
26+
await expect(autoDownloadCheckbox).toBeVisible()
27+
28+
const saveButton = omdbPage.getByRole('button', { name: /save settings/i })
29+
await expect(saveButton).toBeVisible()
30+
})
31+
32+
test('should toggle API key visibility', async ({ page }) => {
33+
const omdbPage = page.locator('omdb-settings-page')
34+
const apiKeyInput = omdbPage.locator('input[name="apiKey"]')
35+
const toggleButton = omdbPage.locator('[data-toggle-visibility]')
36+
37+
// Initially password should be hidden
38+
await expect(apiKeyInput).toHaveAttribute('type', 'password')
39+
40+
// Click toggle to show
41+
await toggleButton.click()
42+
await expect(apiKeyInput).toHaveAttribute('type', 'text')
43+
44+
// Click toggle to hide again
45+
await toggleButton.click()
46+
await expect(apiKeyInput).toHaveAttribute('type', 'password')
47+
})
48+
49+
test('should save OMDB settings successfully', async ({ page }) => {
50+
const omdbPage = page.locator('omdb-settings-page')
51+
const apiKeyInput = omdbPage.locator('input[name="apiKey"]')
52+
const searchCheckbox = omdbPage.locator('input[name="trySearchMovieFromTitle"]')
53+
const autoDownloadCheckbox = omdbPage.locator('input[name="autoDownloadMetadata"]')
54+
55+
// Fill in the form
56+
await apiKeyInput.fill('test-api-key-e2e')
57+
58+
// Ensure checkboxes are in a known state
59+
if (!(await searchCheckbox.isChecked())) {
60+
await searchCheckbox.check()
61+
}
62+
if (!(await autoDownloadCheckbox.isChecked())) {
63+
await autoDownloadCheckbox.check()
64+
}
65+
66+
// Submit the form
67+
const saveButton = omdbPage.getByRole('button', { name: /save settings/i })
68+
await saveButton.click()
69+
70+
// Verify success notification
71+
await assertAndDismissNoty(page, 'OMDB settings saved successfully')
72+
})
73+
74+
test('should persist OMDB settings after save', async ({ page }) => {
75+
const omdbPage = page.locator('omdb-settings-page')
76+
const apiKeyInput = omdbPage.locator('input[name="apiKey"]')
77+
78+
// Fill in a unique API key
79+
const testApiKey = `test-api-key-${Date.now()}`
80+
await apiKeyInput.fill(testApiKey)
81+
82+
// Submit the form
83+
const saveButton = omdbPage.getByRole('button', { name: /save settings/i })
84+
await saveButton.click()
85+
await assertAndDismissNoty(page, 'OMDB settings saved successfully')
86+
87+
// Navigate away and back (simulates leaving and returning)
88+
await page.goto('/')
89+
await page.waitForSelector('text=Apps')
90+
91+
// Navigate back to OMDB settings
92+
await navigateToAppSettings(page)
93+
await page.waitForSelector('text=OMDB Settings')
94+
95+
// Verify the value is persisted
96+
const apiKeyInputAfter = page.locator('omdb-settings-page').locator('input[name="apiKey"]')
97+
await expect(apiKeyInputAfter).toHaveValue(testApiKey)
98+
})
99+
})
100+
101+
test.describe('Streaming Settings', () => {
102+
test.beforeEach(async ({ page }) => {
103+
await page.goto('/')
104+
await login(page)
105+
await navigateToAppSettings(page)
106+
await page.waitForSelector('text=OMDB Settings')
107+
108+
// Navigate to streaming settings
109+
const streamingMenuItem = page.getByText('Streaming Settings')
110+
await streamingMenuItem.click()
111+
await page.waitForSelector('text=📺 Streaming Settings')
112+
})
113+
114+
test('should display streaming settings form', async ({ page }) => {
115+
// Verify streaming settings heading (using text selector to pierce shadow DOM)
116+
await expect(page.locator('text=📺 Streaming Settings').first()).toBeVisible()
117+
118+
const streamingPage = page.locator('streaming-settings-page')
119+
120+
// Verify form fields are present
121+
const extractSubtitlesCheckbox = streamingPage.locator('input[name="autoExtractSubtitles"]')
122+
await expect(extractSubtitlesCheckbox).toBeVisible()
123+
124+
const fullSyncCheckbox = streamingPage.locator('input[name="fullSyncOnStartup"]')
125+
await expect(fullSyncCheckbox).toBeVisible()
126+
127+
const watchFilesCheckbox = streamingPage.locator('input[name="watchFiles"]')
128+
await expect(watchFilesCheckbox).toBeVisible()
129+
130+
const presetSelect = streamingPage.locator('select[name="preset"]')
131+
await expect(presetSelect).toBeVisible()
132+
133+
const threadsInput = streamingPage.locator('input[name="threads"]')
134+
await expect(threadsInput).toBeVisible()
135+
136+
const saveButton = streamingPage.getByRole('button', { name: /save settings/i })
137+
await expect(saveButton).toBeVisible()
138+
})
139+
140+
test('should save streaming settings successfully', async ({ page }) => {
141+
const streamingPage = page.locator('streaming-settings-page')
142+
const extractSubtitlesCheckbox = streamingPage.locator('input[name="autoExtractSubtitles"]')
143+
const presetSelect = streamingPage.locator('select[name="preset"]')
144+
const threadsInput = streamingPage.locator('input[name="threads"]')
145+
146+
// Toggle checkbox
147+
if (!(await extractSubtitlesCheckbox.isChecked())) {
148+
await extractSubtitlesCheckbox.check()
149+
}
150+
151+
// Select preset
152+
await presetSelect.selectOption('fast')
153+
154+
// Set threads
155+
await threadsInput.fill('8')
156+
157+
// Submit the form
158+
const saveButton = streamingPage.getByRole('button', { name: /save settings/i })
159+
await saveButton.click()
160+
161+
// Verify success notification
162+
await assertAndDismissNoty(page, 'Streaming settings saved successfully')
163+
})
164+
165+
test('should persist streaming settings after save', async ({ page }) => {
166+
const streamingPage = page.locator('streaming-settings-page')
167+
const threadsInput = streamingPage.locator('input[name="threads"]')
168+
const presetSelect = streamingPage.locator('select[name="preset"]')
169+
170+
// Set specific values
171+
await threadsInput.fill('12')
172+
await presetSelect.selectOption('veryfast')
173+
174+
// Submit the form
175+
const saveButton = streamingPage.getByRole('button', { name: /save settings/i })
176+
await saveButton.click()
177+
await assertAndDismissNoty(page, 'Streaming settings saved successfully')
178+
179+
// Navigate away and back (simulates leaving and returning)
180+
await page.goto('/')
181+
await page.waitForSelector('text=Apps')
182+
183+
// Navigate back to app settings
184+
await navigateToAppSettings(page)
185+
await page.waitForSelector('text=OMDB Settings')
186+
187+
// Navigate to streaming settings
188+
const streamingMenuItem = page.getByText('Streaming Settings')
189+
await streamingMenuItem.click()
190+
await page.waitForSelector('text=📺 Streaming Settings')
191+
192+
// Verify the values are persisted
193+
const threadsInputAfter = page.locator('streaming-settings-page').locator('input[name="threads"]')
194+
const presetSelectAfter = page.locator('streaming-settings-page').locator('select[name="preset"]')
195+
await expect(threadsInputAfter).toHaveValue('12')
196+
await expect(presetSelectAfter).toHaveValue('veryfast')
197+
})
198+
199+
test('should validate threads input', async ({ page }) => {
200+
const streamingPage = page.locator('streaming-settings-page')
201+
const threadsInput = streamingPage.locator('input[name="threads"]')
202+
203+
// Verify min/max attributes
204+
await expect(threadsInput).toHaveAttribute('min', '1')
205+
await expect(threadsInput).toHaveAttribute('max', '64')
206+
})
207+
})
208+
209+
test.describe('Settings Navigation', () => {
210+
test.beforeEach(async ({ page }) => {
211+
await page.goto('/')
212+
await login(page)
213+
})
214+
215+
test('should navigate between OMDB and Streaming settings', async ({ page }) => {
216+
await navigateToAppSettings(page)
217+
await page.waitForSelector('text=OMDB Settings')
218+
219+
// Verify we're on OMDB settings by default (using text selector to pierce shadow DOM)
220+
await expect(page.locator('text=🎬 OMDB Settings').first()).toBeVisible()
221+
222+
// Navigate to Streaming settings
223+
const streamingMenuItem = page.getByText('Streaming Settings')
224+
await streamingMenuItem.click()
225+
await page.waitForSelector('text=📺 Streaming Settings')
226+
227+
await expect(page.locator('text=📺 Streaming Settings').first()).toBeVisible()
228+
229+
// Navigate back to OMDB settings
230+
const omdbMenuItem = page.getByText('OMDB Settings')
231+
await omdbMenuItem.click()
232+
await page.waitForSelector('text=🎬 OMDB Settings')
233+
234+
await expect(page.locator('text=🎬 OMDB Settings').first()).toBeVisible()
235+
})
236+
237+
test('should highlight active menu item', async ({ page }) => {
238+
await navigateToAppSettings(page)
239+
await page.waitForSelector('text=OMDB Settings')
240+
241+
// Check that OMDB menu item is visible
242+
const omdbMenuItem = page.locator('settings-menu-item').filter({ hasText: 'OMDB Settings' })
243+
await expect(omdbMenuItem).toBeVisible()
244+
245+
// Navigate to streaming
246+
const streamingMenuItem = page.getByText('Streaming Settings')
247+
await streamingMenuItem.click()
248+
249+
// Verify URL changed
250+
await expect(page).toHaveURL(/\/app-settings\/streaming/)
251+
})
252+
253+
test('should redirect from base /app-settings to /app-settings/omdb', async ({ page }) => {
254+
// Navigate to app settings via UI and verify default sub-route
255+
await navigateToAppSettings(page)
256+
await page.waitForSelector('text=OMDB Settings')
257+
258+
// Should be on the omdb settings sub-route
259+
await expect(page).toHaveURL(/\/app-settings\/omdb/)
260+
})
261+
})

e2e/helpers.ts

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -60,20 +60,30 @@ export const navigateToUserSettings = async (page: Page) => {
6060
await expect(settingsPage).toBeVisible()
6161
}
6262

63-
export const navigateToAdminSettings = async (page: Page) => {
63+
export const navigateToAppSettings = async (page: Page) => {
6464
// Click on the user avatar to open the menu
6565
const userAvatar = page.locator('[style*="border-radius: 50%"][style*="cursor: pointer"]')
66+
await expect(userAvatar).toBeVisible()
6667
await userAvatar.click()
6768

68-
// Click on Admin Settings option (only visible to admin users)
69-
const adminSettingsButton = page.getByRole('button', { name: /admin settings/i })
70-
await adminSettingsButton.click()
69+
// Click on Application Settings option (only visible to admin users)
70+
const appSettingsButton = page.getByRole('button', { name: /application settings/i })
71+
await expect(appSettingsButton).toBeVisible()
72+
await appSettingsButton.click()
73+
74+
// Wait for URL to change to app-settings
75+
await page.waitForURL(/\/app-settings/)
7176

72-
// Verify we're on the admin settings page
73-
const adminSettingsPage = page.locator('admin-settings-page')
74-
await expect(adminSettingsPage).toBeVisible()
77+
// Verify we're on the app settings page (may need to wait for lazy load)
78+
const appSettingsPage = page.locator('app-settings-page')
79+
await expect(appSettingsPage).toBeVisible({ timeout: 10000 })
7580
}
7681

82+
/**
83+
* @deprecated Use navigateToAppSettings instead
84+
*/
85+
export const navigateToAdminSettings = navigateToAppSettings
86+
7787
export const uploadFile = async (page: Page, filePath: string, mime: string) => {
7888
const fileContent = await readFile(filePath, { encoding: 'utf-8' })
7989
const fileName = basename(filePath)

0 commit comments

Comments
 (0)