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 all 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
53 changes: 27 additions & 26 deletions framework/Element.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,22 @@ 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) {
newChildElement(childSelector, childElementPage = page) {
var isXPathSlector = (selector) => selector.startsWith("//");
if (isXPathSlector(this.selector) != isXPathSlector(childSelector)) {
throw "Cannot combine different selectors types!";
}
return new Element(`${this.selector} ${childSelector}`);
return new Element(`${this.selector} ${childSelector}`, childElementPage);
}

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