import { expect, test } from '@playwright/test'; import { initMock, settingsJson, statusJson } from '../shared'; test.beforeEach(initMock); test('index page has expected columns control, status, settings', async ({ page }) => { await page.goto('/'); await expect(page.getByRole('heading', { name: 'Control' })).toBeVisible(); await expect(page.getByRole('heading', { name: 'Status' })).toBeVisible(); await expect(page.getByRole('heading', { name: 'Settings' })).toBeVisible(); }); test('index page has working language selector', async ({ page }) => { await page.goto('/'); await expect(page.locator('//*[@id="nav-language-dropdown"]/a')).toBeVisible(); page.locator('//*[@id="nav-language-dropdown"]/a').click(); //*[@id="nav-language-dropdown"]/ul/li[1]/button await expect(page.locator('//*[@id="nav-language-dropdown"]/ul/li[1]/button')).toBeVisible(); page.locator('//*[@id="nav-language-dropdown"]/ul/li[2]/button').click(); await expect(page.getByRole('heading', { name: 'Instellingen' })).toBeVisible(); page.locator('//*[@id="nav-language-dropdown"]/a').click(); page.locator('//*[@id="nav-language-dropdown"]/ul/li[3]/button').click(); await expect(page.getByRole('heading', { name: 'ConfiguraciĆ³n' })).toBeVisible(); }); test('api page has expected load button', async ({ page }) => { await page.goto('/api'); await expect(page.getByRole('button', { name: 'Load' })).toBeVisible(); }); test('timezone can be negative, zero and positive', async ({ page }) => { await page.goto('/'); await page.getByRole('button', { name: 'Show all' }).click(); const tzOffsetField = 'input#tzOffset'; for (const val of ['-10', '0', '42']) { await page.fill(tzOffsetField, val); const resultValue = await page.$eval(tzOffsetField, (input: HTMLInputElement) => input.value); expect(resultValue).toBe(val); await page.getByRole('button', { name: 'Save' }).click(); } }); test('time values can not be zero or negative', async ({ page }) => { await page.goto('/'); await page.getByRole('button', { name: 'Show all' }).click(); for (const field of ['#timePerScreen', '#fullRefreshMin', '#minSecPriceUpd']) { for (const val of ['42', '210']) { await page.fill(field, val); const resultValue = await page.$eval(field, (input: HTMLInputElement) => input.value); expect(resultValue).toBe(val); await page.getByRole('button', { name: 'Save' }).click(); const validationMessage = await page.$eval( field, (input: HTMLInputElement) => input.validationMessage ); expect(validationMessage).not.toContain('Value must be greater'); } for (const val of ['-10', '0']) { await page.fill(field, val); const resultValue = await page.$eval(field, (input: HTMLInputElement) => input.value); expect(resultValue).toBe(val); await page.getByRole('button', { name: 'Save' }).click(); const validationMessage = await page.$eval( field, (input: HTMLInputElement) => input.validationMessage ); expect(validationMessage).toContain('Value must be greater'); } } }); test('info message when fetch eur price is enabled', async ({ page }) => { delete (settingsJson as { actCurrencies?: string[] }).actCurrencies; await page.goto('/'); await page.getByRole('button', { name: 'Show all' }).click(); const inputField = 'input#fetchEurPrice'; const switchElement = await page.locator(inputField); expect(switchElement).toBeTruthy(); const isSwitchEnabled = await switchElement.isChecked(); expect(isSwitchEnabled).toBe(false); await expect(page.getByText('the WS Price connection will show')).toBeHidden(); await switchElement.click(); const isSwitchNowEnabled = await switchElement.isChecked(); expect(isSwitchNowEnabled).toBe(true); await expect(page.getByText('the WS Price connection will show')).toBeVisible(); }); test('npub values will be converted to hex pubkeys', async ({ page }) => { await page.goto('/'); await page.getByRole('button', { name: 'Show all' }).click(); for (const field of ['#nostrZapPubkey']) { for (const val of ['npub1k5f85zx0xdskyayqpfpc0zq6n7vwqjuuxugkayk72fgynp34cs3qfcvqg2']) { await page.fill(field, val); await page.getByLabel('Nostr Relay').click(); const resultValue = await page.$eval(field, (input: HTMLInputElement) => input.value); expect(resultValue).toBe('b5127a08cf33616274800a4387881a9f98e04b9c37116e92de5250498635c422'); } } }); test('empty nostr relay field is not accepted', async ({ page }) => { await page.goto('/'); await page.getByRole('button', { name: 'Show all' }).click(); const nostrRelayField = page.getByLabel('Nostr Relay'); nostrRelayField.fill(''); await page.getByRole('button', { name: 'Save' }).click(); const validationMessage = await nostrRelayField.evaluate((el) => el.validationMessage); expect(validationMessage).toContain('Please fill out this field'); }); test('screens should be able to change', async ({ page }) => { await page.goto('/'); await expect(page.getByRole('button', { name: 'Sats per Dollar' })).toBeVisible(); const responsePromise = page.waitForRequest('*/**/api/show/screen/*'); await page.getByRole('button', { name: 'Sats per Dollar' }).click(); const response = await responsePromise; expect(response.url()).toContain('api/show/screen/1'); }); test('parse all types of EPD content correctly', async ({ page }) => { statusJson.data[2] = '123'; await page.route('**/events', (route) => { const newStatus = statusJson; newStatus.data = ['BLOCK/HEIGHT', '8', '123', '0', '8', '1', '5']; // Respond with a custom SSE message route.fulfill({ status: 200, contentType: 'text/event-stream', json: `${JSON.stringify(newStatus)}\n\n` }); }); await page.goto('/'); await expect(page.getByRole('heading', { name: 'Status' })).toBeVisible(); await page.waitForSelector('#timerStatusText:has-text("running")'); await page.waitForSelector('#btclock-wrapper > div > div:nth-child(1)'); expect(statusJson.data[0]).toContain('/'); await expect(page.locator('#btclock-wrapper > div > div:nth-child(1)')).toBeTruthy(); await expect(page.locator('#btclock-wrapper > div > div:nth-child(1)')).toHaveClass('splitText'); expect(statusJson.data[1]).toHaveLength(1); await expect(page.locator('#btclock-wrapper > div > div:nth-child(2)')).toHaveClass('digit'); expect(statusJson.data[2]).toHaveLength(3); await expect(page.locator('#btclock-wrapper > div > div:nth-child(3)')).toHaveClass('mediumText'); }); test('should work with more than 7 screens', async ({ page }) => { statusJson.data[2] = '1'; statusJson.numScreens = 9; settingsJson.numScreens = 9; statusJson.data.splice(1, 0, ' ', ' '); await page.goto('/'); await expect(page.getByRole('heading', { name: 'Status' })).toBeVisible(); await page.waitForSelector('#timerStatusText:has-text("running")'); await expect(page.locator('#btclock-wrapper > div > div:nth-child(9)')).toBeTruthy(); await expect(page.locator('#customText')).toHaveAttribute( 'maxlength', statusJson.numScreens.toString() ); });