adds playwright tests
This commit is contained in:
9
web/.gitignore
vendored
9
web/.gitignore
vendored
@@ -8,3 +8,12 @@ node_modules
|
|||||||
!.env.example
|
!.env.example
|
||||||
vite.config.js.timestamp-*
|
vite.config.js.timestamp-*
|
||||||
vite.config.ts.timestamp-*
|
vite.config.ts.timestamp-*
|
||||||
|
test-results/
|
||||||
|
playwright-report/
|
||||||
|
blob-report/
|
||||||
|
playwright/.cache/
|
||||||
|
test-results/
|
||||||
|
playwright-report/
|
||||||
|
blob-report/
|
||||||
|
playwright/.cache/
|
||||||
|
playwright/.auth
|
||||||
|
|||||||
8668
web/package-lock.json
generated
8668
web/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
103
web/package.json
103
web/package.json
@@ -1,53 +1,54 @@
|
|||||||
{
|
{
|
||||||
"name": "wanderer",
|
"name": "wanderer",
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite dev",
|
"dev": "vite dev",
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
"preview": "vite preview",
|
"preview": "vite preview",
|
||||||
"test": "npm run test:integration && npm run test:unit",
|
"test": "npm run test:integration && npm run test:unit",
|
||||||
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
"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:integration": "playwright test",
|
"test:integration": "playwright test",
|
||||||
"test:unit": "vitest"
|
"test:unit": "vitest"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@playwright/test": "^1.28.1",
|
"@playwright/test": "^1.42.1",
|
||||||
"@sveltejs/adapter-auto": "^3.0.0",
|
"@sveltejs/adapter-auto": "^3.0.0",
|
||||||
"@sveltejs/kit": "^2.0.0",
|
"@sveltejs/kit": "^2.0.0",
|
||||||
"@sveltejs/vite-plugin-svelte": "^3.0.0",
|
"@sveltejs/vite-plugin-svelte": "^3.0.0",
|
||||||
"@types/leaflet": "^1.9.8",
|
"@types/leaflet": "^1.9.8",
|
||||||
"@types/leaflet-gpx": "^1.3.7",
|
"@types/leaflet-gpx": "^1.3.7",
|
||||||
"autoprefixer": "^10.4.17",
|
"@types/node": "^20.11.25",
|
||||||
"postcss": "^8.4.33",
|
"autoprefixer": "^10.4.17",
|
||||||
"svelte": "^4.2.7",
|
"postcss": "^8.4.33",
|
||||||
"svelte-check": "^3.6.0",
|
"svelte": "^4.2.7",
|
||||||
"tailwindcss": "^3.4.1",
|
"svelte-check": "^3.6.0",
|
||||||
"tslib": "^2.4.1",
|
"tailwindcss": "^3.4.1",
|
||||||
"typescript": "^5.0.0",
|
"tslib": "^2.4.1",
|
||||||
"vite": "^5.0.3",
|
"typescript": "^5.0.0",
|
||||||
"vitest": "^1.2.0"
|
"vite": "^5.0.3",
|
||||||
},
|
"vitest": "^1.2.0"
|
||||||
"type": "module",
|
},
|
||||||
"dependencies": {
|
"type": "module",
|
||||||
"@fortawesome/fontawesome-free": "^6.5.1",
|
"dependencies": {
|
||||||
"@sveltejs/adapter-node": "^4.0.1",
|
"@fortawesome/fontawesome-free": "^6.5.1",
|
||||||
"@threlte/core": "^7.1.0",
|
"@sveltejs/adapter-node": "^4.0.1",
|
||||||
"@threlte/extras": "^8.7.5",
|
"@threlte/core": "^7.1.0",
|
||||||
"@types/leaflet.awesome-markers": "^2.0.28",
|
"@threlte/extras": "^8.7.5",
|
||||||
"@types/three": "^0.161.2",
|
"@types/leaflet.awesome-markers": "^2.0.28",
|
||||||
"crypto-random-string": "^5.0.0",
|
"@types/three": "^0.161.2",
|
||||||
"date-fns": "^3.3.1",
|
"crypto-random-string": "^5.0.0",
|
||||||
"leaflet": "^1.9.4",
|
"date-fns": "^3.3.1",
|
||||||
"leaflet-gpx": "^1.7.0",
|
"leaflet": "^1.9.4",
|
||||||
"leaflet.awesome-markers": "^2.0.5",
|
"leaflet-gpx": "^1.7.0",
|
||||||
"meilisearch": "^0.37.0",
|
"leaflet.awesome-markers": "^2.0.5",
|
||||||
"nouislider": "^15.7.1",
|
"meilisearch": "^0.37.0",
|
||||||
"photoswipe": "^5.4.3",
|
"nouislider": "^15.7.1",
|
||||||
"pocketbase": "^0.21.0",
|
"photoswipe": "^5.4.3",
|
||||||
"svelte-i18n": "^4.0.0",
|
"pocketbase": "^0.21.0",
|
||||||
"three": "^0.161.0",
|
"svelte-i18n": "^4.0.0",
|
||||||
"yup": "^1.3.3"
|
"three": "^0.161.0",
|
||||||
}
|
"yup": "^1.3.3"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,88 @@
|
|||||||
import type { PlaywrightTestConfig } from '@playwright/test';
|
import { defineConfig, devices } from '@playwright/test';
|
||||||
|
|
||||||
const config: PlaywrightTestConfig = {
|
/**
|
||||||
webServer: {
|
* Read environment variables from file.
|
||||||
command: 'npm run build && npm run preview',
|
* https://github.com/motdotla/dotenv
|
||||||
port: 4173
|
*/
|
||||||
},
|
// require('dotenv').config();
|
||||||
testDir: 'tests',
|
|
||||||
testMatch: /(.+\.)?(test|spec)\.[jt]s/
|
|
||||||
};
|
|
||||||
|
|
||||||
export default config;
|
/**
|
||||||
|
* See https://playwright.dev/docs/test-configuration.
|
||||||
|
*/
|
||||||
|
export default defineConfig({
|
||||||
|
testDir: './tests/playwright',
|
||||||
|
/* Run tests in files in parallel */
|
||||||
|
fullyParallel: true,
|
||||||
|
/* Fail the build on CI if you accidentally left test.only in the source code. */
|
||||||
|
forbidOnly: !!process.env.CI,
|
||||||
|
/* Retry on CI only */
|
||||||
|
retries: process.env.CI ? 2 : 0,
|
||||||
|
/* Opt out of parallel tests on CI. */
|
||||||
|
workers: process.env.CI ? 1 : undefined,
|
||||||
|
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
|
||||||
|
reporter: 'html',
|
||||||
|
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
|
||||||
|
use: {
|
||||||
|
/* Base URL to use in actions like `await page.goto('/')`. */
|
||||||
|
baseURL: "http://localhost:5173",
|
||||||
|
|
||||||
|
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
|
||||||
|
trace: 'on-first-retry',
|
||||||
|
},
|
||||||
|
|
||||||
|
/* Configure projects for major browsers */
|
||||||
|
projects: [
|
||||||
|
{ name: 'setup', testMatch: /.*\.setup\.ts/ },
|
||||||
|
|
||||||
|
// {
|
||||||
|
// name: 'firefox',
|
||||||
|
// use: {
|
||||||
|
// ...devices['Desktop Firefox'],
|
||||||
|
// storageState: 'playwright/.auth/user.json',
|
||||||
|
// },
|
||||||
|
|
||||||
|
// dependencies: ['setup']
|
||||||
|
// },
|
||||||
|
|
||||||
|
{
|
||||||
|
name: 'chromium',
|
||||||
|
use: {
|
||||||
|
...devices['Desktop Chrome'],
|
||||||
|
storageState: 'playwright/.auth/user.json',
|
||||||
|
},
|
||||||
|
// dependencies: ['setup']
|
||||||
|
},
|
||||||
|
|
||||||
|
// {
|
||||||
|
// name: 'webkit',
|
||||||
|
// use: { ...devices['Desktop Safari'] },
|
||||||
|
// },
|
||||||
|
|
||||||
|
/* Test against mobile viewports. */
|
||||||
|
// {
|
||||||
|
// name: 'Mobile Chrome',
|
||||||
|
// use: { ...devices['Pixel 5'] },
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: 'Mobile Safari',
|
||||||
|
// use: { ...devices['iPhone 12'] },
|
||||||
|
// },
|
||||||
|
|
||||||
|
/* Test against branded browsers. */
|
||||||
|
// {
|
||||||
|
// name: 'Microsoft Edge',
|
||||||
|
// use: { ...devices['Desktop Edge'], channel: 'msedge' },
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// name: 'Google Chrome',
|
||||||
|
// use: { ...devices['Desktop Chrome'], channel: 'chrome' },
|
||||||
|
// },
|
||||||
|
],
|
||||||
|
|
||||||
|
/* Run your local dev server before starting the tests */
|
||||||
|
// webServer: {
|
||||||
|
// command: 'npm run start',
|
||||||
|
// url: 'http://127.0.0.1:3000',
|
||||||
|
// reuseExistingServer: !process.env.CI,
|
||||||
|
// },
|
||||||
|
});
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
import { describe, it, expect } from 'vitest';
|
|
||||||
|
|
||||||
describe('sum test', () => {
|
|
||||||
it('adds 1 + 2 to equal 3', () => {
|
|
||||||
expect(1 + 2).toBe(3);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
<button class="btn-secondary" on:click={closeModal}
|
<button class="btn-secondary" on:click={closeModal}
|
||||||
>{$_("cancel")}</button
|
>{$_("cancel")}</button
|
||||||
>
|
>
|
||||||
<button class="btn-danger" type="button" on:click={confirm}
|
<button class="btn-danger" type="button" on:click={confirm} name="delete"
|
||||||
>{$_("delete")}</button
|
>{$_("delete")}</button
|
||||||
>
|
>
|
||||||
</div></Modal
|
</div></Modal
|
||||||
|
|||||||
@@ -106,7 +106,7 @@
|
|||||||
<button class="btn-secondary" on:click={closeModal}
|
<button class="btn-secondary" on:click={closeModal}
|
||||||
>{$_("cancel")}</button
|
>{$_("cancel")}</button
|
||||||
>
|
>
|
||||||
<button class="btn-primary" type="submit" form="list-form"
|
<button class="btn-primary" type="submit" form="list-form" name="save"
|
||||||
>{$_("save")}</button
|
>{$_("save")}</button
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -116,10 +116,12 @@
|
|||||||
</div>
|
</div>
|
||||||
<hr class="my-6 border-input-border" />
|
<hr class="my-6 border-input-border" />
|
||||||
<div class="flex flex-col basis-full">
|
<div class="flex flex-col basis-full">
|
||||||
<a class="btn-primary btn-large text-center mx-4" href="/trail/edit/new"
|
|
||||||
><i class="fa fa-plus mr-2"></i>{$_("new-trail")}</a
|
|
||||||
>
|
|
||||||
{#if $currentUser}
|
{#if $currentUser}
|
||||||
|
<a
|
||||||
|
class="btn-primary btn-large text-center mx-4"
|
||||||
|
href="/trail/edit/new"
|
||||||
|
><i class="fa fa-plus mr-2"></i>{$_("new-trail")}</a
|
||||||
|
>
|
||||||
<div class="basis-full"></div>
|
<div class="basis-full"></div>
|
||||||
<hr class="border-input-border" />
|
<hr class="border-input-border" />
|
||||||
<div class="flex gap-4 items-center m-4">
|
<div class="flex gap-4 items-center m-4">
|
||||||
@@ -138,6 +140,10 @@
|
|||||||
></i></button
|
></i></button
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
|
{:else}
|
||||||
|
<a class="btn-primary btn-large text-center mx-4" href="/login"
|
||||||
|
>{$_("login")}</a
|
||||||
|
>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</Drawer>
|
</Drawer>
|
||||||
@@ -179,7 +185,9 @@
|
|||||||
: 'moon'}"
|
: 'moon'}"
|
||||||
on:click={() => toggleTheme()}
|
on:click={() => toggleTheme()}
|
||||||
></button>
|
></button>
|
||||||
<a class="btn-primary btn-large" href="/trail/edit/new"
|
<a
|
||||||
|
class="btn-primary btn-large"
|
||||||
|
href="/trail/edit/new"
|
||||||
><i class="fa fa-plus mr-2"></i>{$_("new-trail")}</a
|
><i class="fa fa-plus mr-2"></i>{$_("new-trail")}</a
|
||||||
>
|
>
|
||||||
<Dropdown
|
<Dropdown
|
||||||
|
|||||||
@@ -29,9 +29,7 @@
|
|||||||
openListModal();
|
openListModal();
|
||||||
}
|
}
|
||||||
|
|
||||||
async function saveList(
|
async function saveList(e: CustomEvent<{ list: List; avatar?: File }>) {
|
||||||
e: CustomEvent<{ list: List; avatar?: File }>,
|
|
||||||
) {
|
|
||||||
const result = e.detail;
|
const result = e.detail;
|
||||||
if (result.list.id) {
|
if (result.list.id) {
|
||||||
await lists_update(result.list, result.avatar);
|
await lists_update(result.list, result.avatar);
|
||||||
@@ -39,7 +37,6 @@
|
|||||||
await lists_create(result.list, result.avatar);
|
await lists_create(result.list, result.avatar);
|
||||||
}
|
}
|
||||||
await lists_index();
|
await lists_index();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleDropdownClick(
|
async function handleDropdownClick(
|
||||||
@@ -82,23 +79,23 @@
|
|||||||
on:click={beforeListModalOpen}
|
on:click={beforeListModalOpen}
|
||||||
>
|
>
|
||||||
<i class="fa fa-plus text-xl aspect-square"></i>
|
<i class="fa fa-plus text-xl aspect-square"></i>
|
||||||
<h5 class="text-xl font-semibold">{$_("create-new-list")}</h5>
|
<h5 id="create-list-button" class="text-xl font-semibold">
|
||||||
|
{$_("create-new-list")}
|
||||||
|
</h5>
|
||||||
</button>
|
</button>
|
||||||
<hr class="border-separator my-2" />
|
<hr class="border-separator my-2" />
|
||||||
<div>
|
{#each $lists as item, i}
|
||||||
{#each $lists as item, i}
|
<li class="list-list-item" on:click={() => list.set(item)} role="presentation">
|
||||||
<li on:click={() => list.set(item)} role="presentation">
|
<ListCard
|
||||||
<ListCard
|
list={item}
|
||||||
list={item}
|
on:change={(e) => handleDropdownClick(e, item)}
|
||||||
on:change={(e) => handleDropdownClick(e, item)}
|
active={item.id === $list.id}
|
||||||
active={item.id === $list.id}
|
></ListCard>
|
||||||
></ListCard>
|
{#if i != $lists.length - 1}
|
||||||
{#if i != $lists.length - 1}
|
<hr class="border-separator my-2" />
|
||||||
<hr class="border-separator my-2" />
|
{/if}
|
||||||
{/if}
|
</li>
|
||||||
</li>
|
{/each}
|
||||||
{/each}
|
|
||||||
</div>
|
|
||||||
</ul>
|
</ul>
|
||||||
<TrailList
|
<TrailList
|
||||||
bind:filter
|
bind:filter
|
||||||
|
|||||||
19
web/tests/playwright/auth.setup.ts
Normal file
19
web/tests/playwright/auth.setup.ts
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import { test as setup } from '@playwright/test';
|
||||||
|
|
||||||
|
const authFile = 'playwright/.auth/user.json';
|
||||||
|
|
||||||
|
setup('authenticate', async ({ page }) => {
|
||||||
|
await page.goto('/login', { waitUntil: 'networkidle' });
|
||||||
|
await page.locator('input[name="username"]').fill('Test');
|
||||||
|
await page.locator('input[name="password"]').fill('password');
|
||||||
|
await page.getByRole('button', { name: 'Login' }).click();
|
||||||
|
// Wait until the page receives the cookies.
|
||||||
|
//
|
||||||
|
// Sometimes login flow sets cookies in the process of several redirects.
|
||||||
|
// Wait for the final URL to ensure that the cookies are actually set.
|
||||||
|
await page.waitForURL('/');
|
||||||
|
|
||||||
|
// End of authentication steps.
|
||||||
|
|
||||||
|
await page.context().storageState({ path: authFile });
|
||||||
|
});
|
||||||
8
web/tests/playwright/e2e/index/index.spec.ts
Normal file
8
web/tests/playwright/e2e/index/index.spec.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import { expect, test } from '@playwright/test';
|
||||||
|
import { IndexPage } from '../../pages/index_page';
|
||||||
|
|
||||||
|
test('index page does not show error', async ({ page }) => {
|
||||||
|
const indexPage = new IndexPage(page);
|
||||||
|
await indexPage.goto()
|
||||||
|
await indexPage.hasNoError()
|
||||||
|
});
|
||||||
30
web/tests/playwright/e2e/list/list.spec.ts
Normal file
30
web/tests/playwright/e2e/list/list.spec.ts
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import { test as base, expect } from '@playwright/test';
|
||||||
|
import { ListsPage } from '../../pages/lists_page';
|
||||||
|
|
||||||
|
const test = base.extend<{ listsPage: ListsPage }>({
|
||||||
|
listsPage: async ({ page }, use) => {
|
||||||
|
const listsPage = new ListsPage(page);
|
||||||
|
await listsPage.goto();
|
||||||
|
await listsPage.create();
|
||||||
|
await use(listsPage);
|
||||||
|
await listsPage.removeAll();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
test('shows a list card', async ({ listsPage }) => {
|
||||||
|
const listItemCount = await listsPage.listItems.count();
|
||||||
|
await listsPage.create();
|
||||||
|
expect(listsPage.listItems).toHaveCount(listItemCount + 1);
|
||||||
|
expect(listsPage.listItemsImage).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('update a list card', async ({ listsPage }) => {
|
||||||
|
await listsPage.update();
|
||||||
|
expect(listsPage.listItems.first()).toContainText("Updated List");
|
||||||
|
expect(listsPage.listItems.first()).toContainText("New Description");
|
||||||
|
});
|
||||||
|
|
||||||
|
test('delete a list card', async ({ listsPage }) => {
|
||||||
|
await listsPage.delete();
|
||||||
|
expect(listsPage.listItems).toHaveCount(0);
|
||||||
|
});
|
||||||
11
web/tests/playwright/e2e/user/user.spec.ts
Normal file
11
web/tests/playwright/e2e/user/user.spec.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import { test, expect } from '@playwright/test';
|
||||||
|
|
||||||
|
test('logs the user out', async ({ page }) => {
|
||||||
|
await page.goto('/');
|
||||||
|
await page.getByRole('button', { name: 'avatar' }).click();
|
||||||
|
await page.locator(".menu .menu-item").filter({ hasText: "Logout" }).click();
|
||||||
|
|
||||||
|
const cookies = await page.context().cookies();
|
||||||
|
const pbAuthCookie = cookies.find(cookie => cookie.name === 'pb_auth');
|
||||||
|
expect(pbAuthCookie).toBeFalsy();
|
||||||
|
});
|
||||||
BIN
web/tests/playwright/fixtures/avatar.webp
Normal file
BIN
web/tests/playwright/fixtures/avatar.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 154 KiB |
19
web/tests/playwright/pages/index_page.ts
Normal file
19
web/tests/playwright/pages/index_page.ts
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import { expect, type Locator, type Page } from '@playwright/test';
|
||||||
|
|
||||||
|
export class IndexPage {
|
||||||
|
readonly page: Page;
|
||||||
|
readonly error: Locator;
|
||||||
|
|
||||||
|
constructor(page: Page) {
|
||||||
|
this.page = page;
|
||||||
|
this.error = page.getByText("Internal Error");
|
||||||
|
}
|
||||||
|
|
||||||
|
async goto() {
|
||||||
|
await this.page.goto('/');
|
||||||
|
}
|
||||||
|
|
||||||
|
async hasNoError() {
|
||||||
|
await expect(this.error).toHaveCount(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
83
web/tests/playwright/pages/lists_page.ts
Normal file
83
web/tests/playwright/pages/lists_page.ts
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
import { type Locator, type Page } from '@playwright/test';
|
||||||
|
|
||||||
|
export class ListsPage {
|
||||||
|
readonly page: Page;
|
||||||
|
readonly createListButton: Locator;
|
||||||
|
|
||||||
|
readonly listItems: Locator;
|
||||||
|
readonly listItemsImage: Locator;
|
||||||
|
|
||||||
|
readonly listModal: Locator;
|
||||||
|
readonly listModalAvatar: Locator;
|
||||||
|
readonly listModalName: Locator;
|
||||||
|
readonly listModalDescription: Locator;
|
||||||
|
readonly listModalSaveButton: Locator;
|
||||||
|
|
||||||
|
|
||||||
|
readonly confirmModal: Locator;
|
||||||
|
readonly confirmModalConfirmButton: Locator;
|
||||||
|
|
||||||
|
|
||||||
|
constructor(page: Page) {
|
||||||
|
this.page = page;
|
||||||
|
this.createListButton = page.locator("#create-list-button");
|
||||||
|
this.listModal = page.locator("#list-modal");
|
||||||
|
|
||||||
|
this.listModalAvatar = this.listModal.locator('input[name="avatar"]')
|
||||||
|
this.listModalName = this.listModal.locator('input[name="name"]')
|
||||||
|
this.listModalDescription = this.listModal.locator('textarea[name="description"]')
|
||||||
|
this.listModalSaveButton = this.listModal.getByText('Save');
|
||||||
|
|
||||||
|
this.listItems = page.locator('.list-list-item');
|
||||||
|
this.listItemsImage = page.locator('.list-list-item img');
|
||||||
|
|
||||||
|
|
||||||
|
this.confirmModal = page.locator("#confirm-modal");
|
||||||
|
this.confirmModalConfirmButton = this.confirmModal.locator("button").filter({ hasText: "Delete" });
|
||||||
|
}
|
||||||
|
|
||||||
|
async goto() {
|
||||||
|
await this.page.goto('/lists', { waitUntil: 'networkidle' });
|
||||||
|
}
|
||||||
|
|
||||||
|
async create(name: string = "Test List") {
|
||||||
|
await this.createListButton.click();
|
||||||
|
await this.listModalName.fill(name);
|
||||||
|
await this.listModalAvatar.setInputFiles([
|
||||||
|
"./tests/playwright/fixtures/avatar.webp"
|
||||||
|
]);
|
||||||
|
await Promise.all([
|
||||||
|
this.page.waitForResponse(resp => resp.url().includes('/api/v1/list') && resp.status() === 200),
|
||||||
|
this.listModalSaveButton.click()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
async update(name: string = "Updated List", description = "New Description") {
|
||||||
|
await this.listItems.first().locator(".dropdown button").click();
|
||||||
|
await this.listItems.first().locator(".menu .menu-item").filter({ hasText: "Edit" }).click();
|
||||||
|
await this.listModalName.fill(name);
|
||||||
|
await this.listModalDescription.fill(description);
|
||||||
|
|
||||||
|
await Promise.all([
|
||||||
|
this.page.waitForResponse(resp => resp.url().includes('/api/v1/list') && resp.status() === 200),
|
||||||
|
this.listModalSaveButton.click()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
async delete() {
|
||||||
|
await this.listItems.first().locator(".dropdown button").click();
|
||||||
|
await this.listItems.first().locator(".menu .menu-item").filter({ hasText: "Delete" }).click();
|
||||||
|
await Promise.all([
|
||||||
|
this.page.waitForResponse(resp => resp.url().includes('/api/v1/list') && resp.status() === 200),
|
||||||
|
this.confirmModalConfirmButton.click()
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
async removeAll() {
|
||||||
|
while ((await this.listItems.count()) > 0) {
|
||||||
|
await this.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
import { expect, test } from '@playwright/test';
|
|
||||||
|
|
||||||
test('index page has expected h1', async ({ page }) => {
|
|
||||||
await page.goto('/');
|
|
||||||
await expect(page.getByRole('heading', { name: 'Welcome to SvelteKit' })).toBeVisible();
|
|
||||||
});
|
|
||||||
Reference in New Issue
Block a user