add: full multi-tenancy control
2
packages/Webkul/Admin/tests/e2e-pw/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
/playwright-report
|
||||
/test-results
|
||||
BIN
packages/Webkul/Admin/tests/e2e-pw/data/images/1.webp
Normal file
|
After Width: | Height: | Size: 170 KiB |
BIN
packages/Webkul/Admin/tests/e2e-pw/data/images/10.webp
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
packages/Webkul/Admin/tests/e2e-pw/data/images/11.webp
Normal file
|
After Width: | Height: | Size: 21 KiB |
BIN
packages/Webkul/Admin/tests/e2e-pw/data/images/12.webp
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
packages/Webkul/Admin/tests/e2e-pw/data/images/2.webp
Normal file
|
After Width: | Height: | Size: 242 KiB |
BIN
packages/Webkul/Admin/tests/e2e-pw/data/images/3.webp
Normal file
|
After Width: | Height: | Size: 120 KiB |
BIN
packages/Webkul/Admin/tests/e2e-pw/data/images/4.webp
Normal file
|
After Width: | Height: | Size: 89 KiB |
BIN
packages/Webkul/Admin/tests/e2e-pw/data/images/5.webp
Normal file
|
After Width: | Height: | Size: 204 KiB |
BIN
packages/Webkul/Admin/tests/e2e-pw/data/images/6.webp
Normal file
|
After Width: | Height: | Size: 36 KiB |
BIN
packages/Webkul/Admin/tests/e2e-pw/data/images/7.webp
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
packages/Webkul/Admin/tests/e2e-pw/data/images/8.webp
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
packages/Webkul/Admin/tests/e2e-pw/data/images/9.webp
Normal file
|
After Width: | Height: | Size: 27 KiB |
56
packages/Webkul/Admin/tests/e2e-pw/playwright.config.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
import { defineConfig, devices } from "@playwright/test";
|
||||
import dotenv from "dotenv";
|
||||
import path from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
|
||||
export const TESTS_ROOT_PATH = __dirname;
|
||||
export const STATE_DIR_PATH = `${ TESTS_ROOT_PATH }/.state/`;
|
||||
export const ADMIN_AUTH_STATE_PATH = `${ STATE_DIR_PATH }/admin-auth.json`;
|
||||
|
||||
dotenv.config({ path: path.resolve(__dirname, "../../../../../.env") });
|
||||
|
||||
export default defineConfig({
|
||||
testDir: "./tests",
|
||||
|
||||
timeout: 30 * 1000,
|
||||
|
||||
expect: { timeout: 20 * 1000 },
|
||||
|
||||
outputDir: "./test-results",
|
||||
|
||||
fullyParallel: false,
|
||||
|
||||
workers: 1,
|
||||
|
||||
forbidOnly: !!process.env.CI,
|
||||
|
||||
retries: 0,
|
||||
|
||||
reportSlowTests: null,
|
||||
|
||||
reporter: [
|
||||
[
|
||||
"html",
|
||||
{
|
||||
outputFolder: "./playwright-report",
|
||||
},
|
||||
],
|
||||
],
|
||||
|
||||
use: {
|
||||
baseURL: `${process.env.APP_URL}/`.replace(/\/+$/, "/"),
|
||||
screenshot: { mode: "only-on-failure", fullPage: true },
|
||||
video: "retain-on-failure",
|
||||
trace: "retain-on-failure",
|
||||
},
|
||||
|
||||
projects: [
|
||||
{
|
||||
name: "chromium",
|
||||
use: { ...devices["Desktop Chrome"] },
|
||||
},
|
||||
],
|
||||
});
|
||||
25
packages/Webkul/Admin/tests/e2e-pw/setup.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { test as base, expect, type Page } from "@playwright/test";
|
||||
|
||||
type AdminFixtures = {
|
||||
adminPage: Page;
|
||||
};
|
||||
|
||||
export const test = base.extend<AdminFixtures>({
|
||||
adminPage: async ({ page }, use) => {
|
||||
const adminCredentials = {
|
||||
email: "admin@example.com",
|
||||
password: "admin123",
|
||||
};
|
||||
|
||||
await page.goto("admin/login");
|
||||
await page.fill('input[name="email"]', adminCredentials.email);
|
||||
await page.fill('input[name="password"]', adminCredentials.password);
|
||||
await page.press('input[name="password"]', "Enter");
|
||||
|
||||
await page.waitForURL("**/admin/dashboard");
|
||||
|
||||
await use(page);
|
||||
},
|
||||
});
|
||||
|
||||
export { expect };
|
||||
36
packages/Webkul/Admin/tests/e2e-pw/tests/auth.spec.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import { test, expect } from "../setup";
|
||||
|
||||
const adminCredentials = {
|
||||
email: "admin@example.com",
|
||||
password: "admin123",
|
||||
};
|
||||
|
||||
test("should be able to login", async ({ page }) => {
|
||||
/**
|
||||
* Login as admin.
|
||||
*/
|
||||
await page.goto("admin/login");
|
||||
await page.getByPlaceholder("Email Address").click();
|
||||
await page.getByPlaceholder("Email Address").fill(adminCredentials.email);
|
||||
await page.getByPlaceholder("Password").click();
|
||||
await page.getByPlaceholder("Password").fill(adminCredentials.password);
|
||||
await page.getByRole("button", { name: "Sign In" }).click();
|
||||
|
||||
await expect(page.getByPlaceholder("Mega Search").first()).toBeVisible();
|
||||
});
|
||||
|
||||
test("should be able to logout", async ({ page }) => {
|
||||
/**
|
||||
* Login as admin.
|
||||
*/
|
||||
await page.goto("admin/login");
|
||||
await page.getByPlaceholder("Email Address").click();
|
||||
await page.getByPlaceholder("Email Address").fill(adminCredentials.email);
|
||||
await page.getByPlaceholder("Password").click();
|
||||
await page.getByPlaceholder("Password").fill(adminCredentials.password);
|
||||
await page.getByLabel("Sign In").click();
|
||||
await page.getByRole('button', { name: "E" }).click();
|
||||
await page.getByRole('link', { name: 'Sign Out' }).click();
|
||||
|
||||
await expect(page.getByPlaceholder("Password").first()).toBeVisible();
|
||||
});
|
||||
@@ -0,0 +1,113 @@
|
||||
import { test, expect } from '../../setup';
|
||||
import {generateCompanyName, createOrganization} from "../../utils/faker"
|
||||
|
||||
test.describe("organization management", () => {
|
||||
test('should be able to create organization', async ({ adminPage }) => {
|
||||
/**
|
||||
* Create Organization.
|
||||
*/
|
||||
await createOrganization(adminPage);
|
||||
});
|
||||
|
||||
test('should be able to edit detail of organization', async ({ adminPage }) => {
|
||||
/**
|
||||
* Create Organization.
|
||||
*/
|
||||
const companyName = await createOrganization(adminPage);
|
||||
|
||||
/**
|
||||
* Edit Organization detail.
|
||||
*/
|
||||
await adminPage.locator('div').filter({ hasText: companyName }).locator('span.icon-edit').first().click();
|
||||
await adminPage.getByRole('textbox', { name: 'City' }).click();
|
||||
await adminPage.getByRole('textbox', { name: 'City' }).fill('Gurugram');
|
||||
await adminPage.getByRole('button', { name: 'Save Organization' }).click();
|
||||
|
||||
/**
|
||||
* Check detail are Edit
|
||||
*/
|
||||
await adminPage.locator('div').filter({ hasText: companyName }).locator('span.icon-edit').first().click();
|
||||
await expect(adminPage.getByRole('textbox', { name: 'City' })).toHaveValue('Gurugram');
|
||||
});
|
||||
|
||||
test('should be able to delete organization', async ({ adminPage }) => {
|
||||
await adminPage.goto('admin/contacts/organizations');
|
||||
|
||||
/**
|
||||
* Delete Organization.
|
||||
*/
|
||||
await adminPage.locator('div')
|
||||
.locator('span.icon-delete')
|
||||
.first()
|
||||
.click();
|
||||
|
||||
await adminPage.getByRole('button', { name: 'Agree', exact: true }).click();
|
||||
await expect(adminPage.locator('#app')).toContainText('Success');
|
||||
});
|
||||
|
||||
test('should be able to mass delete organization', async ({ adminPage }) => {
|
||||
/**
|
||||
* Create Multiple Organizations.
|
||||
*/
|
||||
await createOrganization(adminPage);
|
||||
await createOrganization(adminPage);
|
||||
await createOrganization(adminPage);
|
||||
await createOrganization(adminPage);
|
||||
await createOrganization(adminPage);
|
||||
|
||||
/**
|
||||
* Check if any organization has value greater than 0.
|
||||
*/
|
||||
const organizationCount = await adminPage.locator('#app').getByText('1', { exact: true }).count();
|
||||
|
||||
/**
|
||||
* Mass Delete Organization.
|
||||
*/
|
||||
await adminPage.locator('.icon-checkbox-outline').first().click();
|
||||
await adminPage.getByRole('button', { name: 'Delete' }).click();
|
||||
await adminPage.getByRole('button', { name: 'Agree', exact: true }).click();
|
||||
|
||||
if (organizationCount > 0) {
|
||||
await expect(adminPage.getByText('Error')).toBeVisible();
|
||||
}
|
||||
else{
|
||||
await expect(adminPage.locator('#app')).toContainText('Success');
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
test('should not be able to create same name organization', async ({ adminPage }) => {
|
||||
/**
|
||||
* Create Organization.
|
||||
*/
|
||||
const companyName = await createOrganization(adminPage);
|
||||
await adminPage.getByRole('link', { name: 'Create Organization' }).click();
|
||||
|
||||
/**
|
||||
* Fill in organization details
|
||||
*/
|
||||
await adminPage.getByRole('textbox', { name: 'Name *' }).fill(companyName);
|
||||
await adminPage.locator('textarea[name="address\\[address\\]"]').fill('ARV Park');
|
||||
await adminPage.getByRole('combobox').selectOption('IN');
|
||||
await adminPage.locator('select[name="address\\[state\\]"]').selectOption('DL');
|
||||
await adminPage.getByRole('textbox', { name: 'City' }).fill('Delhi');
|
||||
await adminPage.getByRole('textbox', { name: 'Postcode' }).fill('123456');
|
||||
|
||||
/**
|
||||
* Click to add extra details
|
||||
*/
|
||||
await adminPage.locator('div').filter({ hasText: /^Click to add$/ }).nth(2).click();
|
||||
await adminPage.getByRole('textbox', { name: 'Search...' }).fill('exampl');
|
||||
await adminPage.getByRole('listitem').filter({ hasText: 'Example' }).click();
|
||||
|
||||
/**
|
||||
* Click on "Save Organization"
|
||||
*/
|
||||
await adminPage.getByRole('button', { name: 'Save Organization' }).click();
|
||||
|
||||
/**
|
||||
* Expect Error message
|
||||
*/
|
||||
await expect(adminPage.locator('#app')).toContainText('The value has already been taken.');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,40 @@
|
||||
import { test, expect } from "../../setup";
|
||||
import { createPerson, generateCompanyName } from "../../utils/faker";
|
||||
|
||||
test("should be able to create person", async ({ adminPage }) => {
|
||||
/**
|
||||
* Create person.
|
||||
*/
|
||||
await adminPage.goto("admin/contacts/persons");
|
||||
await createPerson(adminPage);
|
||||
});
|
||||
|
||||
test("should be able to assign a company to person", async ({ adminPage }) => {
|
||||
/**
|
||||
* Create person.
|
||||
*/
|
||||
await adminPage.goto("admin/contacts/persons");
|
||||
await createPerson(adminPage);
|
||||
await adminPage.locator("span.icon-edit").first().click();
|
||||
await adminPage
|
||||
.locator("div")
|
||||
.filter({ hasText: /^Click to add$/ })
|
||||
.nth(2)
|
||||
.click();
|
||||
await adminPage.getByRole("textbox", { name: "Search..." }).click();
|
||||
await adminPage
|
||||
.getByRole("textbox", { name: "Search..." })
|
||||
.fill(generateCompanyName());
|
||||
await adminPage.getByText("Add as New").click();
|
||||
await adminPage.getByRole("button", { name: "Save Person" }).click();
|
||||
});
|
||||
|
||||
test("should be able to delete person", async ({ adminPage }) => {
|
||||
/**
|
||||
* Delete person.
|
||||
*/
|
||||
await adminPage.goto("admin/contacts/persons");
|
||||
await adminPage.locator("span.icon-delete").nth(1).click();
|
||||
await adminPage.getByRole("button", { name: "Agree", exact: true }).click();
|
||||
await expect(adminPage.locator("#app")).toContainText("Success");
|
||||
});
|
||||
81
packages/Webkul/Admin/tests/e2e-pw/tests/lang/lang.spec.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
import { expect, test } from '@playwright/test';
|
||||
import { execSync } from 'child_process';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
|
||||
// Resolve file paths relative to this test file
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
|
||||
// Absolute path to /lang directory
|
||||
const LANG_DIR = path.resolve(
|
||||
__dirname,
|
||||
'../../../../src/Resources/lang'
|
||||
);
|
||||
|
||||
const BASE_LANG = 'en';
|
||||
|
||||
// Helper to extract just the keys from app.php
|
||||
function getNormalizedKeys(filePath: string): string[] {
|
||||
// PHP one-liner to output the array as JSON
|
||||
const phpCode = `echo json_encode(include '${filePath}');`;
|
||||
const json = execSync(`php -r "${phpCode.replace(/"/g, '\\"')}"`).toString();
|
||||
const obj = JSON.parse(json);
|
||||
|
||||
function flattenKeys(obj: any, prefix = ''): string[] {
|
||||
return Object.keys(obj).flatMap(key => {
|
||||
const fullKey = prefix ? `${prefix}.${key}` : key;
|
||||
if (typeof obj[key] === 'object' && obj[key] !== null) {
|
||||
return flattenKeys(obj[key], fullKey);
|
||||
}
|
||||
return [fullKey];
|
||||
});
|
||||
}
|
||||
|
||||
return flattenKeys(obj);
|
||||
}
|
||||
test('All language files must match number of keys and key names with English app.php', () => {
|
||||
const baseFile = path.join(LANG_DIR, BASE_LANG, 'app.php');
|
||||
const baseKeys = getNormalizedKeys(baseFile);
|
||||
// All locales except the base one
|
||||
const locales = fs
|
||||
.readdirSync(LANG_DIR)
|
||||
.filter(locale => locale !== BASE_LANG && fs.existsSync(path.join(LANG_DIR, locale, 'app.php')));
|
||||
|
||||
// Array to collect any locales that have issues
|
||||
let failedLocales: { locale: string; missingKeys: string[]; extraKeys: string[] }[] = [];
|
||||
|
||||
for (const locale of locales) {
|
||||
const filePath = path.join(LANG_DIR, locale, 'app.php');
|
||||
const keys = getNormalizedKeys(filePath);
|
||||
|
||||
const missingKeys = baseKeys.filter(key => !keys.includes(key));
|
||||
const extraKeys = keys.filter(key => !baseKeys.includes(key));
|
||||
|
||||
if (missingKeys.length > 0 || extraKeys.length > 0) {
|
||||
failedLocales.push({ locale, missingKeys, extraKeys });
|
||||
}
|
||||
}
|
||||
|
||||
if (failedLocales.length > 0) {
|
||||
for (const { locale, missingKeys, extraKeys } of failedLocales) {
|
||||
console.error(` ${locale}/app.php has issues:`);
|
||||
|
||||
if (missingKeys.length) {
|
||||
console.error(` Missing keys (${missingKeys.length}):`);
|
||||
for (const key of missingKeys) console.error(` - ${key}`);
|
||||
}
|
||||
|
||||
if (extraKeys.length) {
|
||||
console.error(` Extra keys (${extraKeys.length}):`);
|
||||
for (const key of extraKeys) console.error(` + ${key}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Fail the test
|
||||
expect(failedLocales).toEqual([]);
|
||||
} else {
|
||||
console.log('All language files have matching keys and counts with en/app.php');
|
||||
}
|
||||
});
|
||||
235
packages/Webkul/Admin/tests/e2e-pw/tests/lead.spec.ts
Normal file
@@ -0,0 +1,235 @@
|
||||
import { test, expect } from "../setup";
|
||||
import fs from "fs";
|
||||
import { generateName, getRandomDateTime, generateDescription, generateDate, generateEmail, generatePhoneNumber,generateEmailSubject } from '../utils/faker';
|
||||
|
||||
async function generateLead(adminPage) {
|
||||
/**
|
||||
* Go to the lead listing page.
|
||||
*/
|
||||
await adminPage.goto("admin/leads");
|
||||
await adminPage.getByRole('link', { name: 'Create Lead' }).click();
|
||||
|
||||
/**
|
||||
* Fill the lead form.
|
||||
*/
|
||||
const leadTitle = generateName();
|
||||
const leadDescription = generateDescription();
|
||||
const leadDate = generateDate();
|
||||
const leadEmail = generateEmail();
|
||||
const leadPhoneNumber = generatePhoneNumber();
|
||||
|
||||
await adminPage.fill('input[name="title"]', leadTitle);
|
||||
await adminPage.fill('textarea[name="description"]', leadDescription);
|
||||
await adminPage.locator('select[name="lead_source_id"]').selectOption("1");
|
||||
await adminPage.fill('input[name="expected_close_date"]', leadDate);
|
||||
await adminPage.locator('select[name="lead_type_id"]').selectOption("1");
|
||||
await adminPage.locator('select[name="user_id"]').selectOption("1");
|
||||
await adminPage.fill('input[name="lead_value"]', '1000');
|
||||
|
||||
/**
|
||||
* Add a new person.
|
||||
*/
|
||||
await adminPage.locator('div').filter({ hasText: /^Click to Add$/ }).nth(1).click();
|
||||
await adminPage.getByRole('textbox', { name: 'Search...' }).fill(leadTitle);
|
||||
await adminPage.getByText('Add as New').click();
|
||||
|
||||
await adminPage.fill('input[name="person[emails][0][value]"]', leadEmail);
|
||||
await adminPage.fill('input[name="person[contact_numbers][0][value]"]', leadPhoneNumber);
|
||||
|
||||
/**
|
||||
* Associate an organization.
|
||||
*/
|
||||
await adminPage.locator('div').filter({ hasText: /^Click to add$/ }).nth(2).click();
|
||||
await adminPage.getByRole('textbox', { name: 'Search...' }).fill(leadTitle);
|
||||
await adminPage.getByText('Add as New').click();
|
||||
|
||||
/**
|
||||
* Save the lead.
|
||||
*/
|
||||
await adminPage.getByRole('button', { name: 'Save' }).click();
|
||||
|
||||
/**
|
||||
* Assertion to confirm lead creation.
|
||||
*/
|
||||
await expect(adminPage.getByText('Success', { exact: true })).toBeVisible();
|
||||
|
||||
return { leadTitle, leadDescription, leadDate, leadEmail, leadPhoneNumber };
|
||||
}
|
||||
|
||||
function generateFile(fileName, content) {
|
||||
fs.writeFileSync(fileName, content);
|
||||
return fileName;
|
||||
}
|
||||
|
||||
test.describe("lead management", () => {
|
||||
|
||||
test("should create a new lead", async ({ adminPage }) => {
|
||||
/**
|
||||
* Create a new lead.
|
||||
*/
|
||||
await generateLead(adminPage);
|
||||
});
|
||||
|
||||
test("should able to update lead", async ({ adminPage }) => {
|
||||
/**
|
||||
* Create a new lead.
|
||||
*/
|
||||
const lead = await generateLead(adminPage);
|
||||
|
||||
/**
|
||||
* Update the lead.
|
||||
*/
|
||||
await adminPage.getByRole('link', { name: lead.leadTitle }).click();
|
||||
const page1Promise = adminPage.waitForEvent('popup');
|
||||
await adminPage.getByRole('link', { name: '' }).first().click();
|
||||
const page1 = await page1Promise;
|
||||
await page1.fill('textarea[name="description"]', generateDescription());
|
||||
await page1.fill('input[name="title"]', generateName());
|
||||
await page1.getByLabel('Source').selectOption('3');
|
||||
await page1.fill('input[name="lead_value"]', '30000');
|
||||
await page1.getByRole('button', { name: 'Save' }).click();
|
||||
await page1.getByText('Success', { exact: true }).click();
|
||||
});
|
||||
|
||||
test("should able to delete lead", async ({ adminPage }) => {
|
||||
/**
|
||||
* Create a new lead.
|
||||
*/
|
||||
const lead = await generateLead(adminPage);
|
||||
|
||||
/**
|
||||
* Delete the lead.
|
||||
*/
|
||||
await adminPage.getByRole('link', { name: '' }).click();
|
||||
await adminPage.locator('div:nth-child(4) > .flex > span:nth-child(2)').click();
|
||||
await adminPage.getByRole('button', { name: 'Agree', exact: true }).click();
|
||||
await expect(adminPage.getByText('Success', { exact: true })).toBeVisible();
|
||||
await expect(adminPage.locator('#app')).toContainText('Lead deleted successfully.');
|
||||
});
|
||||
|
||||
test("should sent a mail", async ({ adminPage }) => {
|
||||
/**
|
||||
* Create a new lead.
|
||||
*/
|
||||
const lead = await generateLead(adminPage);
|
||||
|
||||
/**
|
||||
* fill mail detail.
|
||||
*/
|
||||
await adminPage.getByRole('link', { name: lead.leadTitle}).click();
|
||||
await adminPage.getByRole('button', { name: ' Mail' }).click();
|
||||
await adminPage.fill('input[name="temp-reply_to"]', generateEmail());
|
||||
await adminPage.fill('input[name="subject"]', generateEmailSubject());
|
||||
await adminPage.fill('textarea[name="reply"]', generateDescription());
|
||||
|
||||
/**
|
||||
* Sending mail and closing the modal.
|
||||
*/
|
||||
await adminPage.getByRole('button', { name: 'Send' }).click();
|
||||
|
||||
await expect(adminPage.getByText('Email sent successfully.')).toBeVisible();
|
||||
});
|
||||
|
||||
test("should able to upload file in lead", async ({ adminPage }) => {
|
||||
/**
|
||||
* Create a new lead.
|
||||
*/
|
||||
const lead = await generateLead(adminPage);
|
||||
|
||||
/**
|
||||
* fill the file detail or upload a file.
|
||||
*/
|
||||
await adminPage.getByRole('link', { name: lead.leadTitle}).click();
|
||||
await adminPage.getByRole('button', { name: ' File' }).click();
|
||||
await adminPage.locator('input[name="title"]').fill(lead.leadTitle);
|
||||
await adminPage.locator('textarea[name="comment"]').fill(generateDescription());
|
||||
await adminPage.locator('input[name="name"]').fill(generateName());
|
||||
await adminPage.locator('#file').setInputFiles(generateFile('example.txt', 'Hello, this is a generated file!'));
|
||||
await adminPage.getByRole('button', { name: 'Save File' }).click();
|
||||
});
|
||||
|
||||
test("should able to write a note in lead", async ({ adminPage }) => {
|
||||
/**
|
||||
* Create a new lead.
|
||||
*/
|
||||
const lead = await generateLead(adminPage);
|
||||
|
||||
/**
|
||||
* write a notes
|
||||
*/
|
||||
await adminPage.getByRole('link', { name: lead.leadTitle}).click();
|
||||
await adminPage.getByRole('button', { name: ' Note' }).click();
|
||||
await adminPage.locator('textarea[name="comment"]').fill(generateDescription());
|
||||
await adminPage.getByRole('button', { name: 'Save Note' }).click();
|
||||
});
|
||||
|
||||
test("should able to add call activity in lead", async ({ adminPage }) => {
|
||||
/**
|
||||
* Create a new lead.
|
||||
*/
|
||||
const lead = await generateLead(adminPage);
|
||||
|
||||
/**
|
||||
* write a call activity detail
|
||||
*/
|
||||
await adminPage.getByRole('link', { name: lead.leadTitle}).click();
|
||||
await adminPage.getByRole('button', { name: ' Activity' }).click();
|
||||
await adminPage.getByRole('heading', { name: 'Add Activity - Call ' }).locator('span').click();
|
||||
await adminPage.getByText('Call', { exact: true }).click();
|
||||
await adminPage.locator('input[name="title"]').fill(lead.leadTitle);
|
||||
await adminPage.locator('textarea[name="comment"]').fill(generateDescription());
|
||||
await adminPage.locator('input[name="schedule_from"]').click();
|
||||
await adminPage.locator('input[name="schedule_from"]').fill(getRandomDateTime());
|
||||
await adminPage.locator('input[name="schedule_to"]').click();
|
||||
await adminPage.locator('input[name="schedule_to"]').fill(getRandomDateTime());
|
||||
await adminPage.locator('input[name="location"]').fill('call');
|
||||
await adminPage.getByRole('button', { name: 'Save Activity' }).click();
|
||||
|
||||
});
|
||||
|
||||
test("should able to add meeting activity in lead", async ({ adminPage }) => {
|
||||
/**
|
||||
* Create a new lead.
|
||||
*/
|
||||
const lead = await generateLead(adminPage);
|
||||
|
||||
/**
|
||||
* write a call activity detail
|
||||
*/
|
||||
await adminPage.getByRole('link', { name: lead.leadTitle}).click();
|
||||
await adminPage.getByRole('button', { name: ' Activity' }).click();
|
||||
await adminPage.getByRole('heading', { name: 'Add Activity' }).locator('span').click();
|
||||
await adminPage.getByText('Meeting', { exact: true }).click();
|
||||
await adminPage.locator('input[name="title"]').fill(lead.leadTitle);
|
||||
await adminPage.locator('textarea[name="comment"]').fill(generateDescription());
|
||||
await adminPage.locator('input[name="schedule_from"]').click();
|
||||
await adminPage.locator('input[name="schedule_from"]').fill(getRandomDateTime());
|
||||
await adminPage.locator('input[name="schedule_to"]').click();
|
||||
await adminPage.locator('input[name="schedule_to"]').fill(getRandomDateTime());
|
||||
await adminPage.locator('input[name="location"]').fill('Google meet');
|
||||
await adminPage.getByRole('button', { name: 'Save Activity' }).click();
|
||||
});
|
||||
|
||||
test("should able to add lunch activity in lead", async ({ adminPage }) => {
|
||||
/**
|
||||
* Create a new lead.
|
||||
*/
|
||||
const lead = await generateLead(adminPage);
|
||||
|
||||
/**
|
||||
* write a call activity detail
|
||||
*/
|
||||
await adminPage.getByRole('link', { name: lead.leadTitle}).click();
|
||||
await adminPage.getByRole('button', { name: ' Activity' }).click();
|
||||
await adminPage.getByRole('heading', { name: 'Add Activity' }).locator('span').click();
|
||||
await adminPage.getByText('Lunch', { exact: true }).click();
|
||||
await adminPage.locator('input[name="title"]').fill(lead.leadTitle);
|
||||
await adminPage.locator('textarea[name="comment"]').fill(generateDescription());
|
||||
await adminPage.locator('input[name="schedule_from"]').click();
|
||||
await adminPage.locator('input[name="schedule_from"]').fill(getRandomDateTime());
|
||||
await adminPage.locator('input[name="schedule_to"]').click();
|
||||
await adminPage.locator('input[name="schedule_to"]').fill(getRandomDateTime());
|
||||
await adminPage.locator('input[name="location"]').fill('Restraunt');
|
||||
await adminPage.getByRole('button', { name: 'Save Activity' }).click();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1 @@
|
||||
import { test, expect } from "../../setup";
|
||||
69
packages/Webkul/Admin/tests/e2e-pw/tests/mail/inbox.spec.ts
Normal file
@@ -0,0 +1,69 @@
|
||||
import { test, expect } from '../../setup';
|
||||
import { generateEmail, generateEmailSubject, generateDescription } from '../../utils/faker';
|
||||
|
||||
async function composeMail(adminPage, ccMail = false, bccMail = false) {
|
||||
/**
|
||||
* Reaching to the mail listing page.
|
||||
*/
|
||||
await adminPage.goto("admin/mail/inbox");
|
||||
|
||||
/**
|
||||
* Opening compose mail in modal.
|
||||
*/
|
||||
await adminPage.getByRole('button', { name: 'Compose Mail' }).click();
|
||||
await adminPage.fill('input[name="temp-reply_to"]', generateEmail());
|
||||
await adminPage.fill('input[name="subject"]', generateEmailSubject());
|
||||
const frameElementHandle = await adminPage.waitForSelector(
|
||||
"iframe.tox-edit-area__iframe"
|
||||
);
|
||||
|
||||
const frame = await frameElementHandle.contentFrame();
|
||||
|
||||
await frame.waitForSelector("body");
|
||||
await frame.fill("body", generateDescription());
|
||||
|
||||
/**
|
||||
* Sending mail and closing the modal.
|
||||
*/
|
||||
await adminPage.getByRole("button", { name: "Send" }).click();
|
||||
|
||||
await expect(adminPage.getByText("Email sent successfully.")).toBeVisible();
|
||||
}
|
||||
|
||||
test.describe("mail management", () => {
|
||||
/**
|
||||
* Should be able to compose a mail.
|
||||
*/
|
||||
test("should compose a mail", async ({ adminPage }) => {
|
||||
await composeMail(adminPage);
|
||||
});
|
||||
|
||||
/**
|
||||
* Should be able to compose a mail with CC.
|
||||
*/
|
||||
test("should compose a mail with CC", async ({ adminPage }) => {
|
||||
const ccMail = true;
|
||||
|
||||
await composeMail(adminPage, ccMail);
|
||||
});
|
||||
|
||||
/**
|
||||
* Should be able to compose a mail with BCC.
|
||||
*/
|
||||
test("should compose a mail with BCC", async ({ adminPage }) => {
|
||||
const bccMail = true;
|
||||
|
||||
await composeMail(adminPage, bccMail);
|
||||
});
|
||||
|
||||
/**
|
||||
* Should be able to compose a mail with CC & BCC.
|
||||
*/
|
||||
test("should compose a mail with CC & BCC", async ({ adminPage }) => {
|
||||
const ccMail = true;
|
||||
|
||||
const bccMail = true;
|
||||
|
||||
await composeMail(adminPage, ccMail, bccMail);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1 @@
|
||||
import { test, expect } from "../../setup";
|
||||
@@ -0,0 +1 @@
|
||||
import { test, expect } from "../../setup";
|
||||
@@ -0,0 +1 @@
|
||||
import { test, expect } from "../../setup";
|
||||
102
packages/Webkul/Admin/tests/e2e-pw/tests/product.spec.ts
Normal file
@@ -0,0 +1,102 @@
|
||||
import { test, expect } from "../setup";
|
||||
import { generateName, generateSKU, generateDescription } from "../utils/faker";
|
||||
|
||||
test.describe("product management", () => {
|
||||
test("should create a product", async ({ adminPage }) => {
|
||||
/**
|
||||
* Go to the product listing page.
|
||||
*/
|
||||
await adminPage.goto("admin/products");
|
||||
|
||||
/**
|
||||
* Create Product.
|
||||
*/
|
||||
await adminPage.getByRole("link", { name: "Create Product" }).click();
|
||||
|
||||
/**
|
||||
* Fill the product form.
|
||||
*/
|
||||
const name = generateName();
|
||||
const description = generateDescription();
|
||||
await adminPage.waitForSelector('input[name="name"]', { state: 'visible' });
|
||||
await adminPage.getByRole('textbox', { name: 'Name *' }).click();
|
||||
await adminPage.locator('#name').clear();
|
||||
await adminPage.getByRole('textbox', { name: 'Name *' }).fill(name);
|
||||
await adminPage.locator('textarea[name="description"]').clear();
|
||||
await adminPage
|
||||
.locator('textarea[name="description"]')
|
||||
.type(description);
|
||||
await adminPage.fill('input[name="sku"]', generateSKU());
|
||||
await adminPage.waitForSelector('input[name="price"]', {
|
||||
state: "visible",
|
||||
});
|
||||
await adminPage.fill('input[name="price"]', "100");
|
||||
|
||||
await adminPage.waitForSelector('input[name="quantity"]', {
|
||||
state: "visible",
|
||||
});
|
||||
await adminPage.fill('input[name="quantity"]', "50");
|
||||
|
||||
/**
|
||||
* Save Product.
|
||||
*/
|
||||
await adminPage.getByRole("button", { name: "Save Products" }).click();
|
||||
|
||||
/**
|
||||
* sucess message appear.
|
||||
*/
|
||||
await expect(adminPage.locator("#app")).toContainText(
|
||||
"Product created successfully."
|
||||
);
|
||||
});
|
||||
|
||||
test("should edit a product", async ({ adminPage }) => {
|
||||
/**
|
||||
* Go to the product listing page.
|
||||
*/
|
||||
await adminPage.goto("admin/products");
|
||||
await adminPage.waitForSelector("a.primary-button", {
|
||||
state: "visible",
|
||||
});
|
||||
|
||||
/**
|
||||
* Clicking on the edit icon.
|
||||
*/
|
||||
await adminPage.locator("span.icon-edit").first().click();
|
||||
await adminPage.waitForSelector('form[action*="/admin/products/edit"]');
|
||||
|
||||
/**
|
||||
* Edit the product Detail
|
||||
*/
|
||||
await adminPage.fill('input[name="name"]', generateName());
|
||||
await adminPage.fill('input[name="price"]', "1000");
|
||||
await adminPage.fill('input[name="quantity"]', "500");
|
||||
await adminPage.click('button:has-text("Save Products")');
|
||||
await expect(adminPage.locator("#app")).toContainText(
|
||||
"Product updated successfully." );
|
||||
});
|
||||
|
||||
test("should delete a product", async ({ adminPage }) => {
|
||||
/**
|
||||
* Go to the product listing page.
|
||||
*/
|
||||
await adminPage.goto("admin/products");
|
||||
await adminPage.waitForSelector("a.primary-button", {
|
||||
state: "visible",
|
||||
});
|
||||
|
||||
/**
|
||||
* Clicking on the delete icon.
|
||||
*/
|
||||
await adminPage.waitForSelector("span.cursor-pointer.icon-delete", {
|
||||
state: "visible",
|
||||
});
|
||||
await adminPage.locator("span.icon-delete").first().click();
|
||||
await adminPage.click(
|
||||
"button.transparent-button + button.primary-button:visible"
|
||||
);
|
||||
await expect(adminPage.locator("#app")).toContainText(
|
||||
"Product deleted successfully."
|
||||
);
|
||||
});
|
||||
});
|
||||
103
packages/Webkul/Admin/tests/e2e-pw/tests/quotes.spec.ts
Normal file
@@ -0,0 +1,103 @@
|
||||
import { test, expect } from "../setup";
|
||||
import {
|
||||
generateEmailSubject,
|
||||
createPerson,
|
||||
generateDate,
|
||||
generateName,
|
||||
} from "../utils/faker";
|
||||
|
||||
test.describe("quotes management", () => {
|
||||
test("should create a quotes", async ({ adminPage }) => {
|
||||
/**
|
||||
* Create person.
|
||||
*/
|
||||
await adminPage.goto("admin/contacts/persons");
|
||||
const Person = await createPerson(adminPage);
|
||||
|
||||
/**
|
||||
* Create quote.
|
||||
*/
|
||||
await adminPage.goto("admin/quotes");
|
||||
await adminPage.getByRole("link", { name: "Create Quote" }).click();
|
||||
await adminPage.getByRole("textbox", { name: "Subject *" }).click();
|
||||
await adminPage
|
||||
.getByRole("textbox", { name: "Subject *" })
|
||||
.fill(generateEmailSubject());
|
||||
await adminPage.getByRole("textbox", { name: "Description" }).click();
|
||||
await adminPage
|
||||
.getByRole("textbox", { name: "Description" })
|
||||
.fill(generateEmailSubject());
|
||||
await adminPage.getByLabel("Sales Owner").selectOption("1");
|
||||
await adminPage.getByRole("textbox", { name: "Expired At *" }).click();
|
||||
await adminPage
|
||||
.getByRole("textbox", { name: "Expired At *" })
|
||||
.fill(generateDate());
|
||||
await adminPage.locator(".relative > div > .relative").first().click();
|
||||
await adminPage.getByRole("textbox", { name: "Search..." }).click();
|
||||
await adminPage
|
||||
.getByRole("textbox", { name: "Search..." })
|
||||
.fill(Person.Name);
|
||||
await adminPage
|
||||
.getByRole("listitem")
|
||||
.filter({ hasText: Person.Name })
|
||||
.click();
|
||||
|
||||
/**
|
||||
* Fill billing address.
|
||||
*/
|
||||
await adminPage
|
||||
.locator('textarea[name="billing_address\\[address\\]"]')
|
||||
.click();
|
||||
await adminPage
|
||||
.locator('textarea[name="billing_address\\[address\\]"]')
|
||||
.fill("ARV Park");
|
||||
await adminPage
|
||||
.locator('select[name="billing_address\\[country\\]"]')
|
||||
.selectOption("IN");
|
||||
await adminPage
|
||||
.locator('select[name="billing_address\\[state\\]"]')
|
||||
.selectOption("UP");
|
||||
await adminPage
|
||||
.locator('input[name="billing_address\\[city\\]"]')
|
||||
.click();
|
||||
await adminPage
|
||||
.locator('input[name="billing_address\\[city\\]"]')
|
||||
.fill("Noida");
|
||||
await adminPage
|
||||
.locator('input[name="billing_address\\[postcode\\]"]')
|
||||
.click();
|
||||
await adminPage
|
||||
.locator('input[name="billing_address\\[postcode\\]"]')
|
||||
.fill("201301");
|
||||
|
||||
/**
|
||||
* Fill shipping address.
|
||||
*/
|
||||
await adminPage
|
||||
.locator('textarea[name="shipping_address\\[address\\]"]')
|
||||
.click();
|
||||
await adminPage
|
||||
.locator('textarea[name="shipping_address\\[address\\]"]')
|
||||
.fill("ARV Park");
|
||||
await adminPage
|
||||
.locator('select[name="shipping_address\\[country\\]"]')
|
||||
.selectOption("IN");
|
||||
await adminPage
|
||||
.locator('select[name="shipping_address\\[state\\]"]')
|
||||
.selectOption("UP");
|
||||
await adminPage
|
||||
.locator('input[name="shipping_address\\[city\\]"]')
|
||||
.click();
|
||||
await adminPage
|
||||
.locator('input[name="shipping_address\\[city\\]"]')
|
||||
.fill("Noida");
|
||||
await adminPage
|
||||
.locator('input[name="shipping_address\\[postcode\\]"]')
|
||||
.click();
|
||||
await adminPage
|
||||
.locator('input[name="shipping_address\\[postcode\\]"]')
|
||||
.fill("201301");
|
||||
await adminPage.getByRole("button", { name: "Save Quote" }).click();
|
||||
await expect(adminPage.locator("#app")).toContainText("Success");
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,94 @@
|
||||
import { test, expect } from "../../../setup";
|
||||
import { generateFullName, generateDescription, generateDate } from "../../../utils/faker";
|
||||
import { confirmModal } from "../../../utils/components";
|
||||
|
||||
test.describe("event management", () => {
|
||||
test("should create a event", async ({ adminPage }) => {
|
||||
/**
|
||||
* Reaching to the events listing page.
|
||||
*/
|
||||
await adminPage.goto("admin/settings/marketing/events");
|
||||
|
||||
/**
|
||||
* Opening create event form in modal.
|
||||
*/
|
||||
await adminPage.getByRole("button", { name: "Create Event" }).click();
|
||||
|
||||
/**
|
||||
* Filling the form with event details.
|
||||
*/
|
||||
await adminPage
|
||||
.locator('input[name="name"]')
|
||||
.fill(generateFullName());
|
||||
await adminPage
|
||||
.locator('textarea[name="description"]')
|
||||
.fill(generateDescription());
|
||||
await adminPage
|
||||
.locator('input[name="date"]')
|
||||
.fill(generateDate());
|
||||
await adminPage.getByRole('textbox', { name: 'Date *' }).press('Enter');
|
||||
|
||||
/**
|
||||
* Save event and close the modal.
|
||||
*/
|
||||
await adminPage.getByRole('button', { name: 'Save Event' }).click();
|
||||
|
||||
await expect(
|
||||
adminPage.getByText("Event created successfully.")
|
||||
).toBeVisible();
|
||||
});
|
||||
|
||||
test("should edit a event", async ({ adminPage }) => {
|
||||
/**
|
||||
* Reaching to the events listing page.
|
||||
*/
|
||||
await adminPage.goto("admin/settings/marketing/events");
|
||||
|
||||
/**
|
||||
* Clicking on the edit button for the first event opens the modal.
|
||||
*/
|
||||
await adminPage.locator('.row > div:nth-child(6) > a').first().click();
|
||||
|
||||
/**
|
||||
* Fill the form with the event details.
|
||||
*/
|
||||
await adminPage
|
||||
.locator('input[name="name"]')
|
||||
.fill(generateFullName());
|
||||
await adminPage
|
||||
.locator('textarea[name="description"]')
|
||||
.fill(generateDescription());
|
||||
await adminPage
|
||||
.locator('input[name="date"]')
|
||||
.fill(generateDate());
|
||||
|
||||
/**
|
||||
* Saving event and closing the modal.
|
||||
*/
|
||||
await adminPage.getByRole('button', { name: 'Save Event' }).click();
|
||||
await expect(
|
||||
adminPage.getByText("Event updated successfully.")
|
||||
).toBeVisible();
|
||||
});
|
||||
|
||||
test("should delete a event", async ({ adminPage }) => {
|
||||
/**
|
||||
* Reaching to the event listing page.
|
||||
*/
|
||||
await adminPage.goto("admin/settings/marketing/events");
|
||||
|
||||
/**
|
||||
* Delete the first event.
|
||||
*/
|
||||
await adminPage.locator('div:nth-child(6) > a:nth-child(2)').first().click();
|
||||
|
||||
/**
|
||||
* Delete confirmation modal.
|
||||
*/
|
||||
await adminPage.getByRole('button', { name: 'Agree', exact: true }).click();
|
||||
|
||||
await expect(
|
||||
adminPage.getByText("Event deleted successfully.")
|
||||
).toBeVisible();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,90 @@
|
||||
import { test, expect } from "../../../setup";
|
||||
import { generateFullName } from "../../../utils/faker";
|
||||
import { confirmModal } from "../../../utils/components";
|
||||
|
||||
test.describe("type management", () => {
|
||||
test("should create a type", async ({ adminPage }) => {
|
||||
/**
|
||||
* Reaching to the types listing page.
|
||||
*/
|
||||
await adminPage.goto("admin/settings/types");
|
||||
|
||||
/**
|
||||
* Opening create type form in modal.
|
||||
*/
|
||||
await adminPage.getByRole("button", { name: "Create Type" }).click();
|
||||
|
||||
/**
|
||||
* Filling the form with type details.
|
||||
*/
|
||||
await adminPage
|
||||
.locator('input[name="name"]')
|
||||
.fill(generateFullName());
|
||||
|
||||
/**
|
||||
* Save type and close the modal.
|
||||
*/
|
||||
await adminPage.getByRole("button", { name: "Save Type" }).click();
|
||||
|
||||
await expect(
|
||||
adminPage.getByText("Type created successfully.")
|
||||
).toBeVisible();
|
||||
});
|
||||
|
||||
test("should edit a type", async ({ adminPage }) => {
|
||||
/**
|
||||
* Generating new name and email for the type.
|
||||
*/
|
||||
const updatedName = generateFullName();
|
||||
|
||||
/**
|
||||
* Reaching to the types listing page.
|
||||
*/
|
||||
await adminPage.goto("admin/settings/types");
|
||||
|
||||
/**
|
||||
* Clicking on the edit button for the first type opens the modal.
|
||||
*/
|
||||
await adminPage.waitForSelector("span.cursor-pointer.icon-edit", {
|
||||
state: "visible",
|
||||
});
|
||||
const iconEdit = await adminPage.$$("span.cursor-pointer.icon-edit");
|
||||
await iconEdit[0].click();
|
||||
|
||||
await adminPage.locator('input[name="name"]').fill(updatedName);
|
||||
|
||||
/**
|
||||
* Saving type and closing the modal.
|
||||
*/
|
||||
await adminPage.getByRole("button", { name: "Save Type" }).click();
|
||||
|
||||
await expect(
|
||||
adminPage.getByText("Type updated successfully.")
|
||||
).toBeVisible();
|
||||
});
|
||||
|
||||
test("should delete a type", async ({ adminPage }) => {
|
||||
/**
|
||||
* Reaching to the type listing page.
|
||||
*/
|
||||
await adminPage.goto("admin/settings/types");
|
||||
|
||||
/**
|
||||
* Delete the first type.
|
||||
*/
|
||||
await adminPage.waitForSelector("span.cursor-pointer.icon-delete");
|
||||
const iconDelete = await adminPage.$$(
|
||||
"span.cursor-pointer.icon-delete"
|
||||
);
|
||||
await iconDelete[0].click();
|
||||
|
||||
/**
|
||||
* Delete confirmation modal.
|
||||
*/
|
||||
await confirmModal("Are you sure", adminPage);
|
||||
|
||||
await expect(
|
||||
adminPage.getByText("Type deleted successfully.")
|
||||
).toBeVisible();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,36 @@
|
||||
import { test, expect } from "../../../setup";
|
||||
import { generateFullName, generateDescription } from "../../../utils/faker";
|
||||
|
||||
test.describe("group management", () => {
|
||||
test("should create a group", async ({ adminPage }) => {
|
||||
/**
|
||||
* Reaching to the group listing page.
|
||||
*/
|
||||
await adminPage.goto("admin/settings/groups");
|
||||
|
||||
/**
|
||||
* Opening create group form in modal.
|
||||
*/
|
||||
await adminPage.getByRole("button", { name: "Create group" }).click();
|
||||
|
||||
|
||||
/**
|
||||
* Filling the form with group details.
|
||||
*/
|
||||
await adminPage
|
||||
.locator('input[name="name"]')
|
||||
.fill(generateFullName());
|
||||
await adminPage
|
||||
.locator('textarea[name="description"]')
|
||||
.fill(generateDescription(240));
|
||||
|
||||
/**
|
||||
* Save group and close the modal.
|
||||
*/
|
||||
await adminPage.getByRole("button", { name: "Save Group" }).click();
|
||||
|
||||
await expect(
|
||||
adminPage.getByText("Group created successfully.")
|
||||
).toBeVisible();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,227 @@
|
||||
import { test, expect } from "../../../setup";
|
||||
import {
|
||||
generateFullName,
|
||||
generateEmail,
|
||||
generateDescription,
|
||||
} from "../../../utils/faker";
|
||||
import { confirmModal } from "../../../utils/components";
|
||||
|
||||
async function createGroup(adminPage) {
|
||||
/**
|
||||
* Navigate to the group listing page.
|
||||
*/
|
||||
await adminPage.goto("admin/settings/groups");
|
||||
|
||||
/**
|
||||
* Open the create group form in modal.
|
||||
*/
|
||||
await adminPage.getByRole("button", { name: "Create group" }).click();
|
||||
|
||||
/**
|
||||
* Generate group name and fill in the form with group details.
|
||||
*/
|
||||
const groupName = generateFullName();
|
||||
await adminPage.locator('input[name="name"]').fill(groupName);
|
||||
await adminPage
|
||||
.locator('textarea[name="description"]')
|
||||
.fill(generateDescription(240));
|
||||
|
||||
/**
|
||||
* Save the group and close the modal.
|
||||
*/
|
||||
await adminPage.getByRole("button", { name: "Save Group" }).click();
|
||||
|
||||
/**
|
||||
* Validate successful creation.
|
||||
*/
|
||||
await expect(
|
||||
adminPage.getByText("Group created successfully.")
|
||||
).toBeVisible();
|
||||
|
||||
return { groupName };
|
||||
}
|
||||
|
||||
test.describe("user management", () => {
|
||||
test("should create a user with global permission", async ({ adminPage }) => {
|
||||
/**
|
||||
* Reaching to the user listing page.
|
||||
*/
|
||||
await adminPage.goto("admin/settings/users");
|
||||
|
||||
/**
|
||||
* Opening create user form in modal.
|
||||
*/
|
||||
await adminPage.getByRole("button", { name: "Create User" }).click();
|
||||
|
||||
/**
|
||||
* Filling the form with user details.
|
||||
*/
|
||||
await adminPage.locator('input[name="name"]').fill(generateFullName());
|
||||
await adminPage.locator('input[name="email"]').fill(generateEmail());
|
||||
await adminPage.locator('input[name="password"]').fill("admin123");
|
||||
await adminPage
|
||||
.locator('input[name="confirm_password"]')
|
||||
.fill("admin123");
|
||||
await adminPage.locator('select[name="role_id"]').selectOption("1");
|
||||
await adminPage
|
||||
.locator('select[name="view_permission"]')
|
||||
.selectOption("global");
|
||||
|
||||
/**
|
||||
* Clicking on the status toggler to make the user active.
|
||||
*/
|
||||
await adminPage.click('label[for="status"]');
|
||||
|
||||
/**
|
||||
* Save user and close the modal.
|
||||
*/
|
||||
await adminPage.getByRole("button", { name: "Save User" }).click();
|
||||
|
||||
await expect(
|
||||
adminPage.getByText("User created successfully.")
|
||||
).toBeVisible();
|
||||
});
|
||||
|
||||
test("should create a user with group permission", async ({ adminPage }) => {
|
||||
/**
|
||||
* Creating a group to assign to the user.
|
||||
*/
|
||||
const name = await createGroup(adminPage);
|
||||
|
||||
/**
|
||||
* Reaching to the user listing page.
|
||||
*/
|
||||
await adminPage.goto("admin/settings/users");
|
||||
|
||||
/**
|
||||
* Opening create user form in modal.
|
||||
*/
|
||||
await adminPage.getByRole("button", { name: "Create User" }).click();
|
||||
|
||||
/**
|
||||
* Filling the form with user details.
|
||||
*/
|
||||
await adminPage.locator('input[name="name"]').fill(generateFullName());
|
||||
await adminPage.locator('input[name="email"]').fill(generateEmail());
|
||||
await adminPage.locator('input[name="password"]').fill("admin123");
|
||||
await adminPage
|
||||
.locator('input[name="confirm_password"]')
|
||||
.fill("admin123");
|
||||
await adminPage.locator('select[name="role_id"]').selectOption("1");
|
||||
await adminPage
|
||||
.locator('select[name="view_permission"]')
|
||||
.selectOption("group");
|
||||
await adminPage.getByRole('listbox').selectOption({ label: name.groupName });
|
||||
|
||||
/**
|
||||
* Clicking on the status toggler to make the user active.
|
||||
*/
|
||||
await adminPage.click('label[for="status"]');
|
||||
|
||||
/**
|
||||
* Save user and close the modal.
|
||||
*/
|
||||
await adminPage.getByRole("button", { name: "Save User" }).click();
|
||||
|
||||
await expect(
|
||||
adminPage.getByText("User created successfully.")
|
||||
).toBeVisible();
|
||||
});
|
||||
|
||||
test("should create a user with individual permission", async ({ adminPage }) => {
|
||||
/**
|
||||
* Reaching to the user listing page.
|
||||
*/
|
||||
await adminPage.goto("admin/settings/users");
|
||||
|
||||
/**
|
||||
* Opening create user form in modal.
|
||||
*/
|
||||
await adminPage.getByRole("button", { name: "Create User" }).click();
|
||||
|
||||
/**
|
||||
* Filling the form with user details.
|
||||
*/
|
||||
await adminPage.locator('input[name="name"]').fill(generateFullName());
|
||||
await adminPage.locator('input[name="email"]').fill(generateEmail());
|
||||
await adminPage.locator('input[name="password"]').fill("admin123");
|
||||
await adminPage
|
||||
.locator('input[name="confirm_password"]')
|
||||
.fill("admin123");
|
||||
await adminPage.locator('select[name="role_id"]').selectOption("1");
|
||||
await adminPage
|
||||
.locator('select[name="view_permission"]')
|
||||
.selectOption("individual");
|
||||
|
||||
/**
|
||||
* Clicking on the status toggler to make the user active.
|
||||
*/
|
||||
await adminPage.click('label[for="status"]');
|
||||
|
||||
/**
|
||||
* Save user and close the modal.
|
||||
*/
|
||||
await adminPage.getByRole("button", { name: "Save User" }).click();
|
||||
|
||||
await expect(
|
||||
adminPage.getByText("User created successfully.")
|
||||
).toBeVisible();
|
||||
});
|
||||
|
||||
test("should edit a users", async ({ adminPage }) => {
|
||||
/**
|
||||
* Generating new name and email for the user.
|
||||
*/
|
||||
const updatedName = generateFullName();
|
||||
const updatedEmail = generateEmail();
|
||||
|
||||
/**
|
||||
* Reaching to the user listing page.
|
||||
*/
|
||||
await adminPage.goto("admin/settings/users");
|
||||
|
||||
/**
|
||||
* Clicking on the edit button for the first user opens the modal.
|
||||
*/
|
||||
await adminPage.waitForSelector("span.cursor-pointer.icon-edit", {
|
||||
state: "visible",
|
||||
});
|
||||
const iconEdit = await adminPage.$$("span.cursor-pointer.icon-edit");
|
||||
await iconEdit[0].click();
|
||||
|
||||
await adminPage.locator('input[name="name"]').fill(updatedName);
|
||||
await adminPage.locator('input[name="email"]').fill(updatedEmail);
|
||||
|
||||
/**
|
||||
* Saving user and closing the modal.
|
||||
*/
|
||||
await adminPage.getByRole("button", { name: "Save User" }).click();
|
||||
await expect(adminPage.locator('#app')).toContainText("User updated successfully.");
|
||||
await expect(adminPage.locator("#app")).toContainText(updatedName);
|
||||
await expect(
|
||||
adminPage.getByRole("paragraph").filter({ hasText: updatedEmail })
|
||||
).toBeVisible();
|
||||
});
|
||||
|
||||
test("should delete a user", async ({ adminPage }) => {
|
||||
/**
|
||||
* Reaching to the user listing page.
|
||||
*/
|
||||
await adminPage.goto("admin/settings/users");
|
||||
|
||||
/**
|
||||
* Delete the first user.
|
||||
*/
|
||||
await adminPage.waitForSelector("span.cursor-pointer.icon-delete");
|
||||
const iconDelete = await adminPage.$$(
|
||||
"span.cursor-pointer.icon-delete"
|
||||
);
|
||||
await iconDelete[0].click();
|
||||
|
||||
/**
|
||||
* Delete confirmation modal.
|
||||
*/
|
||||
await confirmModal("Are you sure", adminPage);
|
||||
await expect(adminPage.locator('#app')).toContainText("User deleted successfully.");
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,57 @@
|
||||
import { test, expect } from "../../../setup";
|
||||
import { confirmModal } from "../../../utils/components";
|
||||
|
||||
test.describe("warehouse management", () => {
|
||||
test("should create a warehouse", async ({ adminPage }) => {
|
||||
/**
|
||||
* Reaching to the warehouses listing page.
|
||||
*/
|
||||
await adminPage.goto("admin/settings/warehouses");
|
||||
|
||||
// Add code for creating a warehouse.
|
||||
|
||||
});
|
||||
|
||||
test("should edit a warehouse", async ({ adminPage }) => {
|
||||
/**
|
||||
* Reaching to the warehouses listing page.
|
||||
*/
|
||||
await adminPage.goto("admin/settings/warehouses");
|
||||
|
||||
/**
|
||||
* Clicking on the edit button for the first warehouse opens the modal.
|
||||
*/
|
||||
// await adminPage.waitForSelector("span.cursor-pointer.icon-edit", {
|
||||
// state: "visible",
|
||||
// });
|
||||
// const iconEdit = await adminPage.$$("span.cursor-pointer.icon-edit");
|
||||
// await iconEdit[0].click();
|
||||
|
||||
// Add code to edit the warehouse.
|
||||
});
|
||||
|
||||
test("should delete a warehouse", async ({ adminPage }) => {
|
||||
/**
|
||||
* Reaching to the warehouse listing page.
|
||||
*/
|
||||
await adminPage.goto("admin/settings/warehouses");
|
||||
|
||||
/**
|
||||
* Delete the first warehouse.
|
||||
*/
|
||||
// await adminPage.waitForSelector("span.cursor-pointer.icon-delete");
|
||||
// const iconDelete = await adminPage.$$(
|
||||
// "span.cursor-pointer.icon-delete"
|
||||
// );
|
||||
// await iconDelete[0].click();
|
||||
|
||||
// /**
|
||||
// * Delete confirmation modal.
|
||||
// */
|
||||
// await confirmModal("Are you sure", adminPage);
|
||||
|
||||
// await expect(
|
||||
// adminPage.getByText("Warehouse deleted successfully.")
|
||||
// ).toBeVisible();
|
||||
});
|
||||
});
|
||||
18
packages/Webkul/Admin/tests/e2e-pw/utils/components.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* Confirm the modal dialog.
|
||||
*/
|
||||
export function confirmModal(message, page) {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
await page.waitForSelector("text=" + message);
|
||||
const agreeButton = await page.locator(
|
||||
'button.primary-button:has-text("Agree")'
|
||||
);
|
||||
|
||||
if (await agreeButton.isVisible()) {
|
||||
await agreeButton.click();
|
||||
resolve(true);
|
||||
} else {
|
||||
reject("Agree button not found or not visible.");
|
||||
}
|
||||
});
|
||||
}
|
||||
471
packages/Webkul/Admin/tests/e2e-pw/utils/faker.ts
Normal file
@@ -0,0 +1,471 @@
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
|
||||
const usedNames = new Set();
|
||||
const usedEmails = new Set();
|
||||
const usedNumbers = new Set();
|
||||
const usedSlugs = new Set();
|
||||
|
||||
/**
|
||||
* Generate a random name.
|
||||
*/
|
||||
function generateName() {
|
||||
const adjectives = [
|
||||
"Cool", "Smart", "Fast", "Sleek", "Innovative", "Shiny", "Bold",
|
||||
"Elegant", "Epic", "Mystic", "Brilliant", "Luminous", "Radiant",
|
||||
"Majestic", "Vivid", "Glowing", "Dynamic", "Fearless", "Silent",
|
||||
"Electric", "Golden", "Blazing", "Timeless", "Noble", "Eternal"
|
||||
];
|
||||
|
||||
const nouns = [
|
||||
"Star", "Vision", "Echo", "Spark", "Horizon", "Nova", "Shadow",
|
||||
"Wave", "Pulse", "Vortex", "Zenith", "Element", "Flare", "Comet",
|
||||
"Galaxy", "Ember", "Crystal", "Sky", "Stone", "Blaze", "Eclipse",
|
||||
"Storm", "Orbit", "Phantom", "Mirage"
|
||||
];
|
||||
|
||||
let name = "";
|
||||
|
||||
do {
|
||||
const adj = adjectives[Math.floor(Math.random() * adjectives.length)];
|
||||
const noun = nouns[Math.floor(Math.random() * nouns.length)];
|
||||
|
||||
name = `${adj} ${noun}`;
|
||||
} while (usedNames.has(name));
|
||||
|
||||
usedNames.add(name);
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the first Name.
|
||||
*/
|
||||
function generateFirstName() {
|
||||
const firstNames = [
|
||||
"James",
|
||||
"Emma",
|
||||
"Liam",
|
||||
"Olivia",
|
||||
"Noah",
|
||||
"Ava",
|
||||
"William",
|
||||
"Sophia",
|
||||
"Benjamin",
|
||||
"Isabella",
|
||||
"Lucas",
|
||||
"Mia",
|
||||
];
|
||||
|
||||
return firstNames[Math.floor(Math.random() * firstNames.length)];
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the last name.
|
||||
*/
|
||||
function generateLastName() {
|
||||
const lastNames = [
|
||||
"Smith",
|
||||
"Johnson",
|
||||
"Brown",
|
||||
"Williams",
|
||||
"Jones",
|
||||
"Garcia",
|
||||
"Miller",
|
||||
"Davis",
|
||||
"Rodriguez",
|
||||
"Martinez",
|
||||
"Hernandez",
|
||||
"Lopez",
|
||||
];
|
||||
|
||||
return lastNames[Math.floor(Math.random() * lastNames.length)];
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the full name.
|
||||
*/
|
||||
function generateFullName() {
|
||||
return `${generateFirstName()} ${generateLastName()}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the email address.
|
||||
*/
|
||||
function generateEmail() {
|
||||
const adjectives = [
|
||||
"Cool",
|
||||
"Smart",
|
||||
"Fast",
|
||||
"Sleek",
|
||||
"Innovative",
|
||||
"Shiny",
|
||||
"Bold",
|
||||
"Elegant",
|
||||
"Epic",
|
||||
"Mystic",
|
||||
"Brilliant",
|
||||
"Luminous",
|
||||
];
|
||||
|
||||
const nouns = [
|
||||
"Star",
|
||||
"Vision",
|
||||
"Echo",
|
||||
"Spark",
|
||||
"Horizon",
|
||||
"Nova",
|
||||
"Shadow",
|
||||
"Wave",
|
||||
"Pulse",
|
||||
"Vortex",
|
||||
"Zenith",
|
||||
"Element",
|
||||
];
|
||||
|
||||
let email = "";
|
||||
|
||||
do {
|
||||
const adj = adjectives[Math.floor(Math.random() * adjectives.length)];
|
||||
const noun = nouns[Math.floor(Math.random() * nouns.length)];
|
||||
const number = Math.floor(1000 + Math.random() * 9000);
|
||||
|
||||
email = `${adj}${noun}${number}@example.com`.toLowerCase();
|
||||
} while (usedEmails.has(email));
|
||||
|
||||
usedEmails.add(email);
|
||||
|
||||
return email;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the phone number.
|
||||
*/
|
||||
function generatePhoneNumber() {
|
||||
let phoneNumber;
|
||||
|
||||
do {
|
||||
phoneNumber = Math.floor(6000000000 + Math.random() * 4000000000);
|
||||
} while (usedNumbers.has(phoneNumber));
|
||||
|
||||
usedNumbers.add(phoneNumber);
|
||||
|
||||
return `${phoneNumber}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a random SKU.
|
||||
*/
|
||||
function generateSKU() {
|
||||
const letters = Array.from({ length: 3 }, () =>
|
||||
String.fromCharCode(65 + Math.floor(Math.random() * 26))
|
||||
).join("");
|
||||
|
||||
const numbers = Math.floor(1000 + Math.random() * 9000);
|
||||
|
||||
return `${letters}${numbers}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a random URL.
|
||||
*/
|
||||
function generateSlug(delimiter = "-") {
|
||||
let slug;
|
||||
|
||||
do {
|
||||
const name = generateName();
|
||||
|
||||
const randomStr = Math.random().toString(36).substring(2, 8);
|
||||
|
||||
slug = `${name
|
||||
.toLowerCase()
|
||||
.replace(/\s+/g, delimiter)}${delimiter}${randomStr}`;
|
||||
} while (usedSlugs.has(slug));
|
||||
|
||||
usedSlugs.add(slug);
|
||||
|
||||
return slug;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a random email subject.
|
||||
*/
|
||||
function generateEmailSubject() {
|
||||
const subjects = [
|
||||
"Exciting news just for you!",
|
||||
"Don't miss out on this opportunity!",
|
||||
"Limited time offer – act now!",
|
||||
"An exclusive deal awaits you!",
|
||||
"Your next big opportunity is here!",
|
||||
"Something special just for you!",
|
||||
"Unlock amazing benefits today!",
|
||||
"Surprise! A special gift inside!",
|
||||
"This could change everything for you!",
|
||||
"You're invited to something amazing!",
|
||||
"Get ready for a game-changing experience!",
|
||||
"Hurry! This offer won't last long!",
|
||||
"A deal you simply can’t resist!",
|
||||
"Exclusive access – only for you!",
|
||||
"We’ve got something exciting for you!",
|
||||
"Your perfect opportunity is here!",
|
||||
"Important update – check this out!",
|
||||
"Discover what’s waiting for you!",
|
||||
"A limited-time surprise for you!",
|
||||
"Special invitation – don’t miss out!",
|
||||
];
|
||||
|
||||
return subjects[Math.floor(Math.random() * subjects.length)];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generate the description.
|
||||
*/
|
||||
function generateDescription(length = 255) {
|
||||
const phrases = [
|
||||
"An innovative and sleek design.",
|
||||
"Built for speed and efficiency.",
|
||||
"Experience the future today.",
|
||||
"A perfect blend of style and power.",
|
||||
"Engineered to perfection.",
|
||||
"Designed for those who dream big.",
|
||||
"Unleash creativity with this masterpiece.",
|
||||
"A game-changer in every way.",
|
||||
"Smart, fast, and reliable.",
|
||||
"The perfect companion for your journey.",
|
||||
"Crafted with precision and excellence.",
|
||||
"Innovation that redefines possibilities.",
|
||||
"Enhancing your experience like never before.",
|
||||
"Where technology meets elegance.",
|
||||
"Power, performance, and perfection combined.",
|
||||
"Redefining the way you experience the world.",
|
||||
"A masterpiece of engineering and design.",
|
||||
"Unmatched quality and exceptional performance.",
|
||||
"Designed to elevate your lifestyle.",
|
||||
"Beyond expectations, beyond limits.",
|
||||
];
|
||||
|
||||
let description = "";
|
||||
|
||||
while (length > 0) {
|
||||
let phrase = phrases[Math.floor(Math.random() * phrases.length)];
|
||||
|
||||
if (phrase.length <= length) {
|
||||
description += (description ? " " : "") + phrase;
|
||||
length -= phrase.length;
|
||||
} else {
|
||||
description += " " + phrase.substring(0, length);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return description.trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the host name.
|
||||
*/
|
||||
function generateHostname() {
|
||||
const words = [
|
||||
"tech",
|
||||
"cloud",
|
||||
"byte",
|
||||
"stream",
|
||||
"nexus",
|
||||
"core",
|
||||
"pulse",
|
||||
"data",
|
||||
"sync",
|
||||
"wave",
|
||||
"hub",
|
||||
"zone",
|
||||
];
|
||||
|
||||
const domains = [".com", ".net", ".io", ".ai", ".xyz", ".co"];
|
||||
|
||||
const part1 = words[Math.floor(Math.random() * words.length)];
|
||||
const part2 = words[Math.floor(Math.random() * words.length)];
|
||||
const domain = domains[Math.floor(Math.random() * domains.length)];
|
||||
|
||||
return `https://${part1}${part2}${domain}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a random element from the array.
|
||||
*/
|
||||
function randomElement(array) {
|
||||
return array[Math.floor(Math.random() * array.length)];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a random image file from the directory.
|
||||
*/
|
||||
function getImageFile(
|
||||
directory = path.resolve(__dirname, "../data/images/")
|
||||
) {
|
||||
if (!fs.existsSync(directory)) {
|
||||
throw new Error(`Directory does not exist: ${directory}`);
|
||||
}
|
||||
|
||||
const files = fs.readdirSync(directory);
|
||||
const imageFiles = files.filter((file) =>
|
||||
/\.(gif|jpeg|jpg|png|svg|webp)$/i.test(file)
|
||||
);
|
||||
|
||||
if (!imageFiles.length) {
|
||||
throw new Error("No image files found in the directory.");
|
||||
}
|
||||
|
||||
const randomIndex = Math.floor(Math.random() * imageFiles.length);
|
||||
|
||||
return path.join(directory, imageFiles[randomIndex]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a random date from today onwards in YYYY-MM-DD format.
|
||||
*/
|
||||
function generateDate(): string {
|
||||
const today = new Date().getTime();
|
||||
const futureEnd = new Date(2030, 11, 31).getTime();
|
||||
const randomDate = new Date(today + Math.random() * (futureEnd - today));
|
||||
|
||||
return randomDate.toISOString().split('T')[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to generate a random company name
|
||||
*/
|
||||
function generateCompanyName() {
|
||||
const prefixes = [
|
||||
"Tech", "Software", "Innovate", "NextGen", "Cloud", "AI", "Cyber", "Digital",
|
||||
"Technical", "Product", "Organization", "Vendor", "Rock-on", "Super", "Quantum",
|
||||
"Neural", "Hyper", "Ultra", "Smart", "Future", "Mega", "Omni", "Virtual", "Dynamic",
|
||||
"Secure", "Data", "Meta", "Nano", "Robo", "Infinity", "Vision", "Intelli", "Strato",
|
||||
"Blue", "Green", "Red", "White", "Black", "Deep", "Elite", "Prime", "Titan", "Nova",
|
||||
"Storm", "Lightning", "Vertex", "Pioneer", "Omnis", "Synergy", "Core", "Nexus"
|
||||
];
|
||||
const suffixes = [
|
||||
"Solutions", "Systems", "Pvt Ltd", "Technologies", "Enterprises", "Labs", "Networks",
|
||||
"Corporation", "Group", "Ventures", "Holdings", "Consulting", "Industries", "Analytics",
|
||||
"Innovations", "Services", "Softwares", "Developers", "AI", "Cloud", "Security", "Dynamics",
|
||||
"Technica", "Data", "Infotech", "Research", "Automation", "Synergy", "Strategies", "Platform",
|
||||
"Operations", "Logistics", "Infrastructure", "Management", "Digital", "Interactive",
|
||||
"Vision", "Connect", "Smart", "Solutions Inc", "Partners", "Tech Ltd", "Info Systems",
|
||||
"Growth", "Intelligence", "RoboCorp", "Edge", "Enterprise", "Global", "Power", "NextGen",
|
||||
"Creative"
|
||||
];
|
||||
return `${prefixes[Math.floor(Math.random() * prefixes.length)]} ${suffixes[Math.floor(Math.random() * suffixes.length)]}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to automate organization creation
|
||||
*/
|
||||
async function createOrganization(page) {
|
||||
const companyName = generateCompanyName();
|
||||
|
||||
/**
|
||||
* Click on "Create Organization" button
|
||||
*/
|
||||
await page.goto('admin/contacts/organizations');
|
||||
await page.getByRole('link', { name: 'Create Organization' }).click();
|
||||
|
||||
/**
|
||||
* Fill in organization details
|
||||
*/
|
||||
await page.getByRole('textbox', { name: 'Name *' }).fill(companyName);
|
||||
await page.locator('textarea[name="address\\[address\\]"]').fill('ARV Park');
|
||||
await page.getByRole('combobox').selectOption('IN');
|
||||
await page.locator('select[name="address\\[state\\]"]').selectOption('DL');
|
||||
await page.getByRole('textbox', { name: 'City' }).fill('Delhi');
|
||||
await page.getByRole('textbox', { name: 'Postcode' }).fill('123456');
|
||||
|
||||
/**
|
||||
* Click to add extra details
|
||||
*/
|
||||
await page.locator('div').filter({ hasText: /^Click to add$/ }).nth(2).click();
|
||||
await page.getByRole('textbox', { name: 'Search...' }).fill('exampl');
|
||||
await page.getByRole('listitem').filter({ hasText: 'Example' }).click();
|
||||
|
||||
/**
|
||||
* Click on "Save Organization"
|
||||
*/
|
||||
await page.getByRole('button', { name: 'Save Organization' }).click();
|
||||
// await expect(page.getByText(companyName)).toBeVisible();
|
||||
return companyName;
|
||||
}
|
||||
|
||||
function generateJobProfile() {
|
||||
const jobProfiles = [
|
||||
"Playwright Automation Tester",
|
||||
"Software Engineer",
|
||||
"Data Analyst",
|
||||
"Project Manager",
|
||||
"DevOps Engineer",
|
||||
"QA Engineer",
|
||||
"UI/UX Designer",
|
||||
"Product Manager",
|
||||
"Cybersecurity Analyst",
|
||||
"Cloud Architect"
|
||||
];
|
||||
const randomIndex = Math.floor(Math.random() * jobProfiles.length);
|
||||
return jobProfiles[randomIndex];
|
||||
}
|
||||
|
||||
async function createPerson(page) {
|
||||
const Name = generateFullName();
|
||||
const email = generateEmail();
|
||||
const phone = generatePhoneNumber();
|
||||
const Job = generateJobProfile();
|
||||
|
||||
await page.getByRole('link', { name: 'Create Person' }).click();
|
||||
|
||||
await page.getByRole('textbox', { name: 'Name *' }).fill(Name);
|
||||
await page.getByRole('textbox', { name: 'Emails *' }).fill(email);
|
||||
await page.getByRole('textbox', { name: 'Contact Numbers' }).fill(phone);
|
||||
await page.getByRole('textbox', { name: 'Job Title' }).fill(Job);
|
||||
|
||||
// Select an organization
|
||||
await page.locator('.relative > div > .relative').first().click();
|
||||
await page.getByRole('textbox', { name: 'Search...' }).fill('examp');
|
||||
await page.getByRole('listitem').filter({ hasText: 'Example' }).click();
|
||||
|
||||
// Save person
|
||||
await page.getByRole('button', { name: 'Save Person' }).click();
|
||||
|
||||
return { Name, email, phone };
|
||||
}
|
||||
function getRandomDateTime() {
|
||||
const year = Math.floor(Math.random() * (2030 - 2020 + 1)) + 2020;
|
||||
const month = String(Math.floor(Math.random() * 12) + 1).padStart(2, '0');
|
||||
const day = String(Math.floor(Math.random() * 28) + 1).padStart(2, '0');
|
||||
const hours = String(Math.floor(Math.random() * 24)).padStart(2, '0');
|
||||
const minutes = String(Math.floor(Math.random() * 60)).padStart(2, '0');
|
||||
const seconds = String(Math.floor(Math.random() * 60)).padStart(2, '0');
|
||||
|
||||
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
||||
}
|
||||
|
||||
export {
|
||||
generateName,
|
||||
generateFirstName,
|
||||
generateLastName,
|
||||
generateFullName,
|
||||
generateEmail,
|
||||
generatePhoneNumber,
|
||||
generateSKU,
|
||||
generateSlug,
|
||||
generateEmailSubject,
|
||||
generateDescription,
|
||||
generateHostname,
|
||||
randomElement,
|
||||
getImageFile,
|
||||
generateDate,
|
||||
createOrganization,
|
||||
generateCompanyName,
|
||||
createPerson,
|
||||
getRandomDateTime
|
||||
};
|
||||