Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Playwright test #51

Merged
merged 28 commits into from
Oct 18, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
f8f8a05
first commits
Philip-21 Sep 10, 2023
3c2d7ef
removing files
Philip-21 Sep 11, 2023
a53f549
Merge branch 'master' into playwright-test
Philip-21 Sep 11, 2023
42c1693
setup functions to be used for playwright tests
Philip-21 Sep 11, 2023
3b297a7
new setup functions and util functions
Philip-21 Sep 12, 2023
7bdbb5e
creating Api requests
Philip-21 Sep 14, 2023
d718774
refactoring fand adjusting helper functions
Philip-21 Sep 16, 2023
39b760b
new login test passed
Philip-21 Sep 16, 2023
abb1b1a
adding more tests
Philip-21 Sep 17, 2023
bf86152
redefining and adding setup functions
Philip-21 Sep 17, 2023
5e5666c
adding more setup functions
Philip-21 Sep 17, 2023
2d8c9b6
utility tests
Philip-21 Sep 17, 2023
39d8f24
reoving timeouts,declaring await where necessary
Philip-21 Sep 23, 2023
fd13965
switchng to typescript
Philip-21 Sep 27, 2023
dda9e6b
setting up playwright to capture snapshots
Philip-21 Sep 29, 2023
0c13af5
reasjusting and removing test files
Philip-21 Sep 29, 2023
9d37825
adjusting actions
Philip-21 Sep 29, 2023
3774444
taking of if statement
Philip-21 Sep 29, 2023
f94fb5d
commenting out cypress actions
Philip-21 Sep 29, 2023
005c6d2
working on playwright workflow
Philip-21 Sep 30, 2023
81cb704
creating new adir to upload artifacts
Philip-21 Sep 30, 2023
4f31aea
deining env var for appid
Philip-21 Sep 30, 2023
f1e584c
rewriting meshmapsnapshot test function
Philip-21 Oct 6, 2023
8245171
indicating playwright workflow properly
Philip-21 Oct 7, 2023
edac40f
removing branch refs
Philip-21 Oct 7, 2023
714a12f
Merge branch 'layer5labs:master' into playwright-test
Philip-21 Oct 14, 2023
8dfd266
reimplementing screenshots
Philip-21 Oct 18, 2023
a96a237
Merge branch 'playwright-test' of https://github.com/Philip-21/meshma…
Philip-21 Oct 18, 2023
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
8 changes: 5 additions & 3 deletions cypress-action/cypress/support/helpers.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { DESIGNER, extension, MESHMAP_PATH } from "./constants"


//utility func that return strings and id
export function waitFor(str) {
return "@" + str;
}
Expand All @@ -9,14 +9,16 @@ export function id(str) {
return "#" + str
}

//cypress setup capabilities
const doInitialSetup = () => {
cy.setViewPort();
cy.login();
cy.setReleaseTag();
cy.interceptCapabilities();
cy.interceptCapabilities();//intercept request to specific endpoint
cy.setMode(DESIGNER);
}

