Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
yuri-spizhovyi-mit committed Sep 23, 2024
1 parent 136f471 commit fc9ae37
Show file tree
Hide file tree
Showing 24 changed files with 2,700 additions and 616 deletions.
123 changes: 112 additions & 11 deletions fixtures.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,113 @@
import { test as base, expect, BrowserContext } from "@playwright/test";
import { userAgents } from "./utils/useragents";
import {
userAgents,
desktopViewports,
iphoneViewports,
androidViewports,
ipadViewports,
androidTabletViewports,
} from "./utils/useragents"; // Import user agents and viewports
import { getRandomUserAgentAndViewport } from "./utils/useragents";
import { getRandomLocation } from "./utils/geolocation";

type TestFixtures = {
context: BrowserContext;
page: import("@playwright/test").Page;
};

export const test = base.extend<TestFixtures>({
// Override the context fixture to use a random user agent
// Override the context fixture to use a random user agent and viewport
context: async ({ browser }, use, testInfo) => {
// Select a random user agent
const randomUserAgent =
userAgents[Math.floor(Math.random() * userAgents.length)];
// Generate a random probability between 0.65 and 0.8 for mobile devices
const mobileProbability = Math.random() * (0.8 - 0.65) + 0.65;

// Log the user agent
// Choose whether to use mobile or desktop/laptop based on the random probability
const isMobile = Math.random() < mobileProbability;

// Select a random user agent based on the chosen device type
let randomAgent;
if (isMobile) {
randomAgent = userAgents.filter((agent) => agent.deviceType === "mobile")[
Math.floor(
Math.random() *
userAgents.filter((agent) => agent.deviceType === "mobile").length
)
];
} else {
randomAgent = userAgents.filter(
(agent) =>
agent.deviceType === "desktop" || agent.deviceType === "laptop"
)[
Math.floor(
Math.random() *
userAgents.filter(
(agent) =>
agent.deviceType === "desktop" || agent.deviceType === "laptop"
).length
)
];
}

// Log the user agent being used
console.log(
`Test "${testInfo.title}" is using User Agent: ${randomUserAgent}`
`Test "${testInfo.title}" is using User Agent: ${randomAgent.userAgent} with Mobile Probability: ${mobileProbability}`
);

// Create a new browser context with the random user agent
// Determine the viewport based on the device type
let viewport;
if (
randomAgent.deviceType === "desktop" ||
randomAgent.deviceType === "laptop"
) {
// Randomly select a viewport from the desktop/laptop viewports
viewport =
desktopViewports[Math.floor(Math.random() * desktopViewports.length)];
} else if (randomAgent.deviceType === "mobile") {
// Select mobile viewport based on the device (iPhone or Android)
if (randomAgent.userAgent.includes("iPhone")) {
viewport =
iphoneViewports[Math.floor(Math.random() * iphoneViewports.length)];
} else {
viewport =
androidViewports[Math.floor(Math.random() * androidViewports.length)];
}
} else if (randomAgent.deviceType === "tablet") {
// Further distinguish between iPad and Android tablets
if (randomAgent.tabletType === "ipad") {
viewport =
ipadViewports[Math.floor(Math.random() * ipadViewports.length)];
} else {
viewport =
androidTabletViewports[
Math.floor(Math.random() * androidTabletViewports.length)
];
}
}

// Ensure that a viewport was found, if not, throw an error
if (!viewport) {
throw new Error(
`No viewport found for the user agent: ${randomAgent.userAgent}`
);
}

// Log the selected viewport
console.log(`Using viewport: ${JSON.stringify(viewport)}`);

// Create a new browser context with the selected user agent and viewport
const context = await browser.newContext({
userAgent: randomUserAgent,
userAgent: randomAgent.userAgent,
viewport,
});

// Use the context in tests
await use(context);

// Clean up
// Clean up the context
await context.close();
},

// Override the page fixture to use the context with the random user agent
// Override the page fixture to use the context with the random user agent and viewport
page: async ({ context }, use) => {
const page = await context.newPage();
await use(page);
Expand All @@ -39,3 +116,27 @@ export const test = base.extend<TestFixtures>({
});

export { expect };

// Helper to create a new context with random user agent, viewport, and geolocation
export async function createRandomContext(browser) {
// Get a random user agent and viewport
const { userAgent, viewport } = getRandomUserAgentAndViewport();

// Get a random location for geolocation
const location = getRandomLocation();

// Log the selected random values
console.log(`Selected User Agent: ${userAgent}`);
console.log(`Selected Viewport: ${JSON.stringify(viewport)}`);
console.log(
`Selected Geolocation: ${location.name}, Lat: ${location.lat}, Lon: ${location.lon}`
);

// Create a new browser context with geolocation, random user agent, and random viewport
return await browser.newContext({
geolocation: { latitude: location.lat, longitude: location.lon },
permissions: ["geolocation"], // Ensure geolocation permission is granted
viewport, // Set the random viewport
userAgent, // Set the random user agent
});
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"main": "index.js",
"scripts": {},
"keywords": [],
"type": "module",
"author": "",
"license": "ISC",
"description": "",
Expand Down
14 changes: 13 additions & 1 deletion pages/developer.page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ export class DeveloperPage {
.getByText("Contacts"),
private readonly maxWebStudioLink = page.getByRole("link", {
name: "maxweb.studio",
})
}),
// Hamburger menu locator for mobile view
private readonly developerHamburgerMenuButton = page.locator(
"button._navButton_4r0jz_51"
)
) {}

async navigateToAbout() {
Expand All @@ -31,4 +35,12 @@ export class DeveloperPage {
await this.maxWebStudioLink.click();
return page2Promise;
}

// Close the hamburger menu if it is visible (for mobile views)
async closeHamburgerMenuIfVisible() {
if (await this.developerHamburgerMenuButton.isVisible()) {
await this.developerHamburgerMenuButton.click();
await this.page.waitForTimeout(1000); // Optional delay for a smoother close interaction
}
}
}
38 changes: 17 additions & 21 deletions pages/googleSearch.page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,17 @@ import { Page } from "@playwright/test";
import * as timeGenerator from "../utils/timegenerator";

export class GoogleSearchPage {
constructor(
private readonly page: Page,
private readonly acceptCookiesButton = page.locator(
'button:has-text("I agree")'
),
private readonly searchInput = page.getByRole("combobox", {
name: "Search",
}),
private readonly notNowButton = page.locator(
'div[role="button"]:has-text("Not now")'
) // Updated locator for the "Not now" button
) {}
// Declare the locators as readonly properties
private readonly acceptCookiesButton;
private readonly searchInput;
private readonly notNowButton;

// Constructor to initialize the locators
constructor(private readonly page: Page) {
this.acceptCookiesButton = page.locator('button:has-text("I agree")');
this.searchInput = page.locator("textarea[name='q'], input[name='q']");
this.notNowButton = page.getByRole("button", { name: "Not now" });
}

async navigateToGoogle() {
await this.page.goto("https://www.google.com/");
Expand All @@ -40,18 +39,15 @@ export class GoogleSearchPage {
await this.page.waitForTimeout(timeGenerator.waitOneToThreeTime()); // Random delay after scrolling
}

// Dismiss the location popup if the "Not now" button is visible
async dismissLocationPopupIfVisible() {
try {
// Wait for up to 10 seconds for the "Not now" button to appear, then click it
await this.page.waitForSelector(
'div[role="button"]:has-text("Not now")',
{ timeout: 10000 }
);
console.log('Clicking "Not now" button.');
await this.notNowButton.click();
await this.page.waitForTimeout(timeGenerator.waitOneToThreeTime()); // Simulate delay after dismissing pop-up
if (await this.notNowButton.isVisible()) {
console.log('Clicking "Not now" button.');
await this.notNowButton.click();
await this.page.waitForTimeout(timeGenerator.waitOneToThreeTime()); // Simulate delay after dismissing pop-up
}
} catch (e) {
// If the button doesn't appear, we catch the timeout error and continue
console.log('"Not now" button did not appear, continuing.');
}
}
Expand Down
17 changes: 16 additions & 1 deletion pages/project.page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@ export class ProjectPage {
.getByRole("link"),
private readonly viewProjectLink = page.getByRole("link", {
name: "View Project",
})
}),
// Hamburger menu locator for mobile view
private readonly hamburgerMenuButton = page.locator(
"button._hamburger_15if9_13"
)
) {}

// Navigate to the Projects section
Expand Down Expand Up @@ -55,4 +59,15 @@ export class ProjectPage {
await this.viewProjectLink.click();
await this.page.waitForTimeout(timeGenerator.waitOneToThreeTime()); // Simulate delay between actions
}

// Close the hamburger menu if it is visible (for mobile views)
async closeHamburgerMenuIfVisible() {
if (await this.hamburgerMenuButton.isVisible()) {
console.log("Hamburger menu detected, closing it.");
await this.hamburgerMenuButton.click();
await this.page.waitForTimeout(timeGenerator.waitOneToThreeTime()); // Simulate human-like delay for menu closing
} else {
console.log("Hamburger menu not visible.");
}
}
}
57 changes: 57 additions & 0 deletions pages/project1.page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// /pages/project.page.ts

import { Page } from "@playwright/test";
import * as timeGenerator from "../utils/timegenerator";

export class ProjectPage {
constructor(
private readonly page: Page,
// Locators
private readonly allKitchensLink = page.getByText("All/Kitchens"),
private readonly allLink = page.getByRole("link", { name: "All" }),
private readonly projectLink = page.getByRole("link", { name: "Projects" }),
private readonly wardrobesLink = page.getByRole("link", {
name: "Wardrobes",
}),
private readonly kitchenProjectLink = (projectName: string) =>
page
.locator(`li:has-text("${projectName}View Project")`)
.getByRole("link"),
private readonly viewProjectLink = page.getByRole("link", {
name: "View Project",
}),
// Hamburger menu locator for mobile view
private readonly hamburgerMenuButton = page.locator(
"button._hamburger_15if9_13"
)
) {}

// Navigate to the Projects section
async navigateToProjects() {
await this.projectLink.click();
await this.page.waitForTimeout(timeGenerator.waitOneToThreeTime()); // Simulate human-like delay
}

// Navigate to the "All Projects" section
async navigateToAllProjects() {
await this.allLink.click();
await this.page.waitForTimeout(timeGenerator.waitOneToThreeTime()); // Simulate delay
}

// Open a specific Kitchen project by its name
async openKitchenProject(projectName: string) {
await this.kitchenProjectLink(projectName).click();
await this.page.waitForTimeout(timeGenerator.waitOneToThreeTime());
}

// Close the hamburger menu if it is visible (for mobile views)
async closeHamburgerMenuIfVisible() {
if (await this.hamburgerMenuButton.isVisible()) {
console.log("Hamburger menu detected, closing it.");
await this.hamburgerMenuButton.click();
await this.page.waitForTimeout(timeGenerator.waitOneToThreeTime()); // Simulate human-like delay for menu closing
} else {
console.log("Hamburger menu not visible.");
}
}
}
Loading

0 comments on commit fc9ae37

Please sign in to comment.