Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
dipjyotimetia committed Sep 17, 2023
1 parent b017bef commit 56430f6
Show file tree
Hide file tree
Showing 14 changed files with 304 additions and 43 deletions.
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ WORKDIR /app
COPY package.json .
COPY yarn.lock .
COPY playwright.config.ts .
COPY reportConfig.ts .
COPY tsconfig.json .

ENV CI=1
Expand Down
13 changes: 8 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,25 +20,28 @@
"homepage": "https://github.com/dipjyotimetia/PlaywrightTestFramework#readme",
"dependencies": {
"@faker-js/faker": "^8.0.2",
"allure-playwright": "^2.8.1",
"axios": "^1.5.0",
"config": "^3.3.9",
"csv-parse": "5.5.0",
"date-fns": "^2.30.0",
"fs-extra": "^11.1.1",
"fse": "^4.0.1",
"js-yaml": "^4.1.0",
"lodash": "^4.17.21",
"mkdirp": "^3.0.1",
"pg": "^8.11.3",
"recursive-readdir": "^2.2.3",
"rimraf": "^5.0.1",
"winston": "^3.10.0",
"yaml": "^2.3.2",
"pg": "^8.11.3",
"allure-playwright": "^2.8.1",
"csv-parse": "5.5.0"
"yaml": "^2.3.2"
},
"devDependencies": {
"@playwright/test": "^1.38.0",
"@types/js-yaml": "4.0.6",
"@types/node": "^20.6.2",
"eslint": "^8.49.0",
"eslint-plugin-playwright": "0.16.0",
"@playwright/test": "^1.38.0",
"typescript": "^5.2.2"
}
}
20 changes: 12 additions & 8 deletions playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,16 @@ export default defineConfig({
// Opt out of parallel tests on CI.
workers: process.env.CI ? 1 : undefined,

// Reporter to use
reporter: [['html', 'line'], ['./reportConfig.ts'], ["allure-playwright", {
detail: true,
outputFolder: "allure-results",
suiteTitle: false,
},]],
// Reporter configuration
reporter: [
['html', 'line'], // HTML and Line reporters
['./reportConfig.ts'], // Custom reporter configuration file
['allure-playwright', {
detail: true,
outputFolder: "allure-results",
suiteTitle: false,
}],
],

// use: {
// // Base URL to use in actions like `await page.goto('/')`.
Expand All @@ -34,7 +38,7 @@ export default defineConfig({
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
use: { ...devices['Desktop Chrome'] }, // Use Desktop Chrome device configuration
},
],
});
});
15 changes: 8 additions & 7 deletions reportConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,20 @@ if (!existsSync(logDir)) {
mkdirSync(logDir);
}

const console = new transports.Console();
const consoleTransport = new transports.Console();
const fileTransport = new transports.File({ filename: 'logs/info.log', level: 'info' });

const logger = createLogger({
level: 'info',
format: format.json(),
transports: [
// - Write all logs with importance level of `info` or less than it
new transports.File({ filename: 'logs/info.log', level: 'info' }),
// Write all logs with importance level of `info` or less than it to console
consoleTransport,
// Write all logs with importance level of `info` to a log file
fileTransport,
],
});

// Writes logs to console
logger.add(console);