//a callback hook to perform actions before running individual tests
export const beforeEachCallback = () => {
doInitialSetup();
cy.intercept(extension.path).as(extension.alias);
Expand All @@ -30,7 +32,7 @@ export const beforeEachCallbackForCustomUrl = (customPath) => {
cy.visit(customPath);
cy.wait(waitFor(extension.alias), { timeout: 60_000 });
}

//captures meshmap graph screenshots and generates download link
export const saveGraph = (cy) => {
let image = cy.png();
let lnk = document.createElement("a"),
Expand Down
75 changes: 75 additions & 0 deletions playwright-action/helpers/constants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { id } from "./playwrightUtils.js";

export const DESIGNER = "designer"
export const VISUALIZER = "visualizer"

//Objects defining paths, aliases, and wait conditions for intercepting certain API requests.
export const extension = {
path: "/api/provider/extension*",
alias: "extensionFileLoad"
};

export const designEndpoint = {
path: "/api/pattern*",
alias: "designEp",
wait: "@designEp",
absolutePath: "/api/pattern"

Choose a reason for hiding this comment

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

Is api/pattern an endpoint?
What's the use of designEndpoint?

Choose a reason for hiding this comment

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

@Philip-21, may you answer this?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

its the ApiEndpoint for creating or deleting meshmap design .

Choose a reason for hiding this comment

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

I see. Id added after it will point to a particular design, r8?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yes

Copy link
Contributor Author

Choose a reason for hiding this comment

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

i am thinking of writing individual tests for every action but i dont think it will work

Copy link
Contributor Author

@Philip-21 Philip-21 Sep 16, 2023

Choose a reason for hiding this comment

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

i am trying to see how i ca put everything together, for it to work

}

export const MESHMAP_PATH = "/extension/meshmap";

export const CANVAS_CONTAINER_ID = "py-canvas-container"

export const TIME = {
SMALL: 500,
MEDIUM: 1000,
LARGE: 1500,
XLARGE: 2000,
XXLARGE: 5000,
XXXLARGE: 10000,
X4LARGE: 15_000
}

export const canvasContainer = {
query: id(CANVAS_CONTAINER_ID),
alias: "canvas"
}

export const playwrightTestDesign = {
url: "/extension/meshmap?design=142f0054-d9ae-4352-8618-887104a81928",
id: "142f0054-d9ae-4352-8618-887104a81928",
}
//Objects related to specific designs or patterns within the application.
export const hierarchyRelationshipDesign = cypressTestDesign;

// An object specifying a URL, HTTP method, and aliases related to pattern conversion.
export const cytoConversion = {
url: "/api/pattern?output=cytoscape",
method: "POST",
alias: "cytoPatternConversion",
wait: "@cytoPatternConversion"
}

/**
* Selection and general Event Binding Layer
*/
export const canvasLayer0 = {
query: '[data-id="layer0-selectbox"]',
alias: "layer0"
}

/**
* drag and drop Layer
*/
export const canvasLayer1 = {
query: '[data-id="layer1-drag"]',
alias: "layer1"
}

/**
* Node and Element Layer
*/
export const canvaslayer2 = {
query: '[data-id="layer2-node"]',
alias: "layer2"
}
18 changes: 18 additions & 0 deletions playwright-action/helpers/playwrightSetup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//@ts-check
import { waitFor, id, InitialEnvSetup, captureAndSaveScreenshot, saveGraph, Login, setViewportSize,interceptAndModifyRequest, navigateToCustomURL, waitForNetworkResponse } from "./playwrightUtils"


//Set Up Playwright capabilities
const doInitialSetup = () => {
InitialEnvSetup()
setViewportSize();
Login();
interceptAndModifyRequest();
}

//a callback hook to perform actions before running individual tests
export const beforeEachCallbackForCustomUrl = (customPath)=>{
doInitialSetup();
navigateToCustomURL(customPath)
waitForNetworkResponse(customPath)
}
121 changes: 121 additions & 0 deletions playwright-action/helpers/playwrightUtils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
//@ts-check
//Playwright configurations for setting up tests
const { chromium } = require("@playwright/test");
const path = require('path');
const browser = await chromium.launch();
const context = await browser.newContext();
const page = await context.newPage();

const getFormattedDateTime = () =>{
const now = new Date();

// Extract date components (YYYY_MM_DD format)
const year = now.getFullYear();

// Add 1 because months are 0-indexed
const month = (now.getMonth() + 1).toString().padStart(2, "0");
const day = now.getDate().toString().padStart(2, "0");

// Extract time components (HH_MM_SS format)
const hours = now.getHours().toString().padStart(2, "0");
const minutes = now.getMinutes().toString().padStart(2, "0");
const seconds = now.getSeconds().toString().padStart(2, "0");

// Concatenate date and time components into the desired format
const formattedString = `Meshmap_${year}_${month}_${day}_${hours}_${minutes}_${seconds}.png`;

return formattedString;
};

//utility func to generate css selector and return id and strings
function waitFor(str) {
return `@${str}`;
Copy link
Contributor

@VaibhavMalik4187 VaibhavMalik4187 Sep 13, 2023

Choose a reason for hiding this comment

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

I wonder if using $ to access the element is recommended.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

its the same method as return "@" + str;

Copy link
Contributor Author

Choose a reason for hiding this comment

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

${} makes it easier to include variables and expressions within a string without explicit concatenation.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

what do you think of the login and interceptRequests functions

}

function id(str) {
return `#${str}`;
}


//create a fresh testing env for testcases
async function InitialEnvSetup() {
const browser = await chromium.launch();
const context = await browser.newContext();
const page = await context.newPage();

return { browser, context, page };
}


//capture and save a screenshot
async function captureAndSaveScreenshot(filename) {
await page.screenshot({ path: filename });
}

//Save meshmapscreenshot and generate a download link.
async function saveGraph(customUrl) {
const browser = await chromium.launch();
const page = await browser.newPage();

await page.goto(customUrl);

// Capture a screenshot and save it with a custom filename
const date = new Date();
// Format: Meshmap_2023_09_23_14_30_45.png
const fileName = getFormattedDateTime();
const filePath = path.join(__dirname, fileName); // Full path to the saved screenshot

await captureAndSaveScreenshot(filePath);
await browser.close();

// Create a download link
const downloadLink = `/download?fileName=${encodeURIComponent(fileName)}`;

console.log(`Screenshot saved as ${fileName}`);
console.log('Download link:', downloadLink);

return downloadLink;
}

//Login to be used for settingup tests
async function Login(page, username, password) {
await page.goto('https://meshery.layer5.io/login');

await page.locator('input[name="identifier"]').fill(username);
// Press the Tab key (to move to the password field)
await page.locator('input[name="identifier"]').press('Tab');
await page.fill('input[name="password"]').fill(password);
await page.getByRole('button', { name: 'Sign in', exact: true }).click();
}

//set a visiblesize of webpage
async function setViewportSize(width, height) {
await page.setViewportSize({ width, height });
}

// intercept and modify network requests to specific endpoint
// to control network interactions during testing and automation
async function interceptAndModifyRequest(targetUrl, modifiedResponse) {
await page.route(targetUrl, (route) => {
route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify(modifiedResponse),//custom response to send when intercepting a network request
});
});
}

async function navigateToCustomURL(customPath) {
const browser = await chromium.launch();
const context = await browser.newContext();
const page = await context.newPage();
await page.goto(customPath);
}

async function waitForNetworkResponse(targetUrl) {
const timeout = 60000
await page.waitForResponse(targetUrl, { timeout });
}


export { waitFor, id, InitialEnvSetup, captureAndSaveScreenshot, saveGraph, Login, setViewportSize, interceptAndModifyRequest, navigateToCustomURL, waitForNetworkResponse };