Skip to content

Commit

Permalink
Playwright e2e setup (#4168)
Browse files Browse the repository at this point in the history
* Add Plawright POC

* removed unused variable

* removed example file

* Remove TS issues

* CI url fix

* Add artefacts config

* basic setup finished

* all create product type tests refactored and single from create product

* trigger tsc type checks on test folder  before commits

* cr fixes

* removed PW workflow for now, add notification to cypress tests about delete when migration is done, cr fix interface naming

* wraped combobox on taxes and category components with box with data test id

* git ignore fix

---------

Co-authored-by: wojteknowacki <[email protected]>
  • Loading branch information
michalina-graczyk and wojteknowacki authored Sep 27, 2023
1 parent 327008a commit f97d75c
Show file tree
Hide file tree
Showing 27 changed files with 846 additions and 56 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,6 @@ django-queries-results.html
!.env.template
!.dependency-cruiser.js
!.featureFlags
/test-results/
/playwright-report/
/playwright/.cache/
1 change: 1 addition & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
. "$(dirname -- "$0")/_/husky.sh"

npx lint-staged
npm run check-types-playwright
6 changes: 3 additions & 3 deletions cypress/e2e/configuration/productTypes/createProductType.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ describe("As an admin I want to create product types", () => {
});

it(
"should be able to create product type without shipping required. TC: SALEOR_1501",
"should be able to create product type without shipping required. TC: SALEOR_1501 - migration in progress - to delete when done",
{
tags: ["@productType", "@allEnv", "@stable", "@oldRelease", "@critical"],
},
Expand All @@ -37,7 +37,7 @@ describe("As an admin I want to create product types", () => {
);

it(
"should be able to create product type with shipping required. TC: SALEOR_1502",
"should be able to create product type with shipping required. TC: SALEOR_1502 - migration in progress - to delete when done",
{ tags: ["@productType", "@allEnv", "@stable", "@critical"] },
() => {
const name = `${startsWith}${faker.datatype.number()}`;
Expand All @@ -57,7 +57,7 @@ describe("As an admin I want to create product types", () => {
);

it(
"should be able to create product type with gift card kind. TC: SALEOR_1510",
"should be able to create product type with gift card kind. TC: SALEOR_1510 - migration in progress - to delete when done",
{ tags: ["@productType", "@allEnv", "@stable", "@critical"] },
() => {
const name = `${startsWith}${faker.datatype.number()}`;
Expand Down
6 changes: 2 additions & 4 deletions cypress/e2e/products/createProduct.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@

import faker from "faker";

import {
PRODUCT_DETAILS,
} from "../../elements/catalog/products/product-details";
import { PRODUCT_DETAILS } from "../../elements/catalog/products/product-details";
import { PRODUCTS_LIST } from "../../elements/catalog/products/products-list";
import { BUTTON_SELECTORS } from "../../elements/shared/button-selectors";
import { urlList } from "../../fixtures/urlList";
Expand Down Expand Up @@ -65,7 +63,7 @@ describe("As an admin I should be able to create product", () => {
});

it(
"should be able to create product with variants as an admin. SALEOR_2701",
"should be able to create product with variants as an admin. SALEOR_2701 - migration in progress - to delete when done",
{ tags: ["@products", "@allEnv", "@critical", "@stable", "@oldRelease"] },
() => {
const randomName = `${startsWith}${faker.datatype.number()}`;
Expand Down
72 changes: 72 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@
"@graphql-codegen/typescript-apollo-client-helpers": "^2.1.10",
"@graphql-codegen/typescript-operations": "^2.2.4",
"@graphql-codegen/typescript-react-apollo": "^3.2.5",
"@playwright/test": "^1.37.1",
"@saleor/app-sdk": "0.43.0",
"@sentry/cli": "^2.20.6",
"@swc/jest": "^0.2.26",
Expand Down Expand Up @@ -315,6 +316,7 @@
"prebuild": "npm run build-types",
"check-strict-null-errors": "tsc --noEmit --strictNullChecks | node scripts/count-strict-null-check-errors.js",
"check-types": "tsc --noEmit && tsc-strict",
"check-types-playwright": "tsc --noEmit --project playwright/tsconfig.json",
"extract-json-messages": "formatjs extract 'src/**/*.{ts,tsx}' --out-file locale/defaultMessages.json --format scripts/formatter.js",
"extract-messages": "npm run extract-json-messages",
"fetch-schema": "graphql-codegen --config ./fetch-schema.yml",
Expand Down Expand Up @@ -352,7 +354,9 @@
"qa:move-screenshots": "find cypress/reports/mochareports -type d -name \"*.js\" -exec mv {} cypress/reports/mochareports \\;",
"qa:move-videos": "find cypress/videos -type f -name \"*.js.mp4\" -exec mv {} cypress/reports/mochareports/videos \\;",
"qa:artifact-move-screenshots": "find cypress/reports/*/mochareports -type d -name \"*.js\" -exec mv {} cypress/reports/mochareports \\;",
"qa:artifact-move-videos": "find cypress/reports/*/mochareports/videos -type f -name \"*.js.mp4\" -exec mv {} cypress/reports/mochareports/videos \\;"
"qa:artifact-move-videos": "find cypress/reports/*/mochareports/videos -type f -name \"*.js.mp4\" -exec mv {} cypress/reports/mochareports/videos \\;",
"qa:basic-regression": "npx playwright test --grep @basic-regression",
"qa:full-regression": "npx playwright test"
},
"description": "![Saleor Dashboard](https://user-images.githubusercontent.com/44495184/185379472-2a204c0b-9b7a-4a3e-93c0-2cb85205ed5e.png)"
}
39 changes: 39 additions & 0 deletions playwright.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import dotenv from "dotenv";

import { defineConfig, devices } from "@playwright/test";

dotenv.config();

export default defineConfig({
testDir: "playwright/tests",
fullyParallel: true,
forbidOnly: !!process.env.CI,
retries: process.env.CI ? 2 : 0,
workers: process.env.CI ? 1 : undefined,
reporter: "html",
// webServer: {
// command: "npm run dev",
// url: "http://localhost:9000/",
// reuseExistingServer: !process.env.CI,
// },
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
baseURL: process.env.CYPRESS_baseUrl,
trace: "on-first-retry",
screenshot: "only-on-failure",
testIdAttribute: "data-test-id",
video: process.env.CI ? "retain-on-failure" : "off",
},

/* Configure projects for major browsers */
projects: [
{ name: "setup", testMatch: /.*\.setup\.ts/ },

{
// if new project added make sure to add dependency as below
dependencies: ["setup"],
name: "chromium",
use: { ...devices["Desktop Chrome"] },
},
],
});
40 changes: 40 additions & 0 deletions playwright/api/basics.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { APIResponse, request } from "@playwright/test";

const URL = process.env.API_URI || "";
interface Data {
query: string;
}

interface User {
email: string;
password: string;
}
export class GraphQLService {
async example(
user: User,
authorization: string = "auth",
): Promise<APIResponse> {
const headers = { Authorization: `Bearer ${authorization}` };

const api = await request.newContext();
const query = `mutation TokenAuth{
tokenCreate(email: "${user.email}", password: "${user.password}") {
token
refreshToken
errors: errors {
code
field
message
}
user {
id
}
}
}`;
const data: Data = {
query: query,
};
const loginResponse = await api.post(URL, { data, headers });
return loginResponse;
}
}
4 changes: 4 additions & 0 deletions playwright/data/common-locators.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export const LOCATORS = {
successBanner: '[data-test-type="success"]',
dataGridTable: "[data-testid='data-grid-canvas']",
};
36 changes: 36 additions & 0 deletions playwright/data/url.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
export const URL_LIST = {
addProduct: "products/add",
addPageType: "pages/add?page-type-id=",
apps: "custom-apps/",
attributes: "attributes/",
categories: "categories/",
channels: "channels/",
collections: "collections/",
configuration: "configuration/",
customers: "customers/",
dashboard: "dashboard/",
draftOrders: "orders/drafts/",
giftCards: "gift-cards/",
homePage: "/",
newPassword: "new-password/",
navigation: "navigation/",
orders: "orders/",
pages: "pages/",
pageTypes: "page-types/",
permissionsGroups: "permission-groups/",
plugins: "plugins/",
products: "products/",
productTypes: "product-types/",
productTypesAdd: "product-types/add",
sales: "discounts/sales/",
shippingMethods: "shipping/",
siteSettings: "site-settings/",
staffMembers: "staff/",
stripeApiPaymentMethods: "https://api.stripe.com/v1/payment_methods",
translations: "translations/",
variants: "variant/",
vouchers: "discounts/vouchers/",
variant: "variant/",
warehouses: "warehouses/",
webhooksAndEvents: "custom-apps/",
};
28 changes: 28 additions & 0 deletions playwright/pages/dialogs/product-create-dialog.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import type {
Locator,
Page,
} from "@playwright/test";

export class ProductCreateDialog {
readonly page: Page;
readonly dialogProductTypeInput: Locator;
readonly promptedOptions: Locator;
readonly confirmButton: Locator;
constructor(page: Page) {
this.page = page;
this.dialogProductTypeInput = page.locator(
"[data-test-id='dialog-product-type'] input",
);
this.promptedOptions = page.getByTestId(
"single-autocomplete-select-option",
);
this.confirmButton = page.getByTestId("submit");
}
async selectProductTypeWithVariants() {
await this.dialogProductTypeInput.fill("beer");
await this.promptedOptions.filter({ hasText: "Beer" }).click();
}
async clickConfirmButton() {
await this.confirmButton.click();
}
}
16 changes: 16 additions & 0 deletions playwright/pages/home-page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import type {
Locator,
Page,
} from "@playwright/test";

export class HomePage {
readonly page: Page;
readonly welcomeMessage: Locator;
constructor(page: Page) {
this.page = page;
this.welcomeMessage = page.getByTestId("home-header");
}
async goto() {
await this.page.goto("/");
}
}
34 changes: 34 additions & 0 deletions playwright/pages/login-page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import type {
Locator,
Page,
} from "@playwright/test";

export class LoginPage {
readonly page: Page;
readonly emailInput: Locator;
readonly passwordInput: Locator;
readonly signInButton: Locator;
constructor(page: Page) {
this.page = page;
this.emailInput = page.getByTestId("email");
this.passwordInput = page.getByTestId("password");
this.signInButton = page.getByTestId("submit");
}
async typeEmail(email: string) {
await this.emailInput.type(email);
}
async typePassword(password: string) {
await this.passwordInput.type(password);
}
async clickSignInButton() {
await this.signInButton.click();
}
async goto() {
const CYPRESS_baseUrl = process.env.CYPRESS_baseUrl;
const loginPageUrl =
CYPRESS_baseUrl === "http://localhost:9000/"
? "http://localhost:9000/"
: "/dashboard";
await this.page.goto(loginPageUrl);
}
}
Loading

0 comments on commit f97d75c

Please sign in to comment.