export default class MyReporter implements Reporter {

onBegin(config: FullConfig, suite: Suite) {
Expand All @@ -45,4 +46,4 @@ export default class MyReporter implements Reporter {
onError(error: TestError): void {
logger.error(error.message);
}
}
}
3 changes: 0 additions & 3 deletions src/config/config.json

This file was deleted.

25 changes: 23 additions & 2 deletions src/config/config.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,23 @@
export const BASE_URL = '';
export const BASE_API = '';
import * as fs from 'fs';
import * as yaml from 'js-yaml';

export interface AppConfig {
BASE_URL: string;
BASE_API: string;
}

export function readConfigFile(filePath: string): AppConfig | null {
if (!fs.existsSync(filePath)) {
console.error('Config file does not exist:', filePath);
return null;
}

try {
const fileContents = fs.readFileSync(filePath, 'utf-8');
const config = yaml.load(fileContents) as AppConfig;
return config;
} catch (error) {
console.error('Error reading or parsing config file:', error);
return null;
}
}
2 changes: 2 additions & 0 deletions src/config/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
BASE_URL: "https://react-redux.realworld.io/"
BASE_API: ""
71 changes: 71 additions & 0 deletions src/core/apiActions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { BrowserContext, Page } from '@playwright/test';

// Function to mock an API call
export async function mockApiCall(context: BrowserContext | Page, route: string, response: any): Promise<void> {
await context.route(route, (route) => {
// Set the response status and body
route.fulfill({
status: 200,
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(response)
});
});
}

// Function to mock an API response with a delay
export async function mockApiCallWithDelay(
context: BrowserContext | Page,
route: string,
response: any,
delay: number
): Promise<void> {
await context.route(route, (route) => {
// Set a delay before fulfilling the request
setTimeout(() => {
route.fulfill({
status: 200,
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(response)
});
}, delay);
});
}

// Function to mock an API response not found
export async function mockApiCallNotFound(
context: BrowserContext | Page,
route: string
): Promise<void> {
await context.route(route, (route) => {
route.fulfill({
status: 404,
headers: {
'Content-Type': 'application/json'
},
body: '{}'
});
});
}


// Function to mock an API response with a header
export async function mockApiCallWithHeader(
context: BrowserContext | Page,
route: string,
headerName: string,
headerValue: string
): Promise<void> {
await context.route(route, (route) => {
route.fulfill({
status: 200,
headers: {
[headerName]: headerValue
},
body: '{}'
});
});
}
135 changes: 135 additions & 0 deletions src/core/webActions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import { Page, ElementHandle } from '@playwright/test';

// Function to navigate to a URL
export async function navigateToUrl(page: Page, url: string): Promise<void> {
await page.goto(url);
}

// Function to wait for an element to appear on the page
export async function waitForElement(page: Page, selector: string, timeout = 5000): Promise<void> {
await page.waitForSelector(selector, { timeout });
}

// Function to click an element by its selector
export async function clickElement(page: Page, selector: string): Promise<void> {
await page.click(selector);
}

// Function to fill an input field with text
export async function fillInputField(page: Page, selector: string, text: string): Promise<void> {
await page.fill(selector, text);
}

// Function to capture a screenshot
export async function captureScreenshot(page: Page, path: string): Promise<void> {
await page.screenshot({ path });
}

// Function to get the text content of an element
export async function getElementText(page: Page, selector: string): Promise<string | null> {
const element = await page.$(selector);
if (!element) {
throw new Error(`Element with selector ${selector} not found.`);
}
return element.textContent();
}

// Function to wait for navigation to complete
export async function waitForNavigation(page: Page, url: string): Promise<void> {
await page.waitForURL(url);
}

// Function to check if an element exists on the page
export async function doesElementExist(page: Page, selector: string): Promise<boolean> {
const element = await page.$(selector);
return !!element;
}

// Function to clear the content of an input field
export async function clearInputField(page: Page, selector: string): Promise<void> {
await page.fill(selector, ''); // Fill with an empty string to clear the field
}

// Function to select an option from a dropdown by value
export async function selectDropdownOptionByValue(page: Page, selector: string, value: string): Promise<void> {
await page.selectOption(selector, { value });
}

// Function to hover over an element
export async function hoverOverElement(page: Page, selector: string): Promise<void> {
await page.hover(selector);
}

// Function to right-click an element
export async function rightClickElement(page: Page, selector: string): Promise<void> {
await page.click(selector, { button: 'right' });
}

// Function to get an attribute's value of an element
export async function getElementAttributeValue(
page: Page,
selector: string,
attributeName: string
): Promise<string | null> {
const element = await page.$(selector);
if (!element) {
throw new Error(`Element with selector ${selector} not found.`);
}
return element.getAttribute(attributeName);
}

// Function to retrieve an array of elements by selector
export async function getElements(page: Page, selector: string): Promise<ElementHandle[]> {
return await page.locator(selector).elementHandles();
}

// Function to switch to a new tab or window by index
export async function switchToTabOrWindowByIndex(page: Page, index: number): Promise<void> {
const pages = await page.context().pages();
if (index >= 0 && index < pages.length) {
await pages[index].bringToFront();
} else {
throw new Error(`Tab or window with index ${index} not found.`);
}
}

// Function to click an element and wait for a navigation event
export async function clickAndWaitForNavigation(page: Page, selector: string): Promise<void> {
await Promise.all([
page.click(selector),
page.waitForNavigation({ waitUntil: 'domcontentloaded' }),
]);
}

// Function to scroll an element into view
export async function scrollElementIntoView(page: Page, selector: string): Promise<void> {
const element = await page.$(selector);
if (element) {
await element.scrollIntoViewIfNeeded();
}
}

// Function to take a screenshot of the current page
export async function takeScreenshot(page: Page, fileName: string): Promise<void> {
await page.screenshot({ path: fileName });
}

// Function to wait for an element to be visible and clickable
export async function waitForElementToBeClickable(page: Page, selector: string): Promise<ElementHandle | null> {
return page.waitForSelector(selector, { state: 'visible' });
}

// Function to type text into an input field
export async function typeText(page: Page, selector: string, text: string): Promise<void> {
await page.type(selector, text);
}

// Function to press the Enter key
export async function pressEnter(page: Page, selector: string): Promise<void> {
await page.press(selector, 'Enter');
}

// Function to press the Tab key
export async function pressTab(page: Page, selector: string): Promise<void> {
await page.press(selector, 'Tab');
}
Loading

0 comments on commit 56430f6

Please sign in to comment.