Install Playwright and Prettier.
Add tests for login and creating shapes
4
.gitignore
vendored
|
@ -102,3 +102,7 @@ dist
|
|||
|
||||
# TernJS port file
|
||||
.tern-port
|
||||
/test-results/
|
||||
/playwright-report/
|
||||
/playwright/.cache/
|
||||
/.idea/
|
||||
|
|
20
fixtures.js
Normal file
|
@ -0,0 +1,20 @@
|
|||
const base = require("@playwright/test");
|
||||
const { LoginPage } = require("./pages/login-page.js");
|
||||
const { DashboardPage } = require("./pages/dashboard-page.js");
|
||||
|
||||
const mainTest = base.test.extend({
|
||||
page: async ({ page }, use) => {
|
||||
const loginPage = new LoginPage(page);
|
||||
await loginPage.goto();
|
||||
await loginPage.enterEmail(process.env.LOGIN_EMAIL);
|
||||
await loginPage.enterPwd(process.env.LOGIN_PWD);
|
||||
await loginPage.clickLoginButton();
|
||||
const dashboardPage = new DashboardPage(page);
|
||||
await dashboardPage.isHeaderDisplayed("Projects");
|
||||
await dashboardPage.deleteFileIfExists();
|
||||
await dashboardPage.createFile();
|
||||
await use(page);
|
||||
},
|
||||
});
|
||||
|
||||
exports.mainTest = mainTest;
|
BIN
images/images.png
Normal file
After Width: | Height: | Size: 6.9 KiB |
112
package-lock.json
generated
Normal file
|
@ -0,0 +1,112 @@
|
|||
{
|
||||
"name": "penpotqa",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "penpotqa",
|
||||
"version": "1.0.0",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"prettier": "^2.7.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@playwright/test": "^1.27.1",
|
||||
"dotenv": "^16.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@playwright/test": {
|
||||
"version": "1.27.1",
|
||||
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.27.1.tgz",
|
||||
"integrity": "sha512-mrL2q0an/7tVqniQQF6RBL2saskjljXzqNcCOVMUjRIgE6Y38nCNaP+Dc2FBW06bcpD3tqIws/HT9qiMHbNU0A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "*",
|
||||
"playwright-core": "1.27.1"
|
||||
},
|
||||
"bin": {
|
||||
"playwright": "cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "18.11.9",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.9.tgz",
|
||||
"integrity": "sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/dotenv": {
|
||||
"version": "16.0.3",
|
||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz",
|
||||
"integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/playwright-core": {
|
||||
"version": "1.27.1",
|
||||
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.27.1.tgz",
|
||||
"integrity": "sha512-9EmeXDncC2Pmp/z+teoVYlvmPWUC6ejSSYZUln7YaP89Z6lpAaiaAnqroUt/BoLo8tn7WYShcfaCh+xofZa44Q==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"playwright": "cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/prettier": {
|
||||
"version": "2.7.1",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz",
|
||||
"integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==",
|
||||
"bin": {
|
||||
"prettier": "bin-prettier.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.13.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/prettier/prettier?sponsor=1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@playwright/test": {
|
||||
"version": "1.27.1",
|
||||
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.27.1.tgz",
|
||||
"integrity": "sha512-mrL2q0an/7tVqniQQF6RBL2saskjljXzqNcCOVMUjRIgE6Y38nCNaP+Dc2FBW06bcpD3tqIws/HT9qiMHbNU0A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/node": "*",
|
||||
"playwright-core": "1.27.1"
|
||||
}
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "18.11.9",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.9.tgz",
|
||||
"integrity": "sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg==",
|
||||
"dev": true
|
||||
},
|
||||
"dotenv": {
|
||||
"version": "16.0.3",
|
||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz",
|
||||
"integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==",
|
||||
"dev": true
|
||||
},
|
||||
"playwright-core": {
|
||||
"version": "1.27.1",
|
||||
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.27.1.tgz",
|
||||
"integrity": "sha512-9EmeXDncC2Pmp/z+teoVYlvmPWUC6ejSSYZUln7YaP89Z6lpAaiaAnqroUt/BoLo8tn7WYShcfaCh+xofZa44Q==",
|
||||
"dev": true
|
||||
},
|
||||
"prettier": {
|
||||
"version": "2.7.1",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz",
|
||||
"integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g=="
|
||||
}
|
||||
}
|
||||
}
|
28
package.json
Normal file
|
@ -0,0 +1,28 @@
|
|||
{
|
||||
"name": "penpotqa",
|
||||
"version": "1.0.0",
|
||||
"description": "QA Test for Penpot",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "npx playwright test",
|
||||
"prettier": "npx prettier --write ."
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/penpot/penpotqa.git"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"bugs": {
|
||||
"url": "https://github.com/penpot/penpotqa/issues"
|
||||
},
|
||||
"homepage": "https://github.com/penpot/penpotqa#readme",
|
||||
"devDependencies": {
|
||||
"@playwright/test": "^1.27.1",
|
||||
"dotenv": "^16.0.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"prettier": "^2.7.1"
|
||||
}
|
||||
}
|
39
pages/dashboard-page.js
Normal file
|
@ -0,0 +1,39 @@
|
|||
const { expect } = require("@playwright/test");
|
||||
|
||||
exports.DashboardPage = class DashboardPage {
|
||||
/**
|
||||
* @param {import('@playwright/test').Page} page
|
||||
*/
|
||||
constructor(page) {
|
||||
this.header = page.locator("h1");
|
||||
this.numberOfFilesText = page.locator(
|
||||
'div[class="project-name-wrapper"] span[class="info"]'
|
||||
);
|
||||
this.fileTile = page.locator('div[class="item-info"]');
|
||||
this.deleteFileMenuItem = page.locator('a[data-test="file-delete"]');
|
||||
this.deletesFileButton = page.locator('input[value="Delete files"]');
|
||||
this.createFileButton = page.locator('button[class="create-new"]');
|
||||
}
|
||||
|
||||
async isHeaderDisplayed(title) {
|
||||
await expect(this.header).toBeVisible();
|
||||
await expect(this.header).toHaveText(title);
|
||||
}
|
||||
|
||||
async createFile() {
|
||||
await this.createFileButton.click();
|
||||
}
|
||||
|
||||
async deleteFile() {
|
||||
await this.fileTile.click({ button: "right" });
|
||||
await this.deleteFileMenuItem.click();
|
||||
await this.deletesFileButton.click();
|
||||
}
|
||||
|
||||
async deleteFileIfExists() {
|
||||
const text = (await this.numberOfFilesText.innerText()).valueOf();
|
||||
if (!text.includes("0 files")) {
|
||||
await this.deleteFile();
|
||||
}
|
||||
}
|
||||
};
|
68
pages/login-page.js
Normal file
|
@ -0,0 +1,68 @@
|
|||
const { expect } = require("@playwright/test");
|
||||
exports.LoginPage = class LoginPage {
|
||||
/**
|
||||
* @param {import('@playwright/test').Page} page
|
||||
*/
|
||||
constructor(page) {
|
||||
this.page = page;
|
||||
this.emailInput = page.locator("#email");
|
||||
this.pwdInput = page.locator("#password");
|
||||
this.loginButton = page.locator('input[name="submit"]');
|
||||
this.emailInputError = page.locator(
|
||||
'div[class=" invalid with-icon custom-input"] #email'
|
||||
);
|
||||
this.pwdInputError = page.locator(
|
||||
'div[class=" invalid empty with-icon custom-input"] #password'
|
||||
);
|
||||
this.section = page.locator('section[class="auth-content"]');
|
||||
this.loginErrorBanner = page.locator('div[data-test="login-banner"]');
|
||||
}
|
||||
|
||||
async goto() {
|
||||
await this.page.goto("/#/auth/login");
|
||||
}
|
||||
|
||||
async enterEmail(loginEmail) {
|
||||
await this.emailInput.fill(loginEmail);
|
||||
}
|
||||
|
||||
async enterPwd(loginPwd) {
|
||||
await this.pwdInput.fill(loginPwd);
|
||||
}
|
||||
|
||||
async clickLoginButton() {
|
||||
await this.loginButton.click();
|
||||
}
|
||||
|
||||
async clickPwdInput() {
|
||||
await this.pwdInput.click();
|
||||
}
|
||||
|
||||
async isEmailInputErrorDisplayed() {
|
||||
await expect(this.emailInputError).toBeVisible();
|
||||
}
|
||||
|
||||
async isPwdInputErrorDisplayed() {
|
||||
await expect(this.pwdInputError).toBeVisible();
|
||||
}
|
||||
|
||||
async isLoginButtonDisplayed() {
|
||||
await expect(this.loginButton).toBeVisible();
|
||||
}
|
||||
|
||||
async isLoginButtonDisabled() {
|
||||
await expect(this.loginButton).toBeDisabled();
|
||||
}
|
||||
|
||||
async clickSection() {
|
||||
await this.section.click();
|
||||
}
|
||||
|
||||
async isLoginErrorBannerDisplayed() {
|
||||
await expect(this.loginErrorBanner).toBeVisible();
|
||||
}
|
||||
|
||||
async isLoginErrorMessageDisplayed(message) {
|
||||
await expect(this.loginErrorBanner).toHaveText(message);
|
||||
}
|
||||
};
|
89
pages/main-page.js
Normal file
|
@ -0,0 +1,89 @@
|
|||
const { expect } = require("@playwright/test");
|
||||
const viewportLocator = 'div[class="viewport"]';
|
||||
exports.MainPage = class MainPage {
|
||||
/**
|
||||
* @param {import('@playwright/test').Page} page
|
||||
*/
|
||||
|
||||
constructor(page) {
|
||||
this.page = page;
|
||||
this.createBoardButton = page.locator('button[data-test="artboard-btn"]');
|
||||
this.createRectangleButton = page.locator('button[data-test="rect-btn"]');
|
||||
this.createEllipseButton = page.locator('button[data-test="ellipse-btn"]');
|
||||
this.createTextButton = page.locator('button[alt="Text (T)"]');
|
||||
this.uploadImageSelector = page.locator("#image-upload");
|
||||
this.createCurveButton = page.locator('button[data-test="curve-btn"]');
|
||||
this.createPathButton = page.locator('button[data-test="path-btn"]');
|
||||
this.createdObject = page.locator('div *[id^="fills"]');
|
||||
this.textbox = page.locator(
|
||||
'div[role="textbox"] div[contenteditable="true"]'
|
||||
);
|
||||
this.viewport = page.locator(viewportLocator);
|
||||
this.savedChangesIcon = page.locator('div[class="saved"]');
|
||||
}
|
||||
|
||||
async clickCreateBoardButton() {
|
||||
await this.createBoardButton.click();
|
||||
}
|
||||
|
||||
async clickCreateRectangleButton() {
|
||||
await this.createRectangleButton.click();
|
||||
}
|
||||
|
||||
async clickCreateEllipseButton() {
|
||||
await this.createEllipseButton.click();
|
||||
}
|
||||
|
||||
async clickCreateTextButton() {
|
||||
await this.createTextButton.click();
|
||||
}
|
||||
|
||||
async typeText(text) {
|
||||
await this.textbox.fill(text);
|
||||
}
|
||||
|
||||
async uploadImage(imageUrl) {
|
||||
await this.uploadImageSelector.setInputFiles(imageUrl);
|
||||
}
|
||||
|
||||
async clickCreateCurveButton() {
|
||||
await this.createCurveButton.click();
|
||||
}
|
||||
|
||||
async clickCreatePathButton() {
|
||||
await this.createPathButton.click();
|
||||
}
|
||||
|
||||
async clickViewport() {
|
||||
await this.viewport.click();
|
||||
await this.viewport.click();
|
||||
}
|
||||
|
||||
async clickViewportByCoordinates(x, y) {
|
||||
await this.page.mouse.click(x, y);
|
||||
}
|
||||
|
||||
async waitForChangeIsSaved() {
|
||||
await expect(this.savedChangesIcon).toBeVisible();
|
||||
}
|
||||
|
||||
async isCreatedObjectVisible() {
|
||||
await expect(this.createdObject.nth(0)).toBeVisible();
|
||||
}
|
||||
|
||||
async checkHtmlOfCreatedObject(expectedHTML) {
|
||||
expect(await this.createdObject.nth(0).innerHTML()).toEqual(expectedHTML);
|
||||
}
|
||||
|
||||
async checkPartialHtmlOfCreatedObject(expectedHTML) {
|
||||
expect(await this.createdObject.nth(0).innerHTML()).toContain(expectedHTML);
|
||||
}
|
||||
|
||||
async drawCurve(x1, y1, x2, y2) {
|
||||
await this.page.mouse.move(x1, y1);
|
||||
await this.page.mouse.down();
|
||||
await this.page.mouse.move(x1, y1);
|
||||
await this.page.mouse.move(x2, y2);
|
||||
await this.page.mouse.up();
|
||||
}
|
||||
};
|
113
playwright.config.js
Normal file
|
@ -0,0 +1,113 @@
|
|||
// @ts-check
|
||||
const { devices } = require("@playwright/test");
|
||||
|
||||
/**
|
||||
* Read environment variables from file.
|
||||
* https://github.com/motdotla/dotenv
|
||||
*/
|
||||
require("dotenv").config();
|
||||
|
||||
/**
|
||||
* @see https://playwright.dev/docs/test-configuration
|
||||
* @type {import('@playwright/test').PlaywrightTestConfig}
|
||||
*/
|
||||
const config = {
|
||||
testDir: "./tests",
|
||||
/* Maximum time one test can run for. */
|
||||
timeout: 30 * 1000,
|
||||
expect: {
|
||||
/**
|
||||
* Maximum time expect() should wait for the condition to be met.
|
||||
* For example in `await expect(locator).toHaveText();`
|
||||
*/
|
||||
timeout: 5000,
|
||||
},
|
||||
/* Run tests in files in parallel */
|
||||
fullyParallel: true,
|
||||
/* Fail the build on CI if you accidentally left test.only in the source code. */
|
||||
forbidOnly: !!process.env.CI,
|
||||
/* Retry on CI only */
|
||||
retries: process.env.CI ? 2 : 0,
|
||||
/* Opt out of parallel tests on CI. */
|
||||
workers: 1,
|
||||
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
|
||||
reporter: "html",
|
||||
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
|
||||
use: {
|
||||
/* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */
|
||||
actionTimeout: 0,
|
||||
/* Base URL to use in actions like `await page.goto('/')`. */
|
||||
baseURL: process.env.BASE_URL,
|
||||
browserName: "chromium",
|
||||
headless: false,
|
||||
viewport: null,
|
||||
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
|
||||
trace: "on-first-retry",
|
||||
launchOptions: {
|
||||
args: ["--start-maximized"],
|
||||
},
|
||||
},
|
||||
|
||||
/* Configure projects for major browsers */
|
||||
projects: [
|
||||
{
|
||||
name: "chromium",
|
||||
// use: {
|
||||
// ...devices['Desktop Chrome'],
|
||||
// },
|
||||
},
|
||||
|
||||
// {
|
||||
// name: 'firefox',
|
||||
// use: {
|
||||
// ...devices['Desktop Firefox'],
|
||||
// },
|
||||
// },
|
||||
//
|
||||
// {
|
||||
// name: 'webkit',
|
||||
// use: {
|
||||
// ...devices['Desktop Safari'],
|
||||
// },
|
||||
// },
|
||||
|
||||
/* Test against mobile viewports. */
|
||||
// {
|
||||
// name: 'Mobile Chrome',
|
||||
// use: {
|
||||
// ...devices['Pixel 5'],
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// name: 'Mobile Safari',
|
||||
// use: {
|
||||
// ...devices['iPhone 12'],
|
||||
// },
|
||||
// },
|
||||
|
||||
/* Test against branded browsers. */
|
||||
// {
|
||||
// name: 'Microsoft Edge',
|
||||
// use: {
|
||||
// channel: 'msedge',
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// name: 'Google Chrome',
|
||||
// use: {
|
||||
// channel: 'chrome',
|
||||
// },
|
||||
// },
|
||||
],
|
||||
|
||||
/* Folder for test artifacts such as screenshots, videos, traces, etc. */
|
||||
// outputDir: 'test-results/',
|
||||
|
||||
/* Run your local dev server before starting the tests */
|
||||
// webServer: {
|
||||
// command: 'npm run start',
|
||||
// port: 3000,
|
||||
// },
|
||||
};
|
||||
|
||||
module.exports = config;
|
93
tests/create-shapes.spec.js
Normal file
|
@ -0,0 +1,93 @@
|
|||
// @ts-check
|
||||
const { mainTest } = require("../fixtures");
|
||||
const { MainPage } = require("../pages/main-page");
|
||||
const { expect } = require("@playwright/test");
|
||||
|
||||
mainTest("Create a board", async ({ page }) => {
|
||||
const mainPage = new MainPage(page);
|
||||
await mainPage.clickCreateBoardButton();
|
||||
await mainPage.clickViewport();
|
||||
await mainPage.waitForChangeIsSaved();
|
||||
await mainPage.isCreatedObjectVisible();
|
||||
await mainPage.checkHtmlOfCreatedObject(
|
||||
'<rect rx="0" ry="0" x="630" y="410" transform="" width="100" height="100" class="frame-background" style="fill: rgb(255, 255, 255); fill-opacity: 1;"></rect>'
|
||||
);
|
||||
await expect(page).toHaveScreenshot("board.png");
|
||||
});
|
||||
|
||||
mainTest("Create a rectangle", async ({ page }) => {
|
||||
const mainPage = new MainPage(page);
|
||||
await mainPage.clickCreateRectangleButton();
|
||||
await mainPage.clickViewport();
|
||||
await mainPage.waitForChangeIsSaved();
|
||||
await mainPage.isCreatedObjectVisible();
|
||||
await mainPage.checkHtmlOfCreatedObject(
|
||||
'<rect rx="0" ry="0" x="630" y="410" transform="" width="100" height="100" style="fill: rgb(177, 178, 181); fill-opacity: 1;"></rect>'
|
||||
);
|
||||
await expect(page).toHaveScreenshot("rectangle.png");
|
||||
});
|
||||
|
||||
mainTest("Create an ellipse", async ({ page }) => {
|
||||
const mainPage = new MainPage(page);
|
||||
await mainPage.clickCreateEllipseButton();
|
||||
await mainPage.clickViewport();
|
||||
await mainPage.waitForChangeIsSaved();
|
||||
await mainPage.isCreatedObjectVisible();
|
||||
await mainPage.checkHtmlOfCreatedObject(
|
||||
'<ellipse rx="50" ry="50" cx="680" cy="460" transform="" style="fill: rgb(177, 178, 181); fill-opacity: 1;"></ellipse>'
|
||||
);
|
||||
await expect(page).toHaveScreenshot("ellipse.png");
|
||||
});
|
||||
|
||||
mainTest("Create an text", async ({ page }) => {
|
||||
const mainPage = new MainPage(page);
|
||||
await mainPage.clickCreateTextButton();
|
||||
await mainPage.clickViewport();
|
||||
await mainPage.typeText("Hello World!");
|
||||
await mainPage.waitForChangeIsSaved();
|
||||
await mainPage.isCreatedObjectVisible();
|
||||
await mainPage.checkHtmlOfCreatedObject(
|
||||
'<text y="459" textLength="72.4375" lengthAdjust="spacingAndGlyphs" x="680" dominant-baseline="text-before-edge" style="text-transform: none; font-family: sourcesanspro; letter-spacing: normal; font-style: normal; font-weight: 400; white-space: pre; font-size: 14px; text-decoration: none solid rgb(0, 0, 0); direction: ltr; fill: rgb(0, 0, 0); fill-opacity: 1;">Hello World!</text>'
|
||||
);
|
||||
await expect(page).toHaveScreenshot("text.png");
|
||||
});
|
||||
|
||||
mainTest("Import an image", async ({ page }) => {
|
||||
const mainPage = new MainPage(page);
|
||||
await mainPage.uploadImage("images/images.png");
|
||||
await mainPage.clickViewport();
|
||||
await mainPage.waitForChangeIsSaved();
|
||||
await mainPage.isCreatedObjectVisible();
|
||||
await mainPage.checkPartialHtmlOfCreatedObject(
|
||||
'<rect rx="0" ry="0" x="528.5" y="395.5" transform="" width="303" height="130" fill='
|
||||
);
|
||||
await expect(page).toHaveScreenshot("image.png");
|
||||
});
|
||||
|
||||
mainTest("Create a curve", async ({ page }) => {
|
||||
const mainPage = new MainPage(page);
|
||||
await mainPage.clickCreateCurveButton();
|
||||
await mainPage.drawCurve(900, 300, 600, 200);
|
||||
await mainPage.waitForChangeIsSaved();
|
||||
await mainPage.isCreatedObjectVisible();
|
||||
await mainPage.checkHtmlOfCreatedObject(
|
||||
'<path rx="0" ry="0" d="M596,252L296,152"></path>'
|
||||
);
|
||||
await expect(page).toHaveScreenshot("curve.png");
|
||||
});
|
||||
|
||||
mainTest("Create a path", async ({ page }) => {
|
||||
const mainPage = new MainPage(page);
|
||||
await mainPage.clickCreatePathButton();
|
||||
await mainPage.clickViewportByCoordinates(500, 200);
|
||||
await mainPage.clickViewportByCoordinates(1200, 700);
|
||||
await mainPage.clickViewportByCoordinates(1000, 400);
|
||||
await mainPage.clickViewportByCoordinates(500, 200);
|
||||
await mainPage.clickViewport();
|
||||
await mainPage.waitForChangeIsSaved();
|
||||
await mainPage.isCreatedObjectVisible();
|
||||
await mainPage.checkHtmlOfCreatedObject(
|
||||
'<path rx="0" ry="0" d="M196,152L896,652L696,352L196,152ZM680,460"></path>'
|
||||
);
|
||||
await expect(page).toHaveScreenshot("path.png");
|
||||
});
|
BIN
tests/create-shapes.spec.js-snapshots/board-chromium-win32.png
Normal file
After Width: | Height: | Size: 74 KiB |
BIN
tests/create-shapes.spec.js-snapshots/curve-chromium-win32.png
Normal file
After Width: | Height: | Size: 47 KiB |
BIN
tests/create-shapes.spec.js-snapshots/ellipse-chromium-win32.png
Normal file
After Width: | Height: | Size: 64 KiB |
BIN
tests/create-shapes.spec.js-snapshots/image-chromium-win32.png
Normal file
After Width: | Height: | Size: 90 KiB |
BIN
tests/create-shapes.spec.js-snapshots/path-chromium-win32.png
Normal file
After Width: | Height: | Size: 91 KiB |
After Width: | Height: | Size: 62 KiB |
BIN
tests/create-shapes.spec.js-snapshots/text-chromium-win32.png
Normal file
After Width: | Height: | Size: 69 KiB |
46
tests/login.spec.js
Normal file
|
@ -0,0 +1,46 @@
|
|||
// @ts-check
|
||||
const { test } = require("@playwright/test");
|
||||
const { LoginPage } = require("../pages/login-page");
|
||||
const { DashboardPage } = require("../pages/dashboard-page");
|
||||
|
||||
test("Login with an email address", async ({ page }) => {
|
||||
const loginPage = new LoginPage(page);
|
||||
await loginPage.goto();
|
||||
await loginPage.enterEmail(process.env.LOGIN_EMAIL);
|
||||
await loginPage.enterPwd(process.env.LOGIN_PWD);
|
||||
await loginPage.clickLoginButton();
|
||||
const dashboardPage = new DashboardPage(page);
|
||||
await dashboardPage.isHeaderDisplayed("Projects");
|
||||
});
|
||||
|
||||
test("Login with invalid email address", async ({ page }) => {
|
||||
const loginPage = new LoginPage(page);
|
||||
await loginPage.goto();
|
||||
await loginPage.enterEmail("test@com");
|
||||
await loginPage.enterPwd(process.env.LOGIN_PWD);
|
||||
await loginPage.isEmailInputErrorDisplayed();
|
||||
await loginPage.isLoginButtonDisplayed();
|
||||
await loginPage.isLoginButtonDisabled();
|
||||
});
|
||||
|
||||
test("Login with no password", async ({ page }) => {
|
||||
const loginPage = new LoginPage(page);
|
||||
await loginPage.goto();
|
||||
await loginPage.enterEmail(process.env.LOGIN_EMAIL);
|
||||
await loginPage.clickPwdInput();
|
||||
await loginPage.clickSection();
|
||||
await loginPage.isPwdInputErrorDisplayed();
|
||||
await loginPage.isLoginButtonDisplayed();
|
||||
await loginPage.isLoginButtonDisabled();
|
||||
});
|
||||
|
||||
test("Login with incorrect password", async ({ page }) => {
|
||||
const loginPage = new LoginPage(page);
|
||||
await loginPage.goto();
|
||||
await loginPage.enterEmail(process.env.LOGIN_EMAIL);
|
||||
await loginPage.enterPwd("11223344");
|
||||
await loginPage.clickLoginButton();
|
||||
await loginPage.isLoginErrorMessageDisplayed(
|
||||
"Username or password seems to be wrong."
|
||||
);
|
||||
});
|