From 083bf5a0a565b6fb1a6e62310fff0e96e8634a30 Mon Sep 17 00:00:00 2001 From: Elio Bischof Date: Sat, 19 Oct 2024 00:09:29 +0200 Subject: [PATCH] clean dependencies --- apps/login/package.json | 38 +-- pnpm-lock.yaml | 48 +-- tests-examples/demo-todo-app.spec.ts | 437 --------------------------- 3 files changed, 45 insertions(+), 478 deletions(-) delete mode 100644 tests-examples/demo-todo-app.spec.ts diff --git a/apps/login/package.json b/apps/login/package.json index 16479b6441c..9617300a2ed 100644 --- a/apps/login/package.json +++ b/apps/login/package.json @@ -1,6 +1,7 @@ { "name": "@zitadel/login", "private": true, + "type": "module", "scripts": { "dev": "next dev", "test": "concurrently --timings --kill-others-on-fail 'npm:test:unit' 'npm:test:integration'", @@ -32,7 +33,7 @@ "*": "prettier --write --ignore-unknown" }, "dependencies": { - "@headlessui/react": "^1.7.18", + "@headlessui/react": "^2.1.9", "@heroicons/react": "2.1.3", "@tailwindcss/forms": "0.5.7", "@vercel/analytics": "^1.2.2", @@ -41,8 +42,10 @@ "@zitadel/proto": "workspace:*", "clsx": "1.2.1", "copy-to-clipboard": "^3.3.3", + "deepmerge": "^4.3.1", "moment": "^2.29.4", - "next": "14.2.5", + "next": "14.2.14", + "next-intl": "^3.20.0", "next-themes": "^0.2.1", "nice-grpc": "2.0.1", "qrcode.react": "^3.1.0", @@ -53,12 +56,12 @@ "tinycolor2": "1.4.2" }, "devDependencies": { - "@bufbuild/buf": "^1.36.0", + "@bufbuild/buf": "^1.41.0", "@testing-library/jest-dom": "^6.4.5", - "@testing-library/react": "^16.0.0", + "@testing-library/react": "^16.0.1", "@types/ms": "0.7.34", - "@types/node": "22.1.0", - "@types/react": "18.3.3", + "@types/node": "22.5.5", + "@types/react": "18.3.7", "@types/react-dom": "18.3.0", "@types/tinycolor2": "1.4.3", "@types/uuid": "^10.0.0", @@ -66,22 +69,23 @@ "@zitadel/prettier-config": "workspace:*", "@zitadel/tsconfig": "workspace:*", "autoprefixer": "10.4.20", - "concurrently": "^8.1.0", - "cypress": "^13.13.2", + "concurrently": "^9.0.1", + "cypress": "^13.14.2", "del-cli": "5.1.0", "env-cmd": "^10.1.0", "eslint-config-zitadel": "workspace:*", "grpc-tools": "1.12.4", - "lint-staged": "15.2.8", + "jsdom": "^25.0.0", + "lint-staged": "15.2.10", "make-dir-cli": "4.0.0", - "nodemon": "^3.1.4", - "postcss": "8.4.41", - "prettier-plugin-tailwindcss": "0.6.5", - "sass": "^1.77.1", - "start-server-and-test": "^2.0.0", - "tailwindcss": "3.4.9", - "ts-proto": "^1.139.0", - "typescript": "^5.4.5", + "nodemon": "^3.1.5", + "postcss": "8.4.47", + "prettier-plugin-tailwindcss": "0.6.6", + "sass": "^1.79.1", + "start-server-and-test": "^2.0.8", + "tailwindcss": "3.4.13", + "ts-proto": "^2.2.0", + "typescript": "^5.6.2", "zitadel-tailwind-config": "workspace:*" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1ec76ca2d22..8afc1642971 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -19,10 +19,10 @@ importers: version: 1.48.1 '@types/node': specifier: ^22.7.5 - version: 22.7.5 + version: 22.7.6 '@vitejs/plugin-react': specifier: ^4.2.1 - version: 4.3.1(vite@5.4.6(@types/node@22.7.5)(sass@1.79.1)) + version: 4.3.1(vite@5.4.6(@types/node@22.7.6)(sass@1.79.1)) '@zitadel/prettier-config': specifier: workspace:* version: link:packages/zitadel-prettier-config @@ -49,10 +49,10 @@ importers: version: 5.6.2 vite-tsconfig-paths: specifier: ^5.0.1 - version: 5.0.1(typescript@5.6.2)(vite@5.4.6(@types/node@22.7.5)(sass@1.79.1)) + version: 5.0.1(typescript@5.6.2)(vite@5.4.6(@types/node@22.7.6)(sass@1.79.1)) vitest: specifier: ^2.1.1 - version: 2.1.1(@types/node@22.7.5)(jsdom@25.0.0)(sass@1.79.1) + version: 2.1.1(@types/node@22.7.6)(jsdom@25.0.0)(sass@1.79.1) apps/login: dependencies: @@ -1281,8 +1281,8 @@ packages: '@types/node@22.5.5': resolution: {integrity: sha512-Xjs4y5UPO/CLdzpgR6GirZJx36yScjh73+2NlLlkFRSoQN8B0DpfXPdZGnvVmLRLOsqDpOfTNv7D9trgGhmOIA==} - '@types/node@22.7.5': - resolution: {integrity: sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==} + '@types/node@22.7.6': + resolution: {integrity: sha512-/d7Rnj0/ExXDMcioS78/kf1lMzYk4BZV8MZGTBKzTGZ6/406ukkbYlIsZmMPhcR5KlkunDHQLrtAVmSq7r+mSw==} '@types/normalize-package-data@2.4.4': resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} @@ -5622,7 +5622,7 @@ snapshots: dependencies: undici-types: 6.19.8 - '@types/node@22.7.5': + '@types/node@22.7.6': dependencies: undici-types: 6.19.8 @@ -5651,7 +5651,7 @@ snapshots: '@types/yauzl@2.10.3': dependencies: - '@types/node': 22.5.5 + '@types/node': 22.7.6 optional: true '@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.2)': @@ -5705,14 +5705,14 @@ snapshots: '@vercel/git-hooks@1.0.0': {} - '@vitejs/plugin-react@4.3.1(vite@5.4.6(@types/node@22.7.5)(sass@1.79.1))': + '@vitejs/plugin-react@4.3.1(vite@5.4.6(@types/node@22.7.6)(sass@1.79.1))': dependencies: '@babel/core': 7.25.2 '@babel/plugin-transform-react-jsx-self': 7.24.7(@babel/core@7.25.2) '@babel/plugin-transform-react-jsx-source': 7.24.7(@babel/core@7.25.2) '@types/babel__core': 7.20.5 react-refresh: 0.14.2 - vite: 5.4.6(@types/node@22.7.5)(sass@1.79.1) + vite: 5.4.6(@types/node@22.7.6)(sass@1.79.1) transitivePeerDependencies: - supports-color @@ -5723,13 +5723,13 @@ snapshots: chai: 5.1.1 tinyrainbow: 1.2.0 - '@vitest/mocker@2.1.1(@vitest/spy@2.1.1)(vite@5.4.6(@types/node@22.7.5)(sass@1.79.1))': + '@vitest/mocker@2.1.1(@vitest/spy@2.1.1)(vite@5.4.6(@types/node@22.7.6)(sass@1.79.1))': dependencies: '@vitest/spy': 2.1.1 estree-walker: 3.0.3 magic-string: 0.30.11 optionalDependencies: - vite: 5.4.6(@types/node@22.7.5)(sass@1.79.1) + vite: 5.4.6(@types/node@22.7.6)(sass@1.79.1) '@vitest/pretty-format@2.1.1': dependencies: @@ -8212,7 +8212,7 @@ snapshots: '@protobufjs/path': 1.1.2 '@protobufjs/pool': 1.1.0 '@protobufjs/utf8': 1.1.0 - '@types/node': 22.5.5 + '@types/node': 22.7.6 long: 5.2.3 proxy-from-env@1.0.0: {} @@ -9066,12 +9066,12 @@ snapshots: core-util-is: 1.0.2 extsprintf: 1.3.0 - vite-node@2.1.1(@types/node@22.7.5)(sass@1.79.1): + vite-node@2.1.1(@types/node@22.7.6)(sass@1.79.1): dependencies: cac: 6.7.14 debug: 4.3.7(supports-color@5.5.0) pathe: 1.1.2 - vite: 5.4.6(@types/node@22.7.5)(sass@1.79.1) + vite: 5.4.6(@types/node@22.7.6)(sass@1.79.1) transitivePeerDependencies: - '@types/node' - less @@ -9083,31 +9083,31 @@ snapshots: - supports-color - terser - vite-tsconfig-paths@5.0.1(typescript@5.6.2)(vite@5.4.6(@types/node@22.7.5)(sass@1.79.1)): + vite-tsconfig-paths@5.0.1(typescript@5.6.2)(vite@5.4.6(@types/node@22.7.6)(sass@1.79.1)): dependencies: debug: 4.3.6 globrex: 0.1.2 tsconfck: 3.1.1(typescript@5.6.2) optionalDependencies: - vite: 5.4.6(@types/node@22.7.5)(sass@1.79.1) + vite: 5.4.6(@types/node@22.7.6)(sass@1.79.1) transitivePeerDependencies: - supports-color - typescript - vite@5.4.6(@types/node@22.7.5)(sass@1.79.1): + vite@5.4.6(@types/node@22.7.6)(sass@1.79.1): dependencies: esbuild: 0.21.5 postcss: 8.4.47 rollup: 4.21.3 optionalDependencies: - '@types/node': 22.7.5 + '@types/node': 22.7.6 fsevents: 2.3.3 sass: 1.79.1 - vitest@2.1.1(@types/node@22.7.5)(jsdom@25.0.0)(sass@1.79.1): + vitest@2.1.1(@types/node@22.7.6)(jsdom@25.0.0)(sass@1.79.1): dependencies: '@vitest/expect': 2.1.1 - '@vitest/mocker': 2.1.1(@vitest/spy@2.1.1)(vite@5.4.6(@types/node@22.7.5)(sass@1.79.1)) + '@vitest/mocker': 2.1.1(@vitest/spy@2.1.1)(vite@5.4.6(@types/node@22.7.6)(sass@1.79.1)) '@vitest/pretty-format': 2.1.1 '@vitest/runner': 2.1.1 '@vitest/snapshot': 2.1.1 @@ -9122,11 +9122,11 @@ snapshots: tinyexec: 0.3.0 tinypool: 1.0.1 tinyrainbow: 1.2.0 - vite: 5.4.6(@types/node@22.7.5)(sass@1.79.1) - vite-node: 2.1.1(@types/node@22.7.5)(sass@1.79.1) + vite: 5.4.6(@types/node@22.7.6)(sass@1.79.1) + vite-node: 2.1.1(@types/node@22.7.6)(sass@1.79.1) why-is-node-running: 2.3.0 optionalDependencies: - '@types/node': 22.7.5 + '@types/node': 22.7.6 jsdom: 25.0.0 transitivePeerDependencies: - less diff --git a/tests-examples/demo-todo-app.spec.ts b/tests-examples/demo-todo-app.spec.ts deleted file mode 100644 index 8641cb5f5dc..00000000000 --- a/tests-examples/demo-todo-app.spec.ts +++ /dev/null @@ -1,437 +0,0 @@ -import { test, expect, type Page } from '@playwright/test'; - -test.beforeEach(async ({ page }) => { - await page.goto('https://demo.playwright.dev/todomvc'); -}); - -const TODO_ITEMS = [ - 'buy some cheese', - 'feed the cat', - 'book a doctors appointment' -] as const; - -test.describe('New Todo', () => { - test('should allow me to add todo items', async ({ page }) => { - // create a new todo locator - const newTodo = page.getByPlaceholder('What needs to be done?'); - - // Create 1st todo. - await newTodo.fill(TODO_ITEMS[0]); - await newTodo.press('Enter'); - - // Make sure the list only has one todo item. - await expect(page.getByTestId('todo-title')).toHaveText([ - TODO_ITEMS[0] - ]); - - // Create 2nd todo. - await newTodo.fill(TODO_ITEMS[1]); - await newTodo.press('Enter'); - - // Make sure the list now has two todo items. - await expect(page.getByTestId('todo-title')).toHaveText([ - TODO_ITEMS[0], - TODO_ITEMS[1] - ]); - - await checkNumberOfTodosInLocalStorage(page, 2); - }); - - test('should clear text input field when an item is added', async ({ page }) => { - // create a new todo locator - const newTodo = page.getByPlaceholder('What needs to be done?'); - - // Create one todo item. - await newTodo.fill(TODO_ITEMS[0]); - await newTodo.press('Enter'); - - // Check that input is empty. - await expect(newTodo).toBeEmpty(); - await checkNumberOfTodosInLocalStorage(page, 1); - }); - - test('should append new items to the bottom of the list', async ({ page }) => { - // Create 3 items. - await createDefaultTodos(page); - - // create a todo count locator - const todoCount = page.getByTestId('todo-count') - - // Check test using different methods. - await expect(page.getByText('3 items left')).toBeVisible(); - await expect(todoCount).toHaveText('3 items left'); - await expect(todoCount).toContainText('3'); - await expect(todoCount).toHaveText(/3/); - - // Check all items in one call. - await expect(page.getByTestId('todo-title')).toHaveText(TODO_ITEMS); - await checkNumberOfTodosInLocalStorage(page, 3); - }); -}); - -test.describe('Mark all as completed', () => { - test.beforeEach(async ({ page }) => { - await createDefaultTodos(page); - await checkNumberOfTodosInLocalStorage(page, 3); - }); - - test.afterEach(async ({ page }) => { - await checkNumberOfTodosInLocalStorage(page, 3); - }); - - test('should allow me to mark all items as completed', async ({ page }) => { - // Complete all todos. - await page.getByLabel('Mark all as complete').check(); - - // Ensure all todos have 'completed' class. - await expect(page.getByTestId('todo-item')).toHaveClass(['completed', 'completed', 'completed']); - await checkNumberOfCompletedTodosInLocalStorage(page, 3); - }); - - test('should allow me to clear the complete state of all items', async ({ page }) => { - const toggleAll = page.getByLabel('Mark all as complete'); - // Check and then immediately uncheck. - await toggleAll.check(); - await toggleAll.uncheck(); - - // Should be no completed classes. - await expect(page.getByTestId('todo-item')).toHaveClass(['', '', '']); - }); - - test('complete all checkbox should update state when items are completed / cleared', async ({ page }) => { - const toggleAll = page.getByLabel('Mark all as complete'); - await toggleAll.check(); - await expect(toggleAll).toBeChecked(); - await checkNumberOfCompletedTodosInLocalStorage(page, 3); - - // Uncheck first todo. - const firstTodo = page.getByTestId('todo-item').nth(0); - await firstTodo.getByRole('checkbox').uncheck(); - - // Reuse toggleAll locator and make sure its not checked. - await expect(toggleAll).not.toBeChecked(); - - await firstTodo.getByRole('checkbox').check(); - await checkNumberOfCompletedTodosInLocalStorage(page, 3); - - // Assert the toggle all is checked again. - await expect(toggleAll).toBeChecked(); - }); -}); - -test.describe('Item', () => { - - test('should allow me to mark items as complete', async ({ page }) => { - // create a new todo locator - const newTodo = page.getByPlaceholder('What needs to be done?'); - - // Create two items. - for (const item of TODO_ITEMS.slice(0, 2)) { - await newTodo.fill(item); - await newTodo.press('Enter'); - } - - // Check first item. - const firstTodo = page.getByTestId('todo-item').nth(0); - await firstTodo.getByRole('checkbox').check(); - await expect(firstTodo).toHaveClass('completed'); - - // Check second item. - const secondTodo = page.getByTestId('todo-item').nth(1); - await expect(secondTodo).not.toHaveClass('completed'); - await secondTodo.getByRole('checkbox').check(); - - // Assert completed class. - await expect(firstTodo).toHaveClass('completed'); - await expect(secondTodo).toHaveClass('completed'); - }); - - test('should allow me to un-mark items as complete', async ({ page }) => { - // create a new todo locator - const newTodo = page.getByPlaceholder('What needs to be done?'); - - // Create two items. - for (const item of TODO_ITEMS.slice(0, 2)) { - await newTodo.fill(item); - await newTodo.press('Enter'); - } - - const firstTodo = page.getByTestId('todo-item').nth(0); - const secondTodo = page.getByTestId('todo-item').nth(1); - const firstTodoCheckbox = firstTodo.getByRole('checkbox'); - - await firstTodoCheckbox.check(); - await expect(firstTodo).toHaveClass('completed'); - await expect(secondTodo).not.toHaveClass('completed'); - await checkNumberOfCompletedTodosInLocalStorage(page, 1); - - await firstTodoCheckbox.uncheck(); - await expect(firstTodo).not.toHaveClass('completed'); - await expect(secondTodo).not.toHaveClass('completed'); - await checkNumberOfCompletedTodosInLocalStorage(page, 0); - }); - - test('should allow me to edit an item', async ({ page }) => { - await createDefaultTodos(page); - - const todoItems = page.getByTestId('todo-item'); - const secondTodo = todoItems.nth(1); - await secondTodo.dblclick(); - await expect(secondTodo.getByRole('textbox', { name: 'Edit' })).toHaveValue(TODO_ITEMS[1]); - await secondTodo.getByRole('textbox', { name: 'Edit' }).fill('buy some sausages'); - await secondTodo.getByRole('textbox', { name: 'Edit' }).press('Enter'); - - // Explicitly assert the new text value. - await expect(todoItems).toHaveText([ - TODO_ITEMS[0], - 'buy some sausages', - TODO_ITEMS[2] - ]); - await checkTodosInLocalStorage(page, 'buy some sausages'); - }); -}); - -test.describe('Editing', () => { - test.beforeEach(async ({ page }) => { - await createDefaultTodos(page); - await checkNumberOfTodosInLocalStorage(page, 3); - }); - - test('should hide other controls when editing', async ({ page }) => { - const todoItem = page.getByTestId('todo-item').nth(1); - await todoItem.dblclick(); - await expect(todoItem.getByRole('checkbox')).not.toBeVisible(); - await expect(todoItem.locator('label', { - hasText: TODO_ITEMS[1], - })).not.toBeVisible(); - await checkNumberOfTodosInLocalStorage(page, 3); - }); - - test('should save edits on blur', async ({ page }) => { - const todoItems = page.getByTestId('todo-item'); - await todoItems.nth(1).dblclick(); - await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).fill('buy some sausages'); - await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).dispatchEvent('blur'); - - await expect(todoItems).toHaveText([ - TODO_ITEMS[0], - 'buy some sausages', - TODO_ITEMS[2], - ]); - await checkTodosInLocalStorage(page, 'buy some sausages'); - }); - - test('should trim entered text', async ({ page }) => { - const todoItems = page.getByTestId('todo-item'); - await todoItems.nth(1).dblclick(); - await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).fill(' buy some sausages '); - await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).press('Enter'); - - await expect(todoItems).toHaveText([ - TODO_ITEMS[0], - 'buy some sausages', - TODO_ITEMS[2], - ]); - await checkTodosInLocalStorage(page, 'buy some sausages'); - }); - - test('should remove the item if an empty text string was entered', async ({ page }) => { - const todoItems = page.getByTestId('todo-item'); - await todoItems.nth(1).dblclick(); - await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).fill(''); - await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).press('Enter'); - - await expect(todoItems).toHaveText([ - TODO_ITEMS[0], - TODO_ITEMS[2], - ]); - }); - - test('should cancel edits on escape', async ({ page }) => { - const todoItems = page.getByTestId('todo-item'); - await todoItems.nth(1).dblclick(); - await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).fill('buy some sausages'); - await todoItems.nth(1).getByRole('textbox', { name: 'Edit' }).press('Escape'); - await expect(todoItems).toHaveText(TODO_ITEMS); - }); -}); - -test.describe('Counter', () => { - test('should display the current number of todo items', async ({ page }) => { - // create a new todo locator - const newTodo = page.getByPlaceholder('What needs to be done?'); - - // create a todo count locator - const todoCount = page.getByTestId('todo-count') - - await newTodo.fill(TODO_ITEMS[0]); - await newTodo.press('Enter'); - - await expect(todoCount).toContainText('1'); - - await newTodo.fill(TODO_ITEMS[1]); - await newTodo.press('Enter'); - await expect(todoCount).toContainText('2'); - - await checkNumberOfTodosInLocalStorage(page, 2); - }); -}); - -test.describe('Clear completed button', () => { - test.beforeEach(async ({ page }) => { - await createDefaultTodos(page); - }); - - test('should display the correct text', async ({ page }) => { - await page.locator('.todo-list li .toggle').first().check(); - await expect(page.getByRole('button', { name: 'Clear completed' })).toBeVisible(); - }); - - test('should remove completed items when clicked', async ({ page }) => { - const todoItems = page.getByTestId('todo-item'); - await todoItems.nth(1).getByRole('checkbox').check(); - await page.getByRole('button', { name: 'Clear completed' }).click(); - await expect(todoItems).toHaveCount(2); - await expect(todoItems).toHaveText([TODO_ITEMS[0], TODO_ITEMS[2]]); - }); - - test('should be hidden when there are no items that are completed', async ({ page }) => { - await page.locator('.todo-list li .toggle').first().check(); - await page.getByRole('button', { name: 'Clear completed' }).click(); - await expect(page.getByRole('button', { name: 'Clear completed' })).toBeHidden(); - }); -}); - -test.describe('Persistence', () => { - test('should persist its data', async ({ page }) => { - // create a new todo locator - const newTodo = page.getByPlaceholder('What needs to be done?'); - - for (const item of TODO_ITEMS.slice(0, 2)) { - await newTodo.fill(item); - await newTodo.press('Enter'); - } - - const todoItems = page.getByTestId('todo-item'); - const firstTodoCheck = todoItems.nth(0).getByRole('checkbox'); - await firstTodoCheck.check(); - await expect(todoItems).toHaveText([TODO_ITEMS[0], TODO_ITEMS[1]]); - await expect(firstTodoCheck).toBeChecked(); - await expect(todoItems).toHaveClass(['completed', '']); - - // Ensure there is 1 completed item. - await checkNumberOfCompletedTodosInLocalStorage(page, 1); - - // Now reload. - await page.reload(); - await expect(todoItems).toHaveText([TODO_ITEMS[0], TODO_ITEMS[1]]); - await expect(firstTodoCheck).toBeChecked(); - await expect(todoItems).toHaveClass(['completed', '']); - }); -}); - -test.describe('Routing', () => { - test.beforeEach(async ({ page }) => { - await createDefaultTodos(page); - // make sure the app had a chance to save updated todos in storage - // before navigating to a new view, otherwise the items can get lost :( - // in some frameworks like Durandal - await checkTodosInLocalStorage(page, TODO_ITEMS[0]); - }); - - test('should allow me to display active items', async ({ page }) => { - const todoItem = page.getByTestId('todo-item'); - await page.getByTestId('todo-item').nth(1).getByRole('checkbox').check(); - - await checkNumberOfCompletedTodosInLocalStorage(page, 1); - await page.getByRole('link', { name: 'Active' }).click(); - await expect(todoItem).toHaveCount(2); - await expect(todoItem).toHaveText([TODO_ITEMS[0], TODO_ITEMS[2]]); - }); - - test('should respect the back button', async ({ page }) => { - const todoItem = page.getByTestId('todo-item'); - await page.getByTestId('todo-item').nth(1).getByRole('checkbox').check(); - - await checkNumberOfCompletedTodosInLocalStorage(page, 1); - - await test.step('Showing all items', async () => { - await page.getByRole('link', { name: 'All' }).click(); - await expect(todoItem).toHaveCount(3); - }); - - await test.step('Showing active items', async () => { - await page.getByRole('link', { name: 'Active' }).click(); - }); - - await test.step('Showing completed items', async () => { - await page.getByRole('link', { name: 'Completed' }).click(); - }); - - await expect(todoItem).toHaveCount(1); - await page.goBack(); - await expect(todoItem).toHaveCount(2); - await page.goBack(); - await expect(todoItem).toHaveCount(3); - }); - - test('should allow me to display completed items', async ({ page }) => { - await page.getByTestId('todo-item').nth(1).getByRole('checkbox').check(); - await checkNumberOfCompletedTodosInLocalStorage(page, 1); - await page.getByRole('link', { name: 'Completed' }).click(); - await expect(page.getByTestId('todo-item')).toHaveCount(1); - }); - - test('should allow me to display all items', async ({ page }) => { - await page.getByTestId('todo-item').nth(1).getByRole('checkbox').check(); - await checkNumberOfCompletedTodosInLocalStorage(page, 1); - await page.getByRole('link', { name: 'Active' }).click(); - await page.getByRole('link', { name: 'Completed' }).click(); - await page.getByRole('link', { name: 'All' }).click(); - await expect(page.getByTestId('todo-item')).toHaveCount(3); - }); - - test('should highlight the currently applied filter', async ({ page }) => { - await expect(page.getByRole('link', { name: 'All' })).toHaveClass('selected'); - - //create locators for active and completed links - const activeLink = page.getByRole('link', { name: 'Active' }); - const completedLink = page.getByRole('link', { name: 'Completed' }); - await activeLink.click(); - - // Page change - active items. - await expect(activeLink).toHaveClass('selected'); - await completedLink.click(); - - // Page change - completed items. - await expect(completedLink).toHaveClass('selected'); - }); -}); - -async function createDefaultTodos(page: Page) { - // create a new todo locator - const newTodo = page.getByPlaceholder('What needs to be done?'); - - for (const item of TODO_ITEMS) { - await newTodo.fill(item); - await newTodo.press('Enter'); - } -} - -async function checkNumberOfTodosInLocalStorage(page: Page, expected: number) { - return await page.waitForFunction(e => { - return JSON.parse(localStorage['react-todos']).length === e; - }, expected); -} - -async function checkNumberOfCompletedTodosInLocalStorage(page: Page, expected: number) { - return await page.waitForFunction(e => { - return JSON.parse(localStorage['react-todos']).filter((todo: any) => todo.completed).length === e; - }, expected); -} - -async function checkTodosInLocalStorage(page: Page, title: string) { - return await page.waitForFunction(t => { - return JSON.parse(localStorage['react-todos']).map((todo: any) => todo.title).includes(t); - }, title); -}