Skip to content
This repository has been archived by the owner on Feb 3, 2023. It is now read-only.

20 add popups handling #117

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion example/tests/elementActions.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ describe("Element Actions", () => {
//Arrange
const expectedXCoordinate = 640; //width: default viewport 1280px / 2
const expectedYCoordinate = 25; //height: top bar 50px / 2
const rectangleCanvas = new Element(".top-bar__network._fixed");
const rectangleCanvas = new Element(".top-bar__network");
await page.goto("https://stackoverflow.com/users/login");

//Act
Expand Down
30 changes: 30 additions & 0 deletions example/tests/helpers.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,4 +95,34 @@ describe("Helpers", () => {
expect(regex.test(text)).toBeTruthy();
expect(text.length).toEqual(8);
});

it("should accept opened alerts", async () => {
//Arrange
const pageWithAcceptAlertsSetup = await browser.newPage();
await Helpers.acceptPopupsOnPage(pageWithAcceptAlertsSetup);
const resultElement = new Element("#result", pageWithAcceptAlertsSetup);

//Act
await pageWithAcceptAlertsSetup.goto("http://the-internet.herokuapp.com/javascript_alerts");
await pageWithAcceptAlertsSetup.click("button[onclick='jsAlert()']");
const resultElementText = await resultElement.text();

//Assert
expect(resultElementText).toMatch("You successfully clicked an alert");
});

it("should close opened alerts", async () => {
//Arrange
const pageWithDismissAlertsSetup = await browser.newPage();
await Helpers.dismissPopupsOnPage(pageWithDismissAlertsSetup);
const resultElement = new Element("#result", pageWithDismissAlertsSetup);

//Act
await pageWithDismissAlertsSetup.goto("http://the-internet.herokuapp.com/javascript_alerts");
await pageWithDismissAlertsSetup.click("button[onclick='jsAlert()']");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are two lint issues:
C:\source\test-juggler\example\tests\helpers.test.js
107:1 error Mixed spaces and tabs no-mixed-spaces-and-tabs
122:1 error Mixed spaces and tabs no-mixed-spaces-and-tabs

✖ 2 problems (2 errors, 0 warnings)

const resultElementText = await resultElement.text();

//Assert
expect(resultElementText).toMatch("You successfully clicked an alert");
});
});
33 changes: 20 additions & 13 deletions example/tests/interceptor.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,30 @@ import { Element, Interceptor } from "test-juggler";

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 tests are failing in interceptor suite:

  Interceptor
    √ should block requests by any url fragment using Regex pattern while test case running (7423 ms)
    √ should block requests by any url fragment using Glob pattern after abort method is used (3831 ms)
    √ should block request by any url fragment after action (3455 ms)
    × should block any request after action (30176 ms)
    √ should count all requests (368 ms)
    × should detect specific response after action (30182 ms)
    × should detect any request after action (3 ms)

const DemoQaSite = "https://demoqa.com/books";
const DemoOpenCartSite = "https://demo.opencart.com/";
const successMessage = new Element(".alert-success");
const addToCartButton = new Element(".product-layout:nth-child(1) > div button:nth-child(1)");
const loadingWrapper = new Element("#loading-wrapper");
const booksWrapper = new Element(".books-wrapper");
let page;
let successMessage;
let addToCartButton;
let loadingWrapper;
let booksWrapper;
let interceptor;

