From 2fdc338285c56b70fb22cb77be9740d820b999ef Mon Sep 17 00:00:00 2001 From: Kawsar Ahmed Date: Tue, 27 Aug 2024 17:16:14 +0600 Subject: [PATCH] Playwright test implemented --- .github/workflows/playwright.yml | 27 +++++++++++ .gitignore | 5 ++ package.json | 6 ++- playwright.config.ts | 60 ++++++++++++++++++++++++ src/lib/elements/Input.svelte | 2 + src/lib/elements/PaperItem.svelte | 2 +- src/lib/elements/Result.svelte | 8 ++-- src/routes/(app)/+page.svelte | 33 +------------ tests/index.test.ts | 77 +++++++++++++++++++++++++++++++ tests/test.ts | 6 --- 10 files changed, 182 insertions(+), 44 deletions(-) create mode 100644 .github/workflows/playwright.yml create mode 100644 playwright.config.ts create mode 100644 tests/index.test.ts delete mode 100644 tests/test.ts diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml new file mode 100644 index 0000000..e3c5f6b --- /dev/null +++ b/.github/workflows/playwright.yml @@ -0,0 +1,27 @@ +name: Playwright Tests +on: + push: + branches: [master] + pull_request: + branches: [master] +jobs: + test: + timeout-minutes: 60 + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: lts/* + - name: Install dependencies + run: npm ci + - name: Install Playwright Browsers + run: npx playwright install --with-deps + - name: Run Playwright tests + run: npx playwright test + - uses: actions/upload-artifact@v4 + if: always() + with: + name: playwright-report + path: playwright-report/ + retention-days: 10 diff --git a/.gitignore b/.gitignore index 64c66b4..07fca74 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,8 @@ node_modules vite.config.js.timestamp-* vite.config.ts.timestamp-* package-lock.json +/test-results/ +/playwright-report/ +/blob-report/ +/playwright/.cache/ +.vercel \ No newline at end of file diff --git a/package.json b/package.json index 16b37fd..31ed78d 100644 --- a/package.json +++ b/package.json @@ -5,23 +5,27 @@ "scripts": { "dev": "vite dev", "build": "vite build", + "build:dev": "vite build --mode development", "preview": "vite preview", "test": "npm run test:integration && npm run test:unit", "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", - "test:integration": "playwright test", + "test:ui": "playwright test", "test:unit": "vitest", "lint": "prettier --plugin-search-dir . --check .", "format": "prettier --plugin-search-dir . --write ." }, "devDependencies": { "@iconify/svelte": "^4.0.2", + "@playwright/test": "^1.46.1", "@sveltejs/adapter-auto": "^3.0.0", "@sveltejs/adapter-vercel": "^5.4.1", "@sveltejs/kit": "^2.0.0", "@sveltejs/vite-plugin-svelte": "^3.0.0", "@types/mixpanel-browser": "^2.49.0", + "@types/node": "^22.5.0", "autoprefixer": "^10.4.14", + "dotenv": "^16.4.5", "postcss": "^8.4.27", "prettier": "^2.8.0", "prettier-plugin-svelte": "^2.10.1", diff --git a/playwright.config.ts b/playwright.config.ts new file mode 100644 index 0000000..353ff6f --- /dev/null +++ b/playwright.config.ts @@ -0,0 +1,60 @@ +import { defineConfig, devices } from '@playwright/test' + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// dotenv.config({ path: path.resolve(__dirname, '.env.development') }) + +export default defineConfig({ + testDir: './tests', + timeout: 5000, + fullyParallel: true, + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 1, + workers: process.env.CI ? 1 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: 'html', + use: { + /* Base URL to use in actions like `await page.goto('/')`. */ + baseURL: 'http://localhost:4173', + /* 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: 'chromium', + // use: { ...devices['Desktop Chrome'] } + // }, + + /* Test against mobile viewports. */ + { + name: 'Mobile Chrome', + use: { ...devices['Pixel 7'] } + }, + { + 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 build:dev && npm run preview', + url: 'http://localhost:4173', + reuseExistingServer: !process.env.CI + } +}) diff --git a/src/lib/elements/Input.svelte b/src/lib/elements/Input.svelte index 78ce9f3..d74ca88 100644 --- a/src/lib/elements/Input.svelte +++ b/src/lib/elements/Input.svelte @@ -5,6 +5,7 @@ export let id: string = makeid(3) export let value: string + export let name: string = '' export let type: string = 'number' export let disabled: boolean = false export let classNames: string = '' @@ -19,6 +20,7 @@ {#each fields as field} - + {/each}
diff --git a/src/lib/elements/Result.svelte b/src/lib/elements/Result.svelte index ce125a7..40d03e7 100644 --- a/src/lib/elements/Result.svelte +++ b/src/lib/elements/Result.svelte @@ -8,14 +8,14 @@
-

Total:

-

+

Total:

+

{total.toFixed(2)}

-

Total with (40%):

-

+

Total with (40%):

+

{(total + _40Percent).toFixed(2)}

diff --git a/src/routes/(app)/+page.svelte b/src/routes/(app)/+page.svelte index df1b376..4e3025b 100644 --- a/src/routes/(app)/+page.svelte +++ b/src/routes/(app)/+page.svelte @@ -154,6 +154,7 @@ {/if}
handleKeyDown(event)} on:remove={() => removePaper(paper.id)} /> - {/each}
diff --git a/tests/index.test.ts b/tests/index.test.ts new file mode 100644 index 0000000..f56e5d0 --- /dev/null +++ b/tests/index.test.ts @@ -0,0 +1,77 @@ +import { expect, test } from '@playwright/test' + +test('index page has loaded fine', async ({ page }) => { + await page.goto('/') + await expect(page.getByText('Paper Cost')).toBeVisible() +}) + +test('test calculate paper cost works', async ({ page }) => { + await page.goto('/') + + await page.getByPlaceholder('Product name').click() + await page.getByPlaceholder('Product name').fill('Test product') + await page.getByPlaceholder('L').fill('23') + await page.getByPlaceholder('W').fill('23') + await page.getByPlaceholder('GSM').fill('23') + await page.getByPlaceholder('R', { exact: true }).fill('100') + await page.getByRole('button', { name: 'Calculate' }).click() + await page.getByRole('button', { name: 'Save cost' }).click() + await expect(page.getByText('Total with (40%):')).toBeVisible() + await expect(page.getByText('1.10')).toBeVisible() + await page.getByRole('button', { name: 'Clear' }).click() + await expect(page.getByText('= total')).toBeVisible() +}) + +test('test cost history saved in history', async ({ page }) => { + await page.goto('/') + await page.getByPlaceholder('L').fill('34') + await page.getByPlaceholder('L').press('Enter') + await page.getByPlaceholder('W').fill('34') + await page.getByPlaceholder('W').press('Enter') + await page.getByPlaceholder('GSM').fill('34') + await page.getByPlaceholder('GSM').press('Enter') + await page.getByPlaceholder('R', { exact: true }).fill('100') + await page.getByPlaceholder('R', { exact: true }).press('Enter') + await expect(page.getByText('Total with (40%):')).toBeVisible() + await expect(page.getByText('3.55')).toBeVisible() + await page.getByRole('button', { name: 'Save cost' }).click() + await expect(page.getByText('Cost details saved')).toBeVisible() + await page.getByRole('link', { name: 'Cost History' }).click() + await expect(page.getByRole('heading', { name: 'History' })).toBeVisible() +}) + +test('test multiple paper calcuation', async ({ page }) => { + await page.goto('/') + + await page.getByTestId('product_name').click() + await page.getByTestId('product_name').fill('Snaks') + await page.getByRole('button', { name: 'Add paper' }).click() + + await page.getByTestId('length').first().click() + await page.getByTestId('length').first().fill('34') + await page.getByTestId('length').first().press('Enter') + await page.getByTestId('width').first().fill('43') + await page.getByTestId('width').first().press('Enter') + await page.getByTestId('thickness').first().fill('33') + await page.getByTestId('thickness').first().press('Enter') + await page.getByTestId('rate').first().fill('100') + await page.getByTestId('rate').first().press('Enter') + + await page.getByTestId('length').nth(1).fill('43') + await page.getByTestId('length').nth(1).press('Enter') + await page.getByTestId('width').nth(1).fill('32') + await page.getByTestId('width').nth(1).press('Enter') + await page.getByTestId('thickness').nth(1).fill('54') + await page.getByTestId('thickness').nth(1).press('Enter') + await page.getByTestId('rate').nth(1).fill('120') + await page.getByTestId('rate').nth(1).press('Enter') + + await expect(page.getByTestId('total40-text')).toBeVisible() + await expect(page.getByTestId('total40-value')).toBeVisible() + await expect(page.getByTestId('total-text')).toBeVisible() + await expect(page.getByTestId('total-value')).toBeVisible() + await page.getByRole('button', { name: 'Clear' }).click() + + await expect(page.getByTestId('total40-value')).not.toBeVisible() + await expect(page.getByTestId('total-text')).not.toBeVisible() +}) diff --git a/tests/test.ts b/tests/test.ts deleted file mode 100644 index ceb92e1..0000000 --- a/tests/test.ts +++ /dev/null @@ -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() -})