From 7305a31b53ce2f26dc176946e93e38aea9467e8b Mon Sep 17 00:00:00 2001 From: Zakaria_ <135060272+Zako563@users.noreply.github.com> Date: Mon, 11 Nov 2024 16:56:28 -0500 Subject: [PATCH 01/14] test for get emergency by id (#1028) **JIRA:** link to jira ticket ## Context: What is the ticket about and why are we doing this change. ## Does this PR change the .vscode folder in petclinic-frontend?: If the PR changes the .vscode folder, explain why in detail because it should not. Be sure to include cgerard321 as a reviewer. **Reviewers need to check for any changes to the .vscode folder and add a comment about it to their review comments.** ## Changes What are the various changes and what other modules do those changes affect. This can be bullet point or sentence format. ## Before and After UI (Required for UI-impacting PRs) --add a test for emergency by id If this is a change to the UI, include before and after screenshots to show the differences. If this is a new UI feature, include screenshots to show reviewers what it looks like. ## Dev notes (Optional) Specific technical changes that should be noted ## Linked pull requests (Optional) Pull request links Co-authored-by: Zakaria_ <135060272+tramway23@users.noreply.github.com> --- .../tests/ViewEmergencyById.spec.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 petclinic-frontend/tests/ViewEmergencyById.spec.ts diff --git a/petclinic-frontend/tests/ViewEmergencyById.spec.ts b/petclinic-frontend/tests/ViewEmergencyById.spec.ts new file mode 100644 index 000000000..65f4b1bed --- /dev/null +++ b/petclinic-frontend/tests/ViewEmergencyById.spec.ts @@ -0,0 +1,17 @@ +import { test, expect } from '@playwright/test'; + +test('test', async ({ page }) => { + await page.goto('http://localhost:3000/users/login'); + await page.getByPlaceholder('Enter your email').click(); + await page.getByPlaceholder('Enter your email').fill('admin@admin.com'); + await page.getByPlaceholder('Enter your password').click(); + await page.getByPlaceholder('Enter your password').fill('pwd'); + await page.getByRole('button', { name: 'Login' }).click(); + await page.getByRole('link', { name: 'Visits' }).click(); + await page + .getByRole('row', { name: 'emergencyId2' }) + .getByRole('button') + .nth(2) + .click(); + //await page.getByRole('button', { name: 'Return to Emergencies' }).click(); +}); From 6fb3225bfea69bc49ea5344a44ccd6c592361f36 Mon Sep 17 00:00:00 2001 From: Valentine Nneji Date: Mon, 11 Nov 2024 17:07:12 -0500 Subject: [PATCH 02/14] Playwright test to unlist a product (#1030) ## Context: Did a playwright test to unlist a product --- ...CoreApp,Version=v8.0.AssemblyAttributes.cs | 4 + .../net8.0/emailing-service.AssemblyInfo.cs | 24 + .../emailing-service.AssemblyInfoInputs.cache | 1 + ....GeneratedMSBuildEditorConfig.editorconfig | 19 + .../net8.0/emailing-service.GlobalUsings.g.cs | 17 + ...CoreApp,Version=v8.0.AssemblyAttributes.cs | 4 + .../net8.0/emailing-service.AssemblyInfo.cs | 24 + .../emailing-service.AssemblyInfoInputs.cache | 1 + ....GeneratedMSBuildEditorConfig.editorconfig | 19 + .../net8.0/emailing-service.GlobalUsings.g.cs | 17 + petclinic-frontend/e2e/example.spec.ts | 18 + petclinic-frontend/package-lock.json | 1 - .../tests-examples/demo-todo-app.spec.ts | 437 ++++++++++++++++++ .../tests/shoppage/shoppagetests.spec.ts | 22 + 14 files changed, 607 insertions(+), 1 deletion(-) create mode 100644 emailing-service/emailing-service/obj/Debug/net8.0/.NETCoreApp,Version=v8.0.AssemblyAttributes.cs create mode 100644 emailing-service/emailing-service/obj/Debug/net8.0/emailing-service.AssemblyInfo.cs create mode 100644 emailing-service/emailing-service/obj/Debug/net8.0/emailing-service.AssemblyInfoInputs.cache create mode 100644 emailing-service/emailing-service/obj/Debug/net8.0/emailing-service.GeneratedMSBuildEditorConfig.editorconfig create mode 100644 emailing-service/emailing-service/obj/Debug/net8.0/emailing-service.GlobalUsings.g.cs create mode 100644 emailing-service/emailing-service/obj/Release/net8.0/.NETCoreApp,Version=v8.0.AssemblyAttributes.cs create mode 100644 emailing-service/emailing-service/obj/Release/net8.0/emailing-service.AssemblyInfo.cs create mode 100644 emailing-service/emailing-service/obj/Release/net8.0/emailing-service.AssemblyInfoInputs.cache create mode 100644 emailing-service/emailing-service/obj/Release/net8.0/emailing-service.GeneratedMSBuildEditorConfig.editorconfig create mode 100644 emailing-service/emailing-service/obj/Release/net8.0/emailing-service.GlobalUsings.g.cs create mode 100644 petclinic-frontend/e2e/example.spec.ts create mode 100644 petclinic-frontend/tests-examples/demo-todo-app.spec.ts create mode 100644 petclinic-frontend/tests/shoppage/shoppagetests.spec.ts diff --git a/emailing-service/emailing-service/obj/Debug/net8.0/.NETCoreApp,Version=v8.0.AssemblyAttributes.cs b/emailing-service/emailing-service/obj/Debug/net8.0/.NETCoreApp,Version=v8.0.AssemblyAttributes.cs new file mode 100644 index 000000000..2217181c8 --- /dev/null +++ b/emailing-service/emailing-service/obj/Debug/net8.0/.NETCoreApp,Version=v8.0.AssemblyAttributes.cs @@ -0,0 +1,4 @@ +// +using System; +using System.Reflection; +[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETCoreApp,Version=v8.0", FrameworkDisplayName = ".NET 8.0")] diff --git a/emailing-service/emailing-service/obj/Debug/net8.0/emailing-service.AssemblyInfo.cs b/emailing-service/emailing-service/obj/Debug/net8.0/emailing-service.AssemblyInfo.cs new file mode 100644 index 000000000..0fa1ff381 --- /dev/null +++ b/emailing-service/emailing-service/obj/Debug/net8.0/emailing-service.AssemblyInfo.cs @@ -0,0 +1,24 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +using System; +using System.Reflection; + +[assembly: System.Reflection.AssemblyCompanyAttribute("emailing-service")] +[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] +[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+fdaa04180dd32c36d98b3809e2447e007318db58")] +[assembly: System.Reflection.AssemblyProductAttribute("emailing-service")] +[assembly: System.Reflection.AssemblyTitleAttribute("emailing-service")] +[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] +[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("emailing-service-test")] + +// Generated by the MSBuild WriteCodeFragment class. + diff --git a/emailing-service/emailing-service/obj/Debug/net8.0/emailing-service.AssemblyInfoInputs.cache b/emailing-service/emailing-service/obj/Debug/net8.0/emailing-service.AssemblyInfoInputs.cache new file mode 100644 index 000000000..6a42217dd --- /dev/null +++ b/emailing-service/emailing-service/obj/Debug/net8.0/emailing-service.AssemblyInfoInputs.cache @@ -0,0 +1 @@ +7bf0a9728cde5f1afe2ae8025a609b440ad50fe1158c532a0a20adc5d4a3bce7 diff --git a/emailing-service/emailing-service/obj/Debug/net8.0/emailing-service.GeneratedMSBuildEditorConfig.editorconfig b/emailing-service/emailing-service/obj/Debug/net8.0/emailing-service.GeneratedMSBuildEditorConfig.editorconfig new file mode 100644 index 000000000..fbaabd102 --- /dev/null +++ b/emailing-service/emailing-service/obj/Debug/net8.0/emailing-service.GeneratedMSBuildEditorConfig.editorconfig @@ -0,0 +1,19 @@ +is_global = true +build_property.TargetFramework = net8.0 +build_property.TargetPlatformMinVersion = +build_property.UsingMicrosoftNETSdkWeb = true +build_property.ProjectTypeGuids = +build_property.InvariantGlobalization = +build_property.PlatformNeutralAssembly = +build_property.EnforceExtendedAnalyzerRules = +build_property._SupportedPlatformList = Linux,macOS,Windows +build_property.RootNamespace = emailing_service +build_property.RootNamespace = emailing_service +build_property.ProjectDir = C:\Users\nneji\Github\champlain_petclinic\emailing-service\emailing-service\ +build_property.EnableComHosting = +build_property.EnableGeneratedComInterfaceComImportInterop = +build_property.RazorLangVersion = 8.0 +build_property.SupportLocalizedComponentNames = +build_property.GenerateRazorMetadataSourceChecksumAttributes = +build_property.MSBuildProjectDirectory = C:\Users\nneji\Github\champlain_petclinic\emailing-service\emailing-service +build_property._RazorSourceGeneratorDebug = diff --git a/emailing-service/emailing-service/obj/Debug/net8.0/emailing-service.GlobalUsings.g.cs b/emailing-service/emailing-service/obj/Debug/net8.0/emailing-service.GlobalUsings.g.cs new file mode 100644 index 000000000..025530a29 --- /dev/null +++ b/emailing-service/emailing-service/obj/Debug/net8.0/emailing-service.GlobalUsings.g.cs @@ -0,0 +1,17 @@ +// +global using global::Microsoft.AspNetCore.Builder; +global using global::Microsoft.AspNetCore.Hosting; +global using global::Microsoft.AspNetCore.Http; +global using global::Microsoft.AspNetCore.Routing; +global using global::Microsoft.Extensions.Configuration; +global using global::Microsoft.Extensions.DependencyInjection; +global using global::Microsoft.Extensions.Hosting; +global using global::Microsoft.Extensions.Logging; +global using global::System; +global using global::System.Collections.Generic; +global using global::System.IO; +global using global::System.Linq; +global using global::System.Net.Http; +global using global::System.Net.Http.Json; +global using global::System.Threading; +global using global::System.Threading.Tasks; diff --git a/emailing-service/emailing-service/obj/Release/net8.0/.NETCoreApp,Version=v8.0.AssemblyAttributes.cs b/emailing-service/emailing-service/obj/Release/net8.0/.NETCoreApp,Version=v8.0.AssemblyAttributes.cs new file mode 100644 index 000000000..2217181c8 --- /dev/null +++ b/emailing-service/emailing-service/obj/Release/net8.0/.NETCoreApp,Version=v8.0.AssemblyAttributes.cs @@ -0,0 +1,4 @@ +// +using System; +using System.Reflection; +[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETCoreApp,Version=v8.0", FrameworkDisplayName = ".NET 8.0")] diff --git a/emailing-service/emailing-service/obj/Release/net8.0/emailing-service.AssemblyInfo.cs b/emailing-service/emailing-service/obj/Release/net8.0/emailing-service.AssemblyInfo.cs new file mode 100644 index 000000000..2b58ebfdf --- /dev/null +++ b/emailing-service/emailing-service/obj/Release/net8.0/emailing-service.AssemblyInfo.cs @@ -0,0 +1,24 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +using System; +using System.Reflection; + +[assembly: System.Reflection.AssemblyCompanyAttribute("emailing-service")] +[assembly: System.Reflection.AssemblyConfigurationAttribute("Release")] +[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+fdaa04180dd32c36d98b3809e2447e007318db58")] +[assembly: System.Reflection.AssemblyProductAttribute("emailing-service")] +[assembly: System.Reflection.AssemblyTitleAttribute("emailing-service")] +[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] +[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("emailing-service-test")] + +// Generated by the MSBuild WriteCodeFragment class. + diff --git a/emailing-service/emailing-service/obj/Release/net8.0/emailing-service.AssemblyInfoInputs.cache b/emailing-service/emailing-service/obj/Release/net8.0/emailing-service.AssemblyInfoInputs.cache new file mode 100644 index 000000000..0dd579d33 --- /dev/null +++ b/emailing-service/emailing-service/obj/Release/net8.0/emailing-service.AssemblyInfoInputs.cache @@ -0,0 +1 @@ +c4cd523c82050fd023f7beda18c0487395a670c00681e1c920589e0d5671d06e diff --git a/emailing-service/emailing-service/obj/Release/net8.0/emailing-service.GeneratedMSBuildEditorConfig.editorconfig b/emailing-service/emailing-service/obj/Release/net8.0/emailing-service.GeneratedMSBuildEditorConfig.editorconfig new file mode 100644 index 000000000..fbaabd102 --- /dev/null +++ b/emailing-service/emailing-service/obj/Release/net8.0/emailing-service.GeneratedMSBuildEditorConfig.editorconfig @@ -0,0 +1,19 @@ +is_global = true +build_property.TargetFramework = net8.0 +build_property.TargetPlatformMinVersion = +build_property.UsingMicrosoftNETSdkWeb = true +build_property.ProjectTypeGuids = +build_property.InvariantGlobalization = +build_property.PlatformNeutralAssembly = +build_property.EnforceExtendedAnalyzerRules = +build_property._SupportedPlatformList = Linux,macOS,Windows +build_property.RootNamespace = emailing_service +build_property.RootNamespace = emailing_service +build_property.ProjectDir = C:\Users\nneji\Github\champlain_petclinic\emailing-service\emailing-service\ +build_property.EnableComHosting = +build_property.EnableGeneratedComInterfaceComImportInterop = +build_property.RazorLangVersion = 8.0 +build_property.SupportLocalizedComponentNames = +build_property.GenerateRazorMetadataSourceChecksumAttributes = +build_property.MSBuildProjectDirectory = C:\Users\nneji\Github\champlain_petclinic\emailing-service\emailing-service +build_property._RazorSourceGeneratorDebug = diff --git a/emailing-service/emailing-service/obj/Release/net8.0/emailing-service.GlobalUsings.g.cs b/emailing-service/emailing-service/obj/Release/net8.0/emailing-service.GlobalUsings.g.cs new file mode 100644 index 000000000..025530a29 --- /dev/null +++ b/emailing-service/emailing-service/obj/Release/net8.0/emailing-service.GlobalUsings.g.cs @@ -0,0 +1,17 @@ +// +global using global::Microsoft.AspNetCore.Builder; +global using global::Microsoft.AspNetCore.Hosting; +global using global::Microsoft.AspNetCore.Http; +global using global::Microsoft.AspNetCore.Routing; +global using global::Microsoft.Extensions.Configuration; +global using global::Microsoft.Extensions.DependencyInjection; +global using global::Microsoft.Extensions.Hosting; +global using global::Microsoft.Extensions.Logging; +global using global::System; +global using global::System.Collections.Generic; +global using global::System.IO; +global using global::System.Linq; +global using global::System.Net.Http; +global using global::System.Net.Http.Json; +global using global::System.Threading; +global using global::System.Threading.Tasks; diff --git a/petclinic-frontend/e2e/example.spec.ts b/petclinic-frontend/e2e/example.spec.ts new file mode 100644 index 000000000..54a906a4e --- /dev/null +++ b/petclinic-frontend/e2e/example.spec.ts @@ -0,0 +1,18 @@ +import { test, expect } from '@playwright/test'; + +test('has title', async ({ page }) => { + await page.goto('https://playwright.dev/'); + + // Expect a title "to contain" a substring. + await expect(page).toHaveTitle(/Playwright/); +}); + +test('get started link', async ({ page }) => { + await page.goto('https://playwright.dev/'); + + // Click the get started link. + await page.getByRole('link', { name: 'Get started' }).click(); + + // Expects page to have a heading with the name of Installation. + await expect(page.getByRole('heading', { name: 'Installation' })).toBeVisible(); +}); diff --git a/petclinic-frontend/package-lock.json b/petclinic-frontend/package-lock.json index f47f40a89..f28651f3a 100644 --- a/petclinic-frontend/package-lock.json +++ b/petclinic-frontend/package-lock.json @@ -704,7 +704,6 @@ "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.48.2.tgz", "integrity": "sha512-54w1xCWfXuax7dz4W2M9uw0gDyh+ti/0K/MxcCUxChFh37kkdxPdfZDw5QBbuPUJHr1CiHJ1hXgSs+GgeQc5Zw==", "dev": true, - "license": "Apache-2.0", "dependencies": { "playwright": "1.48.2" }, diff --git a/petclinic-frontend/tests-examples/demo-todo-app.spec.ts b/petclinic-frontend/tests-examples/demo-todo-app.spec.ts new file mode 100644 index 000000000..8641cb5f5 --- /dev/null +++ b/petclinic-frontend/tests-examples/demo-todo-app.spec.ts @@ -0,0 +1,437 @@ +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); +} diff --git a/petclinic-frontend/tests/shoppage/shoppagetests.spec.ts b/petclinic-frontend/tests/shoppage/shoppagetests.spec.ts new file mode 100644 index 000000000..9982c6395 --- /dev/null +++ b/petclinic-frontend/tests/shoppage/shoppagetests.spec.ts @@ -0,0 +1,22 @@ +import { test, expect } from '@playwright/test'; + +test('Unlist Product', async ({ page }) => { +//Authenticate as admin +await page.goto('http://localhost:3000/users/login'); +await page.getByPlaceholder('Enter your email').fill('admin@admin.com'); +await page.getByPlaceholder('Enter your password').fill('pwd'); +await page.getByRole('button', { name: 'Login' }).click(); + +await page.waitForURL('http://localhost:3000/home'); + +await page.getByRole('link', { name: 'Shop' }).click(); + +await page.getByRole('heading', { name: 'Fish Tank Heater' }).first().click(); +await page.getByRole('button', { name: 'Unlist Item' }).click(); +await page.getByRole('button', { name: 'Yes' }).click(); + +await expect(page.getByRole('button', { name: 'List Item' })).toBeVisible(); + +await page.close(); + +}); \ No newline at end of file From 6eeee3a71df501c5b42ce658905dd8b494d3ff23 Mon Sep 17 00:00:00 2001 From: Viktor Kuts Date: Mon, 11 Nov 2024 17:15:23 -0500 Subject: [PATCH 03/14] PROD Product Details E2E Test (#1033) **JIRA:** link to jira ticket ## Context: What is the ticket about and why are we doing this change. ## Does this PR change the .vscode folder in petclinic-frontend?: If the PR changes the .vscode folder, explain why in detail because it should not. Be sure to include cgerard321 as a reviewer. **Reviewers need to check for any changes to the .vscode folder and add a comment about it to their review comments.** ## Changes What are the various changes and what other modules do those changes affect. This can be bullet point or sentence format. ## Before and After UI (Required for UI-impacting PRs) If this is a change to the UI, include before and after screenshots to show the differences. If this is a new UI feature, include screenshots to show reviewers what it looks like. ## Dev notes (Optional) Specific technical changes that should be noted ## Linked pull requests (Optional) Pull request links Co-authored-by: Jessy Gjerek <118135201+J91-cloud@users.noreply.github.com> --- .../tests/productspage/viewproduct.spec.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 petclinic-frontend/tests/productspage/viewproduct.spec.ts diff --git a/petclinic-frontend/tests/productspage/viewproduct.spec.ts b/petclinic-frontend/tests/productspage/viewproduct.spec.ts new file mode 100644 index 000000000..c8db141ba --- /dev/null +++ b/petclinic-frontend/tests/productspage/viewproduct.spec.ts @@ -0,0 +1,16 @@ +import { test, expect } from '@playwright/test'; + +test('View Shop Product Title', async ({ page }) => { + await page.goto('http://localhost:3000/home'); + await page.getByRole('link', { name: 'Login' }).click(); + await page.getByPlaceholder('Enter your email').click(); + await page.getByPlaceholder('Enter your email').fill('admin@admin.com'); + await page.getByPlaceholder('Enter your password').click(); + await page.getByPlaceholder('Enter your password').fill('pwd'); + await page.getByRole('button', { name: 'Login' }).click(); + await page.getByRole('link', { name: 'Shop' }).click(); + await page.getByRole('heading', { name: 'Aquarium Filter' }).first().click(); + await expect( + page.getByRole('heading', { name: 'Aquarium Filter', exact: true }) + ).toContainText('Aquarium Filter'); +}); From 3dc11994053137eedff85496c3194d6363376505 Mon Sep 17 00:00:00 2001 From: Justin Morissette <123003289+Justin222993@users.noreply.github.com> Date: Mon, 11 Nov 2024 17:23:55 -0500 Subject: [PATCH 04/14] Created the new Emailing Test (#1029) # New test: Check if we can send an email Co-authored-by: Felix Allard <132389716+FelixAllard@users.noreply.github.com> --- .../tests/emailing/emailingpagetests.spec.ts | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 petclinic-frontend/tests/emailing/emailingpagetests.spec.ts diff --git a/petclinic-frontend/tests/emailing/emailingpagetests.spec.ts b/petclinic-frontend/tests/emailing/emailingpagetests.spec.ts new file mode 100644 index 000000000..52168fe91 --- /dev/null +++ b/petclinic-frontend/tests/emailing/emailingpagetests.spec.ts @@ -0,0 +1,25 @@ +import { test, expect } from '@playwright/test'; + +test('Sending Email Test', async ({ page }) => { + await page.goto('http://localhost:3000/users/login'); + await page.getByPlaceholder('Enter your email').click(); + await page.getByPlaceholder('Enter your email').fill('admin@admin.com'); + await page.getByPlaceholder('Enter your password').click(); + await page.getByPlaceholder('Enter your password').fill('pwd'); + await page.getByRole('button', { name: 'Login' }).click(); + await page.getByRole('link', { name: 'Emails' }).click(); + await page.getByRole('button', { name: 'Send Raw Email' }).click(); + await page.locator('input[type="email"]').click(); + await page.locator('input[type="email"]').fill('xilef992@gmail.com'); + await page.locator('input[type="email"]').press('Tab'); + await page.locator('input[type="text"]').fill('TestEmail'); + await page.locator('input[type="text"]').press('Tab'); + await page.locator('textarea').fill('This is a test email'); + await page.getByRole('button', { name: 'Submit' }).click(); + await expect(page.getByText('Status Code:')).toBeVisible(); + await expect(page.locator('#root')).toContainText( + 'Message: Email sent successfully' + ); + + await page.close(); +}); From 63c48ff96d9f21bb026341774067e8754f8b3715 Mon Sep 17 00:00:00 2001 From: Jesse Bourassa <129144730+Jesse-Bourassa@users.noreply.github.com> Date: Mon, 11 Nov 2024 17:32:08 -0500 Subject: [PATCH 05/14] Test Signup page (#1035) --- .../tests/signuppage/signuppagetests.spec.ts | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 petclinic-frontend/tests/signuppage/signuppagetests.spec.ts diff --git a/petclinic-frontend/tests/signuppage/signuppagetests.spec.ts b/petclinic-frontend/tests/signuppage/signuppagetests.spec.ts new file mode 100644 index 000000000..7597eec74 --- /dev/null +++ b/petclinic-frontend/tests/signuppage/signuppagetests.spec.ts @@ -0,0 +1,29 @@ +import { test, expect } from '@playwright/test'; + +test('test', async ({ page }) => { +await page.goto('http://localhost:3000/home'); +await page.getByRole('link', { name: 'Signup' }).click(); +await page.locator('input[name="firstName"]').click(); +await page.locator('input[name="firstName"]').fill('ew'); +await page.locator('input[name="lastName"]').click(); +await page.locator('input[name="lastName"]').fill('ew'); +await page.locator('input[name="address"]').click(); +await page.locator('input[name="address"]').fill('jesse'); +await page.locator('input[name="city"]').click(); +await page.locator('input[name="city"]').fill('stjean'); +await page.locator('input[name="province"]').click(); +await page.locator('input[name="province"]').fill('qc'); +await page.locator('input[name="telephone"]').click(); +await page.locator('input[name="telephone"]').fill('1234567890'); +await page.locator('input[name="username"]').click(); +await page.locator('input[name="username"]').fill('wewew'); +await page.locator('input[name="email"]').click(); +await page.locator('input[name="email"]').fill('wrongemail'); +await page.locator('input[name="password"]').click(); +await page.locator('input[name="password"]').press('CapsLock'); +await page.locator('input[name="password"]').fill('P'); +await page.locator('input[name="password"]').press('CapsLock'); +await page.locator('input[name="password"]').fill('Password12:'); +await page.getByRole('button', { name: 'Send Verification Email' }).click(); +await expect(page.locator('form')).toContainText('Invalid email format.'); +}); \ No newline at end of file From e40256676bb74a0b9d0f274a62de9faf516f3d65 Mon Sep 17 00:00:00 2001 From: Debo Date: Mon, 11 Nov 2024 17:40:06 -0500 Subject: [PATCH 06/14] created test for admin edit customer (#1031) --- .../customerspage/customerspagetests.spec.ts | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/petclinic-frontend/tests/customerspage/customerspagetests.spec.ts b/petclinic-frontend/tests/customerspage/customerspagetests.spec.ts index 49732f270..4fa9d58ca 100644 --- a/petclinic-frontend/tests/customerspage/customerspagetests.spec.ts +++ b/petclinic-frontend/tests/customerspage/customerspagetests.spec.ts @@ -79,3 +79,37 @@ test('Get User By Id works and connected customer link works and right info', as await page.close(); }); + +test('Admin Edit Customer', async ({ page }) => { + await page.goto('http://localhost:3000/users/login'); + await page.getByPlaceholder('Enter your email').click(); + await page.getByPlaceholder('Enter your email').fill('admin@admin.com'); + await page.getByPlaceholder('Enter your password').click(); + await page.getByPlaceholder('Enter your password').fill('pwd'); + await page.getByRole('button', { name: 'Login' }).click(); + await page.getByRole('button', { name: 'Customers' }).click(); + await page.getByRole('link', { name: 'Customers List' }).click(); + await page.getByRole('link', { name: 'e6c7398e-8ac4-4e10-9ee0-' }).click(); + await page.getByRole('button', { name: 'Edit Customer' }).click(); + await page.locator('input[name="firstName"]').click(); + await page.locator('input[name="firstName"]').fill('John'); + await page.locator('input[name="lastName"]').click(); + await page.locator('input[name="lastName"]').fill('Doe'); + await page.locator('input[name="address"]').click(); + await page.locator('input[name="address"]').fill('Baker Street 123'); + await page.locator('input[name="city"]').click(); + await page.locator('input[name="city"]').fill('Montreal'); + await page.getByRole('combobox').selectOption('Quebec'); + await page.locator('input[name="telephone"]').click(); + await page.locator('input[name="telephone"]').fill('5144203239'); + await page.getByRole('button', { name: 'Update' }).click(); + await expect(page.locator('h2')).toContainText('Success!'); + await expect(page.getByRole('paragraph')).toContainText('Customer has been successfully updated.'); + await page.getByRole('button', { name: 'Close' }).click(); + await expect(page.locator('#root')).toContainText('First Name: John'); + await expect(page.locator('#root')).toContainText('Last Name: Doe'); + await expect(page.locator('#root')).toContainText('City: Montreal'); + await expect(page.locator('#root')).toContainText('Province: Quebec'); + await expect(page.locator('#root')).toContainText('Telephone: 5144203239'); + await page.close(); +}); From 9fdd381cb592b0363d89ee46878592e2ba498725 Mon Sep 17 00:00:00 2001 From: AlejandroBrnab <98438629+AlejandroBrnab@users.noreply.github.com> Date: Mon, 11 Nov 2024 17:49:11 -0500 Subject: [PATCH 07/14] e2etest/VIST-AlejandroBernabe (#1036) my test --- .../tests/visitstestpage/addvisittest.spec.ts | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 petclinic-frontend/tests/visitstestpage/addvisittest.spec.ts diff --git a/petclinic-frontend/tests/visitstestpage/addvisittest.spec.ts b/petclinic-frontend/tests/visitstestpage/addvisittest.spec.ts new file mode 100644 index 000000000..03a163c4e --- /dev/null +++ b/petclinic-frontend/tests/visitstestpage/addvisittest.spec.ts @@ -0,0 +1,27 @@ +import { test, expect } from '@playwright/test'; + +test('test', async ({ page }) => { + await page.goto('http://localhost:3000/users/login'); + await page.getByPlaceholder('Enter your email').click(); + await page.getByPlaceholder('Enter your email').fill('admin@admin.com'); + await page.getByPlaceholder('Enter your password').click(); + await page.getByPlaceholder('Enter your password').fill('pwd'); + await page.getByRole('button', { name: 'Login' }).click(); + await page.getByRole('link', { name: 'Visits' }).click(); + await page.getByRole('button', { name: 'Make a Visit' }).click(); + await page.locator('input[name="petId"]').click(); + await page + .locator('input[name="petId"]') + .fill('0e4d8481-b611-4e52-baed-af16caa8bf8a'); + await page.locator('input[name="visitStartDate"]').click(); + await page.locator('input[name="visitStartDate"]').press('ArrowRight'); + await page.locator('input[name="visitStartDate"]').press('ArrowRight'); + await page.locator('input[name="visitStartDate"]').fill('2024-11-12T17:55'); + await page.locator('input[name="description"]').click(); + await page.locator('input[name="description"]').fill('doggo'); + await page.locator('input[name="practitionerId"]').click(); + await page + .locator('input[name="practitionerId"]') + .fill('69f85d2e-625b-11ee-8c99-0242ac120002'); + await page.getByRole('button', { name: 'Add' }).click(); +}); From 30c076d5ef7bc5fa46fac2316c433ee433c1e604 Mon Sep 17 00:00:00 2001 From: Thomas <90119345+ThomasBedard@users.noreply.github.com> Date: Mon, 11 Nov 2024 17:57:32 -0500 Subject: [PATCH 08/14] e2etest/PROD-Thomas (#1038) ## Context: Made an e2e test for edit a product name ## Does this PR change the .vscode folder in petclinic-frontend?: If the PR changes the .vscode folder, explain why in detail because it should not. it doesn't --- .../tests/productspage/shoppagetests.spec.ts | 20 +++++++++++++++++++ test-results/.last-run.json | 4 ++++ 2 files changed, 24 insertions(+) create mode 100644 petclinic-frontend/tests/productspage/shoppagetests.spec.ts create mode 100644 test-results/.last-run.json diff --git a/petclinic-frontend/tests/productspage/shoppagetests.spec.ts b/petclinic-frontend/tests/productspage/shoppagetests.spec.ts new file mode 100644 index 000000000..8d24cbf3a --- /dev/null +++ b/petclinic-frontend/tests/productspage/shoppagetests.spec.ts @@ -0,0 +1,20 @@ +import { test, expect } from '@playwright/test'; + + +test('Admin View Vet Details from VetPage', async ({ page }) => { +await page.goto('http://localhost:3000/users/login'); +await page.getByPlaceholder('Enter your email').click(); +await page.getByPlaceholder('Enter your email').fill('admin@admin.com'); +await page.getByPlaceholder('Enter your password').click(); +await page.getByPlaceholder('Enter your password').fill('pwd'); +await page.getByRole('button', { name: 'Login' }).click(); +await page.getByRole('link', { name: 'Shop' }).click(); +await page.getByRole('heading', { name: 'Fish Tank Heater' }).nth(1).click(); +await page.getByRole('button', { name: 'Edit' }).click(); +await page.getByLabel('Product Name:').click(); +await page.getByLabel('Product Name:').fill('Fish Tank'); +await page.getByLabel('Product Sale Price:').click(); +await page.getByLabel('Product Sale Price:').fill('19.99'); +await page.getByRole('button', { name: 'Update Product' }).click(); +await (expect(page.getByRole('heading', {name: 'Fish Tank'})).toBeVisible()); +}); \ No newline at end of file diff --git a/test-results/.last-run.json b/test-results/.last-run.json new file mode 100644 index 000000000..5fca3f84b --- /dev/null +++ b/test-results/.last-run.json @@ -0,0 +1,4 @@ +{ + "status": "failed", + "failedTests": [] +} \ No newline at end of file From 24ebe1a9e0856cb1fa0a868c700bcd7cb4d248a1 Mon Sep 17 00:00:00 2001 From: Aian Batoochirov <119423256+orell2j@users.noreply.github.com> Date: Mon, 11 Nov 2024 18:24:47 -0500 Subject: [PATCH 09/14] e2etest/VETS-Aian: E2E testing add vet education (#1047) ## Context: Made an e2e test to add vet education and delete vet education ## Does this PR change the .vscode folder in petclinic-frontend?: No **Reviewers need to check for any changes to the .vscode folder and add a comment about it to their review comments.** ## Changes Added e2e test files for adding and deleteing vet education --- petclinic-frontend/playwright.config.ts | 24 +- .../tests-examples/demo-todo-app.spec.ts | 437 ++++++++++++++++++ .../tests/tests-examples/e2e/test-1.spec.ts | 24 + 3 files changed, 473 insertions(+), 12 deletions(-) create mode 100644 petclinic-frontend/tests/tests-examples/demo-todo-app.spec.ts create mode 100644 petclinic-frontend/tests/tests-examples/e2e/test-1.spec.ts diff --git a/petclinic-frontend/playwright.config.ts b/petclinic-frontend/playwright.config.ts index 630689819..a05d8b5a1 100644 --- a/petclinic-frontend/playwright.config.ts +++ b/petclinic-frontend/playwright.config.ts @@ -34,10 +34,10 @@ export default defineConfig({ /* Configure projects for major browsers */ projects: [ - // { - // name: 'chromium', - // use: { ...devices['Desktop Chrome'] }, - // }, + { + name: 'chromium', + use: { ...devices['Desktop Chrome'] }, + }, { name: 'firefox', @@ -60,14 +60,14 @@ export default defineConfig({ // }, /* Test against branded browsers. */ - { - name: 'Microsoft Edge', - use: { ...devices['Desktop Edge'], channel: 'msedge' }, - }, - { - name: 'Google Chrome', - use: { ...devices['Desktop Chrome'], channel: 'chrome' }, - }, + // { + // 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 */ diff --git a/petclinic-frontend/tests/tests-examples/demo-todo-app.spec.ts b/petclinic-frontend/tests/tests-examples/demo-todo-app.spec.ts new file mode 100644 index 000000000..8641cb5f5 --- /dev/null +++ b/petclinic-frontend/tests/tests-examples/demo-todo-app.spec.ts @@ -0,0 +1,437 @@ +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); +} diff --git a/petclinic-frontend/tests/tests-examples/e2e/test-1.spec.ts b/petclinic-frontend/tests/tests-examples/e2e/test-1.spec.ts new file mode 100644 index 000000000..3f3e24712 --- /dev/null +++ b/petclinic-frontend/tests/tests-examples/e2e/test-1.spec.ts @@ -0,0 +1,24 @@ +import { test, expect } from '@playwright/test'; + +test('test', async ({ page }) => { + await page.goto('http://localhost:3000/users/login'); + await page.getByPlaceholder('Enter your email').click(); + await page.getByPlaceholder('Enter your email').fill('admin@admin.com'); + await page.getByPlaceholder('Enter your password').click(); + await page.getByPlaceholder('Enter your password').fill('pwd'); + await page.getByRole('button', { name: 'Login' }).click(); + await page.getByRole('link', { name: 'Veterinarians' }).click(); + await page.locator('.card-image').first().click(); + await page.getByRole('button', { name: 'Add Education' }).nth(1).click(); + await page.getByRole('button', { name: 'Add Education' }).nth(1).click(); + await page.locator('div').filter({ hasText: /^School Name$/ }).getByRole('textbox').click(); + await page.locator('div').filter({ hasText: /^School Name$/ }).getByRole('textbox').fill('Champlain College'); + await page.locator('div').filter({ hasText: /^Degree$/ }).getByRole('textbox').click(); + await page.locator('div').filter({ hasText: /^Degree$/ }).getByRole('textbox').fill('Cegep'); + await page.locator('div').filter({ hasText: /^Field of Study$/ }).getByRole('textbox').click(); + await page.locator('div').filter({ hasText: /^Field of Study$/ }).getByRole('textbox').fill('Computer Science'); + await page.locator('div').filter({ hasText: /^Start Date$/ }).getByRole('textbox').fill('2021-08-23'); + await page.locator('div').filter({ hasText: /^End Date$/ }).getByRole('textbox').fill('2025-05-16'); + await page.getByRole('dialog').getByRole('button', { name: 'Add Education' }).click(); + await page.getByRole('button', { name: 'Delete Education' }).nth(2).click(); +}); \ No newline at end of file From d9af6ffdb8e039f741ebd435ec13c643bb9dd9e9 Mon Sep 17 00:00:00 2001 From: Vinicius Velozo de Sousa <77692089+vinivelozo@users.noreply.github.com> Date: Mon, 11 Nov 2024 18:59:40 -0500 Subject: [PATCH 10/14] Test for search by description (#1039) Test for search by description (INVT) --- .../FindInventoryByDescription.spec.ts | 15 +++++++++++++++ petclinic-frontend/tests/test-1.spec.ts | 5 +++++ 2 files changed, 20 insertions(+) create mode 100644 petclinic-frontend/tests/inventoriespage/FindInventoryByDescription.spec.ts create mode 100644 petclinic-frontend/tests/test-1.spec.ts diff --git a/petclinic-frontend/tests/inventoriespage/FindInventoryByDescription.spec.ts b/petclinic-frontend/tests/inventoriespage/FindInventoryByDescription.spec.ts new file mode 100644 index 000000000..e7a18cda9 --- /dev/null +++ b/petclinic-frontend/tests/inventoriespage/FindInventoryByDescription.spec.ts @@ -0,0 +1,15 @@ +import { test, expect } from '@playwright/test'; + +test('test', async ({ page }) => { + await page.goto('http://localhost:3000/users/login'); + await page.getByPlaceholder('Enter your email').click(); + await page.getByPlaceholder('Enter your email').fill('admin@admin.com'); + await page.getByPlaceholder('Enter your password').click(); + await page.getByPlaceholder('Enter your password').fill('pwd'); + await page.getByRole('button', { name: 'Login' }).click(); + await page.getByRole('link', { name: 'Inventories' }).click(); + await page.getByRole('textbox').nth(1).click(); + await page.getByRole('textbox').nth(1).fill('tools'); + await page.getByRole('button', { name: 'Search' }).click(); + await expect(page.getByText('Tools for performing surgical')).toBeVisible(); +}); \ No newline at end of file diff --git a/petclinic-frontend/tests/test-1.spec.ts b/petclinic-frontend/tests/test-1.spec.ts new file mode 100644 index 000000000..5b3d48cfd --- /dev/null +++ b/petclinic-frontend/tests/test-1.spec.ts @@ -0,0 +1,5 @@ +import { test, expect } from '@playwright/test'; + +test('test', async ({ page }) => { + // Recording... +}); \ No newline at end of file From d43ae71913d35aae15838c05772a2b1676497f0d Mon Sep 17 00:00:00 2001 From: Carlos Alvarado <142922516+Carlos-123321@users.noreply.github.com> Date: Mon, 11 Nov 2024 19:50:48 -0500 Subject: [PATCH 11/14] Test for updating an inventory (#1051) **JIRA:** link to jira ticket ## Context: Added a test which checks that if an inventory is updated correctly, it should display a message saying "Inventory updated successfully". --- .../inventoriespage/updateInventory.spec.ts | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 petclinic-frontend/tests/inventoriespage/updateInventory.spec.ts diff --git a/petclinic-frontend/tests/inventoriespage/updateInventory.spec.ts b/petclinic-frontend/tests/inventoriespage/updateInventory.spec.ts new file mode 100644 index 000000000..33f91eaa0 --- /dev/null +++ b/petclinic-frontend/tests/inventoriespage/updateInventory.spec.ts @@ -0,0 +1,24 @@ +import { test, expect } from '@playwright/test'; + +test('Update Inventory', async ({ page }) => { + + await page.goto('http://localhost:3000/users/login'); + await page.getByPlaceholder('Enter your email').click(); + await page.getByPlaceholder('Enter your email').fill('admin@admin.com'); + await page.getByPlaceholder('Enter your email').press('Tab'); + await page.getByPlaceholder('Enter your password').fill('pwd'); + await page.getByPlaceholder('Enter your password').press('Enter'); + await page.getByRole('button', { name: 'Login' }).click(); + await page.getByRole('link', { name: 'Inventories' }).click(); + await page.locator('div').filter({ hasText: /^Carlos3 Type: EquipmentMedical equipment for surgery$/ }).locator('[id="_cardMenu_cob55_1"]').click(); + await page.getByRole('button', { name: 'Edit' }).click(); await page.getByPlaceholder('Inventory Name').click(); + await page.getByPlaceholder('Inventory Name').fill(''); + await page.getByPlaceholder('Inventory Name').press('CapsLock'); + await page.getByPlaceholder('Inventory Name').fill('M'); + await page.getByPlaceholder('Inventory Name').press('CapsLock'); + await page.getByPlaceholder('Inventory Name').fill('Medical'); + await page.getByRole('button', { name: 'Update' }).click(); + await expect(page.getByText('Inventory updated successfully').first()).toBeVisible(); + await page.goto('http://localhost:3000/inventories'); + +}); \ No newline at end of file From f6ce8c5d9e5e3e240d7f02059be13fe92d974835 Mon Sep 17 00:00:00 2001 From: Zakaria_ <135060272+Zako563@users.noreply.github.com> Date: Mon, 11 Nov 2024 21:20:32 -0500 Subject: [PATCH 12/14] E2etest/vist zakaria (#1052) **JIRA:** link to jira ticket ## Context: What is the ticket about and why are we doing this change. ## Does this PR change the .vscode folder in petclinic-frontend?: If the PR changes the .vscode folder, explain why in detail because it should not. Be sure to include cgerard321 as a reviewer. **Reviewers need to check for any changes to the .vscode folder and add a comment about it to their review comments.** ## Changes Test for add What are the various changes and what other modules do those changes affect. This can be bullet point or sentence format. ## Before and After UI (Required for UI-impacting PRs) If this is a change to the UI, include before and after screenshots to show the differences. If this is a new UI feature, include screenshots to show reviewers what it looks like. ## Dev notes (Optional) Specific technical changes that should be noted ## Linked pull requests (Optional) Pull request links --------- Co-authored-by: Zakaria_ <135060272+tramway23@users.noreply.github.com> --- .../tests/AddEmergencyVisit(Zakaria).spec.ts | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 petclinic-frontend/tests/AddEmergencyVisit(Zakaria).spec.ts diff --git a/petclinic-frontend/tests/AddEmergencyVisit(Zakaria).spec.ts b/petclinic-frontend/tests/AddEmergencyVisit(Zakaria).spec.ts new file mode 100644 index 000000000..2a27db282 --- /dev/null +++ b/petclinic-frontend/tests/AddEmergencyVisit(Zakaria).spec.ts @@ -0,0 +1,32 @@ +import { test, expect } from '@playwright/test'; + +test('test', async ({ page }) => { + //test + await page.goto('http://localhost:3000/users/login'); + await page.getByPlaceholder('Enter your email').click(); + await page.getByPlaceholder('Enter your email').fill('betty@email.com'); + await page.getByPlaceholder('Enter your password').click(); + await page.getByPlaceholder('Enter your password').fill('pwd'); + await page.getByRole('button', { name: 'Login' }).click(); + await page.getByRole('link', { name: 'Emergency' }).click(); + await page.getByRole('button', { name: 'Create Emergency visit' }).click(); + await page.locator('input[name="petName"]').click(); + await page.locator('input[name="petName"]').fill('ham'); + await page.locator('textarea[name="description"]').click(); + await page.locator('textarea[name="description"]').fill('c'); + await page.getByText('c', { exact: true }).fill('cast'); + await page.locator('input[name="emergencyType"]').click(); + await page.locator('input[name="emergencyType"]').fill('death'); + await page.getByRole('combobox').selectOption('MEDIUM'); + await page.locator('input[name="petId"]').click(); + await page.locator('input[name="petId"]').click(); + await page + .locator('input[name="petId"]') + .fill('ecb109cd-57ea-4b85-b51e-99751fd1c349'); + await page.locator('input[name="practitionerId"]').click(); + await page.locator('input[name="practitionerId"]').click(); + await page + .locator('input[name="practitionerId"]') + .fill('69f85d2e-625b-11ee-8c99-0242ac120002'); + await page.getByRole('button', { name: 'Submit Emergency' }).click(); +}); From b9b1598dcfdc20843ac4780af00d3e38ce5c569c Mon Sep 17 00:00:00 2001 From: Sunveer <142905066+Sunveerg@users.noreply.github.com> Date: Mon, 11 Nov 2024 23:27:37 -0500 Subject: [PATCH 13/14] Test for search product by name (#1041) Test in front-end for search by inventory name. --- .../searchInventoryByName.spec.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 petclinic-frontend/tests/inventoriespage/searchInventoryByName.spec.ts diff --git a/petclinic-frontend/tests/inventoriespage/searchInventoryByName.spec.ts b/petclinic-frontend/tests/inventoriespage/searchInventoryByName.spec.ts new file mode 100644 index 000000000..652f2de65 --- /dev/null +++ b/petclinic-frontend/tests/inventoriespage/searchInventoryByName.spec.ts @@ -0,0 +1,18 @@ +import { test, expect } from '@playwright/test'; + +test('test', async ({ page }) => { + await page.goto('http://localhost:3000/users/login'); + await page.getByPlaceholder('Enter your email').click(); + await page.getByPlaceholder('Enter your email').fill('admin@admin.com'); + await page.getByPlaceholder('Enter your password').click(); + await page.getByPlaceholder('Enter your password').fill('pwd'); + await page.getByRole('button', { name: 'Login' }).click(); + await page.getByRole('link', { name: 'Inventories' }).click(); + await page.getByRole('textbox').first().click(); + await page.getByRole('textbox').first().press('CapsLock'); + await page.getByRole('textbox').first().fill('M'); + await page.getByRole('textbox').first().press('CapsLock'); + await page.getByRole('cell', { name: 'M', exact: true }).getByRole('textbox').fill('Medical'); + await page.getByRole('button', { name: 'Search' }).click(); + await expect(page.getByText('Medical equipment', { exact: true })).toBeVisible(); +}); \ No newline at end of file From 81fbcf0d434e28038182be38aaa4fc1c1642dd78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zachary=20Leli=C3=A8vre?= <93009892+ZacharyLelievre@users.noreply.github.com> Date: Tue, 12 Nov 2024 11:24:57 -0500 Subject: [PATCH 14/14] e2etest/PROD-Zachary (#1056) **JIRA:** [Link to JIRA ticket] ## Context: This ticket focuses on adding a test to ensure that the review filter works correctly when users set a minimum rating equal to or higher than the maximum rating. The test verifies that an error message is displayed if this condition is met. ## Does this PR change the .vscode folder in petclinic-frontend?: No changes were made to the `.vscode` folder. Reviewers, please confirm that no unintentional changes were made to this folder. **Reviewers need to check for any changes to the .vscode folder and add a comment about it to their review comments.** ## Changes - Added validation to the review filter for minimum and maximum star ratings. --- .../tests/productspage/filterbyreview.spec.ts | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 petclinic-frontend/tests/productspage/filterbyreview.spec.ts diff --git a/petclinic-frontend/tests/productspage/filterbyreview.spec.ts b/petclinic-frontend/tests/productspage/filterbyreview.spec.ts new file mode 100644 index 000000000..938486607 --- /dev/null +++ b/petclinic-frontend/tests/productspage/filterbyreview.spec.ts @@ -0,0 +1,26 @@ +import { test, expect } from '@playwright/test'; + + test('test', async ({ page }) => { + await page.goto('http://localhost:3000/users/login'); + await page.getByPlaceholder('Enter your email').click(); + await page.getByPlaceholder('Enter your email').fill('betty@email.com'); + await page.getByPlaceholder('Enter your password').click(); + await page.getByPlaceholder('Enter your password').fill('pwd'); + await page.getByRole('button', { name: 'Login' }).click(); + await page.getByRole('link', { name: 'Visits' }).click(); + await page.getByRole('button', { name: 'Leave a Review' }).click(); + await page.getByRole('spinbutton').click(); + await page.getByRole('spinbutton').fill('5'); + await page.locator('input[name="reviewerName"]').click(); + await page.locator('input[name="reviewerName"]').press('CapsLock'); + await page.locator('input[name="reviewerName"]').fill('B'); + await page.locator('input[name="reviewerName"]').press('CapsLock'); + await page.locator('input[name="reviewerName"]').fill('Betty'); + await page.locator('textarea[name="review"]').click(); + await page.locator('textarea[name="review"]').press('CapsLock'); + await page.locator('textarea[name="review"]').fill('V'); + await page.locator('textarea[name="review"]').press('CapsLock'); + await page.getByText('V', { exact: true }).fill('Very good!'); + await page.getByRole('button', { name: 'Submit Review' }).click(); + + }); \ No newline at end of file