describe("Interceptor", () => {
beforeEach(async () => {
console.log(`Running test: '${jasmine["currentTest"].fullName}'`);
//this is workaraound to avoid 'Request is already handled!' error. Shoud be removed when https://github.com/smooth-code/jest-puppeteer/issues/308 defect is fixed.
const context = await browser.newContext();
page = await context.newPage();
successMessage = new Element(".alert-success", page);
addToCartButton = new Element(".product-layout:nth-child(1) > div button:nth-child(1)", page);
loadingWrapper = new Element("#loading-wrapper", page);
booksWrapper = new Element(".books-wrapper", page);
interceptor = new Interceptor(page);
});

it("should block requests by any url fragment using Regex pattern while test case running", async () => {
//Arrange
const requestUrlRegex = /BookStore/;
await Interceptor.abortRequests(requestUrlRegex);
await interceptor.abortRequests(requestUrlRegex);

//Act
await page.goto(DemoQaSite);
Expand All @@ -41,13 +48,13 @@ describe("Interceptor", () => {

//Act
await page.goto(DemoQaSite);
await loadingWrapper.waitUntilInvisible();
await booksWrapper.waitUntilVisible();

//Assert
await expect(booksWrapper.exists()).resolves.toBeTruthy();

//Act
await Interceptor.abortRequests(requestUrlGlob);
await interceptor.abortRequests(requestUrlGlob);
await page.reload();
await loadingWrapper.waitUntilVisible();

Expand All @@ -59,7 +66,7 @@ describe("Interceptor", () => {
//Arrange

const requestUrlGlob = "**/BookStore/**";
await Interceptor.abortRequestsAfterAction(page.goto(DemoQaSite), requestUrlGlob);
await interceptor.abortRequestsAfterAction(page.goto(DemoQaSite), requestUrlGlob);

//Assert
await loadingWrapper.waitUntilVisible();
Expand All @@ -69,7 +76,7 @@ describe("Interceptor", () => {

//Act
await page.reload();
await loadingWrapper.waitUntilInvisible();
await booksWrapper.waitUntilVisible();

//Assert
await expect(booksWrapper.exists()).resolves.toBeTruthy();
Expand All @@ -86,7 +93,7 @@ describe("Interceptor", () => {
});

//Act
await Interceptor.abortRequestsAfterAction(addToCartButton.click());
await interceptor.abortRequestsAfterAction(addToCartButton.click());

//Assert
await expect(successMessage.isVisible()).resolves.toBeFalsy();
Expand All @@ -95,7 +102,7 @@ describe("Interceptor", () => {

it("should count all requests", async () => {
//Act
var totalRequests = await Interceptor.getAllRequestsData(page.goto(DemoOpenCartSite));
var totalRequests = await interceptor.getAllRequestsData(page.goto(DemoOpenCartSite));

//Assert
expect(totalRequests.length > 0).toBeTruthy();
Expand All @@ -108,7 +115,7 @@ describe("Interceptor", () => {
await page.goto(DemoOpenCartSite);

//Act
var responseAfterAction = await Interceptor.waitForResponseAfterAction(addToCartButton.click(), responseUrlFragment);
var responseAfterAction = await interceptor.waitForResponseAfterAction(addToCartButton.click(), responseUrlFragment);

//Assert
await expect(successMessage.isVisible()).resolves.toBeTruthy();
Expand All @@ -122,7 +129,7 @@ describe("Interceptor", () => {
await page.goto(DemoOpenCartSite);

//Act
var requestAfterAction = await Interceptor.waitForRequestAfterAction(addToCartButton.click());
var requestAfterAction = await interceptor.waitForRequestAfterAction(addToCartButton.click());

//Assert
await expect(successMessage.isVisible()).resolves.toBeTruthy();
Expand Down
49 changes: 25 additions & 24 deletions framework/Element.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ const defaultTimeout = config.defaultTimeout;
const shortTimeout = config.shortTimeout;

export default class Element {
constructor(selector) {
this.selector = selector;
constructor(selector, elementPage = page) {
this.selector = selector,
this.page = elementPage
}

newChildElement(childSelector) {
Expand All @@ -20,7 +21,7 @@ export default class Element {

async wait(timeout = defaultTimeout) {
console.log(`Waiting for ${this.selector} ...`);
const elementHandle = await page.waitForSelector(this.selector, { timeout: timeout });
const elementHandle = await this.page.waitForSelector(this.selector, { timeout: timeout });
if (config.captureScreenshots) {
await Helpers.takeScreenshot();
}
Expand All @@ -29,7 +30,7 @@ export default class Element {

async waitUntilVisible(timeout = defaultTimeout) {
console.log(`Waiting for ${this.selector} to be visible...`);
const elementHandle = await page.waitForSelector(this.selector, { state: "visible", timeout: timeout });
const elementHandle = await this.page.waitForSelector(this.selector, { state: "visible", timeout: timeout });
if (config.captureScreenshots) {
await Helpers.takeScreenshot();
}
Expand All @@ -38,7 +39,7 @@ export default class Element {

async waitUntilInvisible(timeout = defaultTimeout) {
console.log(`Waiting for ${this.selector} to be invisible...`);
await page.waitForSelector(this.selector, { state: "hidden", timeout: timeout });
await this.page.waitForSelector(this.selector, { state: "hidden", timeout: timeout });
if (config.captureScreenshots) {
await Helpers.takeScreenshot();
}
Expand All @@ -58,36 +59,36 @@ export default class Element {
console.log(`Clicking ${this.selector} ...`);
if (xOffset != null || yOffset != null) {
const coordinates = await this.getCoordinates(xOffset, yOffset);
await page.click(this.selector, { position: { x: coordinates.x, y: coordinates.y } });
await this.page.click(this.selector, { position: { x: coordinates.x, y: coordinates.y } });
}
else await page.click(this.selector);
else await this.page.click(this.selector);
}

async doubleClick(xOffset = null, yOffset = null) {
console.log(`Double clicking ${this.selector} ...`);
if (xOffset != null || yOffset != null) {
const coordinates = await this.getCoordinates(xOffset, yOffset);
await page.dblclick(this.selector, { position: { x: coordinates.x, y: coordinates.y } });
await this.page.dblclick(this.selector, { position: { x: coordinates.x, y: coordinates.y } });
}
else await page.dblclick(this.selector);
else await this.page.dblclick(this.selector);
}

async rightClick(xOffset = null, yOffset = null) {
console.log(`Right clicking ${this.selector} ...`);
if (xOffset != null || yOffset != null) {
const coordinates = await this.getCoordinates(xOffset, yOffset);
await page.click(this.selector, { position: { x: coordinates.x, y: coordinates.y }, button: "right" } );
await this.page.click(this.selector, { position: { x: coordinates.x, y: coordinates.y }, button: "right" } );
}
else await page.click(this.selector, { button: "right" });
else await this.page.click(this.selector, { button: "right" });
}

async hover(xOffset = null, yOffset = null) {
console.log(`Hovering mouse on to ${this.selector} ...`);
if (xOffset != null || yOffset != null) {
const coordinates = await this.getCoordinates(xOffset, yOffset);
await page.hover(this.selector, { position: { x: coordinates.x, y: coordinates.y } });
await this.page.hover(this.selector, { position: { x: coordinates.x, y: coordinates.y } });
}
else await page.hover(this.selector);
else await this.page.hover(this.selector);
}

async exists() {
Expand Down Expand Up @@ -119,15 +120,15 @@ export default class Element {
}

async dragAndDrop(destination) {
const sourceElement = await page.waitForSelector(this.selector);
const destinationElement = await page.waitForSelector(destination.selector);
const sourceElement = await this.page.waitForSelector(this.selector);
const destinationElement = await this.page.waitForSelector(destination.selector);
const sourceBox = await sourceElement.boundingBox();
const destinationBox = await destinationElement.boundingBox();
console.log(`Drag and dropping ${this.selector} to ${destination.selector} ...`);
await page.mouse.move(sourceBox.x + sourceBox.width / 2, sourceBox.y + sourceBox.height / 2);
await page.mouse.down();
await page.mouse.move(destinationBox.x + destinationBox.width / 2, destinationBox.y + destinationBox.height / 2);
await page.mouse.up();
await this.page.mouse.move(sourceBox.x + sourceBox.width / 2, sourceBox.y + sourceBox.height / 2);
await this.page.mouse.down();
await this.page.mouse.move(destinationBox.x + destinationBox.width / 2, destinationBox.y + destinationBox.height / 2);
await this.page.mouse.up();
}

async text() {
Expand All @@ -153,10 +154,10 @@ export default class Element {
async clearText() {
console.log(`Clearing the text value for ${this.selector} ...`);
await this.click();
await page.keyboard.down("Control");
await page.keyboard.press("A");
await page.keyboard.up("Control");
await page.keyboard.press("Backspace");
await this.page.keyboard.down("Control");
await this.page.keyboard.press("A");
await this.page.keyboard.up("Control");
await this.page.keyboard.press("Backspace");
}

async takeScreenshot() {
Expand Down Expand Up @@ -216,7 +217,7 @@ export default class Element {
async downloadFile(filePath) {
if (!path.isAbsolute(filePath)) filePath = process.cwd().replace(/\\/g, "/") + filePath;
const [download] = await Promise.all([
page.waitForEvent("download"),
this.page.waitForEvent("download"),
this.click(),
]);
await download.saveAs(filePath);
Expand Down
14 changes: 14 additions & 0 deletions framework/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,20 @@ class Helpers {
console.log(`Generated a random text: ${result}`);
return result;
}

async acceptPopupsOnPage(page) {
await page.on("dialog", dialog => {
console.log(`Alert was detected: '${dialog.message()}'`);
dialog.accept();
});
}

async dismissPopupsOnPage(page) {
await page.on("dialog", dialog => {
console.log(`Alert was detected: '${dialog.message()}'`);
dialog.dismiss();
});
}
}

export default new Helpers();
23 changes: 13 additions & 10 deletions framework/interceptor.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
const fs = require("fs");

class Interceptor {
export default class Interceptor {
constructor(interceptorPage = page) {
this.page = interceptorPage
}

async takeScreenshot(filename) {
const targetDir = `./logs/${jasmine["currentSuite"].fullName}/${jasmine["currentTest"].description}`;
fs.mkdirSync(targetDir, { recursive: true });
await page.screenshot({ path: `${targetDir}/${filename || Date.now()}.png` });
await this.page.screenshot({ path: `${targetDir}/${filename || Date.now()}.png` });
}

async abortRequests(requestUrlFragment = "**") {
await page.route(requestUrlFragment, route => {
await this.page.route(requestUrlFragment, route => {
route.abort();
console.log(`Aborted request Url: '${route.request().url()}'`);
} );
Expand All @@ -17,34 +21,33 @@ class Interceptor {
async abortRequestsAfterAction(action, requestUrlFragment = "", waitDuration = 500) {
await this.abortRequests(requestUrlFragment);
await action;
await page.waitForTimeout(waitDuration);
await page.unroute(requestUrlFragment);
await this.page.waitForTimeout(waitDuration);
await this.page.unroute(requestUrlFragment);
}

async getAllRequestsData(action) {
let requestsData = [];
const requestLogger = request => {
requestsData.push(request);
};
page.on("request", requestLogger);
this.page.on("request", requestLogger);
await action;
page.removeListener("request", requestLogger);
this.page.removeListener("request", requestLogger);
return requestsData;
}

async waitForRequestAfterAction(action, requestUrlFragment = "") {
const requestAferAction = await page.waitForRequest(request => request.url().indexOf(requestUrlFragment) > -1);
const requestAferAction = await this.page.waitForRequest(request => request.url().indexOf(requestUrlFragment) > -1);
await action;
console.log(`Url: '${requestAferAction.url()}'`);
return requestAferAction;
}

async waitForResponseAfterAction(action, responsetUrlFragment = "") {
const responseAferAction = await page.waitForResponse(response => response.url().indexOf(responsetUrlFragment) > -1);
const responseAferAction = await this.page.waitForResponse(response => response.url().indexOf(responsetUrlFragment) > -1);
await action;
console.log(`Url: '${responseAferAction.url()}'`);
return responseAferAction;
}
}

export default new Interceptor();