fix(ui): reflect update availability and config changes; expand mobile player metadata
ci / api / api (push) Successful in 50s
ci / contract / contract (сгенерированный код совпадает с openapi.yaml) (push) Successful in 1m0s
ci / db / db (push) Successful in 58s
ci / mobile / mobile (Metro-бандл Android) (push) Successful in 1m27s
ci / docker / docker (образы собираются — их сервер собирает сам при обновлении) (push) Successful in 1m39s
ci / ts / ts (packages + web) (push) Successful in 2m40s
ci / api / api (push) Successful in 50s
ci / contract / contract (сгенерированный код совпадает с openapi.yaml) (push) Successful in 1m0s
ci / db / db (push) Successful in 58s
ci / mobile / mobile (Metro-бандл Android) (push) Successful in 1m27s
ci / docker / docker (образы собираются — их сервер собирает сам при обновлении) (push) Successful in 1m39s
ci / ts / ts (packages + web) (push) Successful in 2m40s
This commit is contained in:
1 parent
bc55528afd
commit
a6c9fd8a00
30 files changed
+833
-395
No files matched your search
@@ -102,7 +102,15 @@ test('mobile player keeps the island above navigation and exposes the queue', as
|
||||
await page.getByRole('listitem').first().click();
|
||||
const player = page.getByRole('contentinfo', { name: 'Плеер' });
|
||||
await expect(player.getByRole('button', { name: 'Очередь', exact: true })).toBeVisible();
|
||||
expect((await player.getByText('Группа крови', { exact: true }).boundingBox())!.width).toBeGreaterThan(40);
|
||||
expect((await player.getByText('Группа крови', { exact: true }).boundingBox())!.width).toBeGreaterThan(220);
|
||||
const artist = player.getByRole('link', { name: 'Кино', exact: true });
|
||||
await expect(artist).toBeVisible();
|
||||
const artistArea = await artist.locator('..').boundingBox();
|
||||
expect(artistArea!.width).toBeGreaterThan(220);
|
||||
const trackInfo = await player.getByText('Группа крови', { exact: true }).boundingBox();
|
||||
const play = await player.getByRole('button', { name: /^(Пауза|Слушать)$/ }).boundingBox();
|
||||
expect(trackInfo!.y + trackInfo!.height).toBeLessThanOrEqual(play!.y);
|
||||
await page.screenshot({ path: info.outputPath('player-readable.png') });
|
||||
await fits(page);
|
||||
await page.getByRole('button', { name: 'Меню профиля' }).click();
|
||||
await page.getByRole('menuitem', { name: 'Настройки', exact: true }).click();
|
||||
|
||||
@@ -34,7 +34,9 @@ for (const width of [320, 1280]) {
|
||||
await page.getByRole('button', { name: 'Поделиться плейлистом', exact: true }).click();
|
||||
await expect(page.getByRole('status')).toHaveText('Ссылка на плейлист скопирована');
|
||||
const sharedUrl = await page.evaluate(() => navigator.clipboard.readText());
|
||||
expect(sharedUrl).toMatch(/^http:\/\/127\.0\.0\.1:4173\/shared\/playlist\/[a-f0-9-]+$/);
|
||||
const shared = new URL(sharedUrl);
|
||||
expect(shared.origin).toBe(new URL(page.url()).origin);
|
||||
expect(shared.pathname).toMatch(/^\/shared\/playlist\/[a-f0-9-]+$/);
|
||||
await expect(page.getByRole('button', { name: 'Отключить доступ по ссылке', exact: true })).toBeVisible();
|
||||
|
||||
await expect.poll(() => page.evaluate(() => {
|
||||
|
||||
@@ -27,9 +27,9 @@ test('admin selects repository and version, confirms and sees persistent job log
|
||||
await expect(dialog).toContainText('Тестовая репа');
|
||||
await expect(dialog).toContainText('v1.10.0');
|
||||
await dialog.getByRole('button', { name: 'Установить обновление' }).click();
|
||||
await expect(page.getByRole('status').filter({ hasText: 'Выполняется' })).toBeVisible();
|
||||
await expect(page.getByRole('status').filter({ hasText: /^Выполняется$/ })).toBeVisible();
|
||||
await expect(page.getByLabel('Журнал выполнения')).toContainText('build and restart');
|
||||
await expect(page.getByRole('button', { name: 'Установить обновление', exact: true })).toBeDisabled();
|
||||
await expect(page.getByRole('button', { name: 'Установить обновление', exact: true })).not.toBeVisible();
|
||||
await page.screenshot({ path: 'test-results/server-updates.png', fullPage: true });
|
||||
});
|
||||
|
||||
@@ -37,12 +37,15 @@ test('config keeps secret unchanged, saves local override and applies separately
|
||||
await login(page, 'mobile-admin', '/admin/config');
|
||||
await expect(page.getByRole('heading', { name: 'Конфигурация', exact: true })).toBeVisible();
|
||||
await expect(page.getByLabel('GITEA_TOKEN · config.local', { exact: true })).toHaveValue('');
|
||||
await expect(page.getByRole('button', { name: 'Сохранить', exact: true })).not.toBeVisible();
|
||||
await page.getByLabel('LOG_LEVEL · config.local', { exact: true }).fill('debug');
|
||||
await expect(page.getByText('В .env есть значение:', { exact: false })).toBeVisible();
|
||||
await page.getByLabel('TRAIN_HOUR · config.local', { exact: true }).fill('6');
|
||||
await expect(page.getByRole('button', { name: 'Применить и перезапустить', exact: true })).toBeDisabled();
|
||||
await expect(page.getByRole('button', { name: 'Применить и перезапустить', exact: true })).not.toBeVisible();
|
||||
await page.getByRole('button', { name: 'Сохранить', exact: true }).click();
|
||||
await expect(page.getByText('Изменения сохранены в config.local', { exact: true })).toBeVisible();
|
||||
await expect(page.getByRole('button', { name: 'Сохранить', exact: true })).not.toBeVisible();
|
||||
await expect(page.getByRole('button', { name: 'Отменить правки', exact: true })).not.toBeVisible();
|
||||
await expect(page.getByLabel('GITEA_TOKEN · config.local', { exact: true })).toHaveAttribute('placeholder', 'Секрет сохранён');
|
||||
await expect(page.getByText('Выполняется', { exact: true })).not.toBeVisible();
|
||||
await page.getByRole('main').evaluate((element) => { element.scrollTop = 0; });
|
||||
@@ -64,3 +67,61 @@ test('ordinary user is redirected away from server management', async ({ page })
|
||||
await login(page, 'alice', '/admin/updates');
|
||||
await expect(page).toHaveURL('/');
|
||||
});
|
||||
|
||||
|
||||
test('installed main and release show no install action; another version can be installed', async ({ page }) => {
|
||||
await login(page, 'mobile-admin', '/admin/updates');
|
||||
await expect(page.getByRole('button', { name: 'Установить обновление', exact: true })).toBeVisible();
|
||||
await page.getByRole('button', { name: 'main', exact: true }).click();
|
||||
await expect(page.getByText('Эта версия уже установлена — обновлений нет', { exact: true })).toBeVisible();
|
||||
await expect(page.getByRole('button', { name: 'Установить обновление', exact: true })).not.toBeVisible();
|
||||
await page.getByRole('button', { name: 'Выбрать версию', exact: true }).click();
|
||||
await expect(page.getByText('Выберите версию для проверки', { exact: true })).toBeVisible();
|
||||
await page.getByLabel('Версия', { exact: true }).selectOption('v1.9.0');
|
||||
await expect(page.getByText('Эта версия уже установлена — обновлений нет', { exact: true })).toBeVisible();
|
||||
await expect(page.getByRole('button', { name: 'Установить обновление', exact: true })).not.toBeVisible();
|
||||
await page.getByLabel('Версия', { exact: true }).selectOption('v1.10.0');
|
||||
await expect(page.getByText('Доступно обновление', { exact: true })).toBeVisible();
|
||||
await expect(page.getByRole('button', { name: 'Установить обновление', exact: true })).toBeVisible();
|
||||
});
|
||||
|
||||
test('explicit check bypasses cache and hides install action until the check finishes', async ({ page }) => {
|
||||
await login(page, 'mobile-admin', '/admin/updates');
|
||||
await expect(page.getByRole('button', { name: 'Установить обновление', exact: true })).toBeVisible();
|
||||
await page.evaluate(() => {
|
||||
const original = window.fetch;
|
||||
window.fetch = async (input, init) => {
|
||||
const request = new Request(input, init);
|
||||
if (request.url.includes('/api/v1/admin/server/updates') && request.url.includes('fresh=true')) {
|
||||
await new Promise((resolve) => setTimeout(resolve, 1000));
|
||||
const response = await original(input, init);
|
||||
const data = await response.json();
|
||||
return new Response(JSON.stringify({ ...data, update_state: 'current', target_commit: data.current_commit }), { headers: { 'Content-Type': 'application/json' } });
|
||||
}
|
||||
return original(input, init);
|
||||
};
|
||||
});
|
||||
await page.getByRole('button', { name: 'Проверить обновления', exact: true }).click();
|
||||
await expect(page.getByText('Проверяем выбранную версию…', { exact: true })).toBeVisible();
|
||||
await expect(page.getByRole('button', { name: 'Установить обновление', exact: true })).not.toBeVisible();
|
||||
await expect(page.getByText('Эта версия уже установлена — обновлений нет', { exact: true })).toBeVisible();
|
||||
});
|
||||
|
||||
test('saving panel disappears when all edited values return to their original state', async ({ page }) => {
|
||||
await login(page, 'mobile-admin', '/admin/config');
|
||||
await expect(page.getByRole('heading', { name: 'Конфигурация', exact: true })).toBeVisible();
|
||||
const save = page.getByRole('button', { name: 'Сохранить', exact: true });
|
||||
const apply = page.getByRole('button', { name: 'Применить и перезапустить', exact: true });
|
||||
await expect(save).not.toBeVisible();
|
||||
await expect(apply).not.toBeVisible();
|
||||
const field = page.getByLabel('TRAIN_HOUR · config.local', { exact: true });
|
||||
await field.fill('6');
|
||||
await expect(save).toBeVisible();
|
||||
await field.clear();
|
||||
await expect(save).not.toBeVisible();
|
||||
await expect(apply).not.toBeVisible();
|
||||
await field.fill('7');
|
||||
await page.getByRole('button', { name: 'Отменить правки', exact: true }).click();
|
||||
await expect(save).not.toBeVisible();
|
||||
await expect(field).toHaveValue('');
|
||||
});
|
||||
Reference in new issue
Block a user