mirror of
https://github.com/imputnet/cobalt.git
synced 2025-07-18 11:18:28 +00:00
WIP tests
This commit is contained in:
parent
b04c204492
commit
9106b4f511
@ -119,6 +119,9 @@ importers:
|
||||
'@fontsource/redaction-10':
|
||||
specifier: ^5.0.2
|
||||
version: 5.0.2
|
||||
'@playwright/test':
|
||||
specifier: ^1.47.1
|
||||
version: 1.47.1
|
||||
'@sveltejs/adapter-static':
|
||||
specifier: ^3.0.2
|
||||
version: 3.0.2(@sveltejs/kit@2.5.19(@sveltejs/vite-plugin-svelte@3.1.1(svelte@4.2.18)(vite@5.3.5(@types/node@20.14.14)))(svelte@4.2.18)(vite@5.3.5(@types/node@20.14.14)))
|
||||
@ -135,7 +138,7 @@ importers:
|
||||
specifier: ^2.1.25
|
||||
version: 2.1.25
|
||||
'@types/node':
|
||||
specifier: ^20.14.10
|
||||
specifier: ^20.14.14
|
||||
version: 20.14.14
|
||||
compare-versions:
|
||||
specifier: ^6.1.0
|
||||
@ -561,6 +564,11 @@ packages:
|
||||
resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
|
||||
engines: {node: '>=14'}
|
||||
|
||||
'@playwright/test@1.47.1':
|
||||
resolution: {integrity: sha512-dbWpcNQZ5nj16m+A5UNScYx7HX5trIy7g4phrcitn+Nk83S32EBX/CLU4hiF4RGKX/yRc93AAqtfaXB7JWBd4Q==}
|
||||
engines: {node: '>=18'}
|
||||
hasBin: true
|
||||
|
||||
'@polka/url@1.0.0-next.25':
|
||||
resolution: {integrity: sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ==}
|
||||
|
||||
@ -1320,6 +1328,11 @@ packages:
|
||||
fs.realpath@1.0.0:
|
||||
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
|
||||
|
||||
fsevents@2.3.2:
|
||||
resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==}
|
||||
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
|
||||
os: [darwin]
|
||||
|
||||
fsevents@2.3.3:
|
||||
resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
|
||||
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
|
||||
@ -1749,6 +1762,16 @@ packages:
|
||||
resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==}
|
||||
engines: {node: '>= 6'}
|
||||
|
||||
playwright-core@1.47.1:
|
||||
resolution: {integrity: sha512-i1iyJdLftqtt51mEk6AhYFaAJCDx0xQ/O5NU8EKaWFgMjItPVma542Nh/Aq8aLCjIJSzjaiEQGW/nyqLkGF1OQ==}
|
||||
engines: {node: '>=18'}
|
||||
hasBin: true
|
||||
|
||||
playwright@1.47.1:
|
||||
resolution: {integrity: sha512-SUEKi6947IqYbKxRiqnbUobVZY4bF1uu+ZnZNJX9DfU1tlf2UhWfvVjLf01pQx9URsOr18bFVUKXmanYWhbfkw==}
|
||||
engines: {node: '>=18'}
|
||||
hasBin: true
|
||||
|
||||
postcss-load-config@6.0.1:
|
||||
resolution: {integrity: sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==}
|
||||
engines: {node: '>= 18'}
|
||||
@ -2525,6 +2548,10 @@ snapshots:
|
||||
'@pkgjs/parseargs@0.11.0':
|
||||
optional: true
|
||||
|
||||
'@playwright/test@1.47.1':
|
||||
dependencies:
|
||||
playwright: 1.47.1
|
||||
|
||||
'@polka/url@1.0.0-next.25': {}
|
||||
|
||||
'@rollup/rollup-android-arm-eabi@4.19.2':
|
||||
@ -3342,6 +3369,9 @@ snapshots:
|
||||
|
||||
fs.realpath@1.0.0: {}
|
||||
|
||||
fsevents@2.3.2:
|
||||
optional: true
|
||||
|
||||
fsevents@2.3.3:
|
||||
optional: true
|
||||
|
||||
@ -3709,6 +3739,14 @@ snapshots:
|
||||
|
||||
pirates@4.0.6: {}
|
||||
|
||||
playwright-core@1.47.1: {}
|
||||
|
||||
playwright@1.47.1:
|
||||
dependencies:
|
||||
playwright-core: 1.47.1
|
||||
optionalDependencies:
|
||||
fsevents: 2.3.2
|
||||
|
||||
postcss-load-config@6.0.1(postcss@8.4.40):
|
||||
dependencies:
|
||||
lilconfig: 3.1.2
|
||||
|
5
web/.gitignore
vendored
5
web/.gitignore
vendored
@ -6,3 +6,8 @@
|
||||
# vite
|
||||
vite.config.js.timestamp-*
|
||||
vite.config.ts.timestamp-*
|
||||
node_modules/
|
||||
/test-results/
|
||||
/playwright-report/
|
||||
/blob-report/
|
||||
/playwright/.cache/
|
||||
|
@ -8,7 +8,10 @@
|
||||
"build": "vite build",
|
||||
"preview": "vite preview",
|
||||
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
||||
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch"
|
||||
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
||||
"test": "playwright test",
|
||||
"test:headfull": "playwright test --headed",
|
||||
"test:withui": "playwright test --ui"
|
||||
},
|
||||
"license": "CC-BY-NC-SA-4.0",
|
||||
"engines": {
|
||||
@ -26,12 +29,13 @@
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.5.0",
|
||||
"@fontsource/redaction-10": "^5.0.2",
|
||||
"@playwright/test": "^1.47.1",
|
||||
"@sveltejs/adapter-static": "^3.0.2",
|
||||
"@sveltejs/kit": "^2.0.0",
|
||||
"@sveltejs/vite-plugin-svelte": "^3.0.0",
|
||||
"@types/eslint__js": "^8.42.3",
|
||||
"@types/fluent-ffmpeg": "^2.1.25",
|
||||
"@types/node": "^20.14.10",
|
||||
"@types/node": "^20.14.14",
|
||||
"compare-versions": "^6.1.0",
|
||||
"eslint": "^8.57.0",
|
||||
"glob": "^10.4.5",
|
||||
|
44
web/playwright.config.ts
Normal file
44
web/playwright.config.ts
Normal file
@ -0,0 +1,44 @@
|
||||
import { defineConfig, devices } from '@playwright/test';
|
||||
|
||||
// See https://playwright.dev/docs/test-configuration.
|
||||
export default defineConfig({
|
||||
testDir: './tests',
|
||||
fullyParallel: true,
|
||||
forbidOnly: !!process.env.CI,
|
||||
retries: process.env.CI ? 2 : 0,
|
||||
workers: process.env.CI ? 1 : undefined,
|
||||
reporter: 'html',
|
||||
use: {
|
||||
trace: 'on-first-retry',
|
||||
baseURL: 'https://localhost:5173',
|
||||
ignoreHTTPSErrors: true, // Cobalt uses a self-signed certificate in development
|
||||
},
|
||||
|
||||
/* Configure projects for major browsers */
|
||||
projects: [
|
||||
{
|
||||
name: 'chromium',
|
||||
use: { ...devices['Desktop Chrome'] },
|
||||
},
|
||||
|
||||
// {
|
||||
// name: 'firefox',
|
||||
// use: { ...devices['Desktop Firefox'] },
|
||||
// },
|
||||
|
||||
// {
|
||||
// name: 'webkit',
|
||||
// use: { ...devices['Desktop Safari'] },
|
||||
// },
|
||||
|
||||
// Test on mobile devices (might be useful in the future)?
|
||||
// {
|
||||
// name: 'Mobile Chrome',
|
||||
// use: { ...devices['Pixel 5'] },
|
||||
// },
|
||||
// {
|
||||
// name: 'Mobile Safari',
|
||||
// use: { ...devices['iPhone 12'] },
|
||||
// },
|
||||
],
|
||||
});
|
@ -1,13 +1,16 @@
|
||||
import { get } from "svelte/store";
|
||||
import { get } from 'svelte/store';
|
||||
|
||||
import env, { apiURL } from "$lib/env";
|
||||
import settings from "$lib/state/settings";
|
||||
import env, { apiURL } from '$lib/env';
|
||||
import settings from '$lib/state/settings';
|
||||
|
||||
export const currentApiURL = () => {
|
||||
const processingSettings = get(settings).processing;
|
||||
const customInstanceURL = processingSettings.customInstanceURL;
|
||||
|
||||
if (processingSettings.enableCustomInstances && customInstanceURL.length > 0) {
|
||||
if (
|
||||
processingSettings.enableCustomInstances &&
|
||||
customInstanceURL.length > 0
|
||||
) {
|
||||
return new URL(customInstanceURL).origin;
|
||||
}
|
||||
|
||||
@ -16,4 +19,4 @@ export const currentApiURL = () => {
|
||||
}
|
||||
|
||||
return new URL(apiURL).origin;
|
||||
}
|
||||
};
|
||||
|
120
web/tests/home.spec.ts
Normal file
120
web/tests/home.spec.ts
Normal file
@ -0,0 +1,120 @@
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
const VIDEO_TEST_LINK = 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'; // :3
|
||||
|
||||
// Before each test, open the page (/) in the browser and wait for the
|
||||
// page to load.
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto('/');
|
||||
await page.waitForLoadState('networkidle', { timeout: 10000 });
|
||||
});
|
||||
|
||||
// Test the branding of the page.
|
||||
test('branding', async ({ page }) => {
|
||||
// Page has a tile of "cobalt"
|
||||
const title = await page.title();
|
||||
expect(title).toBe('cobalt');
|
||||
|
||||
/*
|
||||
* Check if the omnibar is present on the page and has correct branding.
|
||||
* IDs: omnibox, meowbalt (branding), cobalt-save (root main tag)
|
||||
*/
|
||||
const requiredOmniBarElements = ['omnibox', 'cobalt-save'];
|
||||
for (const element of requiredOmniBarElements) {
|
||||
expect(await page.isVisible(`#${element}`)).toBe(true);
|
||||
}
|
||||
|
||||
// Make sure meowbalt is in the correct default state (visible, class set to "meowbalt smile")
|
||||
// note: meowbalt is a class, not an id
|
||||
const meowbalt = await page.$('.meowbalt');
|
||||
expect(await meowbalt?.isVisible()).toBe(true);
|
||||
expect(await meowbalt?.getAttribute('class')).toContain('meowbalt smile');
|
||||
expect(await meowbalt?.getAttribute('src')).toBe('/meowbalt/smile.png');
|
||||
|
||||
// Aria-hidden attribute is set to true, alt = "meowbalt"
|
||||
expect(await meowbalt?.getAttribute('aria-hidden')).toBe('true');
|
||||
expect(await meowbalt?.getAttribute('alt')).toBe('meowbalt');
|
||||
});
|
||||
|
||||
// Omnibar related tests
|
||||
test('omnibar', async ({ page }) => {
|
||||
// Check if the omnibar is present on the page
|
||||
expect(await page.isVisible('#omnibox')).toBe(true);
|
||||
|
||||
// Input field is present and has the correct placeholder
|
||||
const input = await page.$('#omnibox input');
|
||||
expect(await input?.isVisible()).toBe(true);
|
||||
expect(await input?.getAttribute('placeholder')).toBe(
|
||||
'paste the link here',
|
||||
);
|
||||
|
||||
// Check that all buttons can be clicked #action-container (besides the first one and the last one)
|
||||
const buttons = await (
|
||||
await page.$$('#action-container button')
|
||||
).slice(1, -1);
|
||||
for (const button of buttons) {
|
||||
await button.click();
|
||||
|
||||
// Check if the button has the "selected" class after clicking
|
||||
expect(await button.getAttribute('class')).toContain('active');
|
||||
|
||||
// Make sure the aria-pressed attribute is set to true
|
||||
expect(await button.getAttribute('aria-pressed')).toBe('true');
|
||||
}
|
||||
});
|
||||
|
||||
test('supported services', async ({ page }) => {
|
||||
// Check if the supported services are present on the page
|
||||
expect(await page.isVisible('#supported-services')).toBe(true);
|
||||
|
||||
// Click the services-button and expect the dropdown to be visible (services-popover)
|
||||
// Visibility of the popover is when the popover has the "expanded" class
|
||||
const servicesButton = await page.$('#services-button');
|
||||
const servicesPopover = await page.$('#services-popover');
|
||||
await servicesButton?.click();
|
||||
|
||||
// Check if the services popover is visible
|
||||
expect(await servicesPopover?.getAttribute('class')).toContain('expanded');
|
||||
await servicesButton?.click();
|
||||
expect(await servicesPopover?.getAttribute('class')).not.toContain(
|
||||
'expanded',
|
||||
);
|
||||
|
||||
// Now open the services popover and ensure skeleton is present
|
||||
await servicesButton?.click();
|
||||
|
||||
// Get all the skeleton elements
|
||||
const skeletonElements = await page.$$('#services-popover .skeleton');
|
||||
expect(skeletonElements.length).toBeGreaterThan(0);
|
||||
|
||||
// Now wait for the services to load and ensure the skeleton is gone (max of 10 seconds)
|
||||
await page.waitForSelector('#services-popover .service-item', {
|
||||
state: 'attached',
|
||||
timeout: 10000,
|
||||
});
|
||||
});
|
||||
|
||||
test('download example', async ({ page }) => {
|
||||
// Get the input field and set the value to the test link
|
||||
const input = await page.$('#omnibox input');
|
||||
await input?.fill(VIDEO_TEST_LINK);
|
||||
|
||||
// Click the download button
|
||||
const downloadButton = await page.$('#download-button');
|
||||
await downloadButton?.click();
|
||||
|
||||
// Wait for the network request to api.cobalt.tools to finish
|
||||
const req = await page.waitForRequest('**/api.cobalt.tools/');
|
||||
const rsp = await req.response();
|
||||
expect(rsp).not.toBe(null);
|
||||
|
||||
// Ensure we have a 200 OK and a valid JSON response
|
||||
expect(rsp!.status()).toBe(200);
|
||||
const json = await rsp!.json();
|
||||
|
||||
// Json should contain the following keys: "status", "url", "and filename"
|
||||
const props = ['status', 'url', 'filename'];
|
||||
for (const prop of props) {
|
||||
expect(json).toHaveProperty(prop);
|
||||
}
|
||||
});
|
Loading…
Reference in New Issue
Block a user