add: full multi-tenancy control

This commit is contained in:
Cauê Faleiros
2026-02-02 15:31:15 -03:00
commit c6ec92802b
1711 changed files with 258106 additions and 0 deletions

View File

@@ -0,0 +1,2 @@
/playwright-report
/test-results

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 242 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

View 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"] },
},
],
});

View 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 };

View 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();
});

View File

@@ -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.');
});
});

View File

@@ -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");
});

View 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');
}
});

View 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();
});
});

View File

@@ -0,0 +1 @@
import { test, expect } from "../../setup";

View 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);
});
});

View File

@@ -0,0 +1 @@
import { test, expect } from "../../setup";

View File

@@ -0,0 +1 @@
import { test, expect } from "../../setup";

View File

@@ -0,0 +1 @@
import { test, expect } from "../../setup";

View 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."
);
});
});

View 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");
});
});

View File

@@ -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();
});
});

View File

@@ -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();
});
});

View File

@@ -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();
});
});

View File

@@ -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.");
});
});

View File

@@ -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();
});
});

View 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.");
}
});
}

View 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 cant resist!",
"Exclusive access only for you!",
"Weve got something exciting for you!",
"Your perfect opportunity is here!",
"Important update check this out!",
"Discover whats waiting for you!",
"A limited-time surprise for you!",
"Special invitation dont 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
};