DigitalConsumer.ISS/playwright-tests/impl/utils/HttpUtils.ts
Siraj Shaik 6d5a0524e3 latest updates from QA repo
21 and 22 scenarios were added
Mock responses refactored.
2025-02-18 14:41:05 -05:00

192 lines
6.9 KiB
TypeScript

import { Page } from 'playwright';
import { AxiosResponse, AxiosInstance } from 'axios';
import fs from 'fs';
import path from 'path';
interface MockResponse {
status: number;
body: any;
headers?: { [key: string]: string };
}
class MockApiManager {
private static instance: MockApiManager;
private mockResponses: { [url: string]: MockResponse } = {};
private constructor() { }
public static referralNumber: string;
public static referralSequenceNumber: string;
public static referralCorrelationId: string;
public static savedSessionId: string;
public static getInstance(): MockApiManager {
if (!MockApiManager.instance) {
MockApiManager.instance = new MockApiManager();
}
return MockApiManager.instance;
}
/**
* Loads mock responses from a configuration file.
* @param scenario - The scenario to load mock responses for.
*/
private loadMockResponses(scenario: string): void {
const mockResponsesDir = path.resolve(__dirname, '../../tests/mockResponses');
const configFilePath = path.join(mockResponsesDir, 'mockResponsesConfig.json');
if (fs.existsSync(configFilePath)) {
const config = JSON.parse(fs.readFileSync(configFilePath, 'utf-8'));
const scenarioConfig = config[scenario];
const commonConfig = config['common'];
for (const endpoint in scenarioConfig) {
this.loadMockResponse(endpoint, scenarioConfig[endpoint], mockResponsesDir);
}
for (const endpoint in commonConfig) {
if (!this.mockResponses[endpoint]) {
this.loadMockResponse(endpoint, commonConfig[endpoint], mockResponsesDir);
}
}
} else {
console.error(`Mock responses configuration file not found at path: ${configFilePath}`);
}
}
/**
* Loads a single mock response from a file.
* @param endpoint - The endpoint to load the mock response for.
* @param mockFilePath - The path to the mock response file.
* @param mockResponsesDir - The directory containing the mock response files.
*/
private loadMockResponse(endpoint: string, mockFilePath: string, mockResponsesDir: string): void {
const filePath = path.join(mockResponsesDir, mockFilePath);
if (fs.existsSync(filePath)) {
const mockResponse = fs.readFileSync(filePath, 'utf-8');
try {
this.mockResponses[endpoint] = JSON.parse(mockResponse);
} catch (error) {
console.error(`Error parsing mock response for endpoint: ${endpoint}`, error);
}
} else {
console.warn(`Mock response file${filePath} not found for endpoint: ${endpoint}`);
}
}
/**
* Gets the mocked API response for the given endpoint.
* @param endpoint - The endpoint to get the mocked response for.
* @param scenario - The scenario to load mock responses for.
* @returns The mocked response or null if not found.
*/
public getMockedApiResponse(endpoint: string, scenario: string): MockResponse | null {
if (!this.mockResponses[endpoint]) {
this.loadMockResponses(scenario);
}
return this.mockResponses[endpoint] || null;
}
/**
* Mocks the API response for the given endpoint.
* @param page - The Playwright page object.
* @param endpoint - The endpoint to mock.
* @param scenario - The scenario to load mock responses for.
* @param mockTestingFlag - Flag to enable or disable mocking.
*/
public async mockApiResponse(page: Page, scenario: string, mockTestingFlag: boolean): Promise<void> {
if (!mockTestingFlag) {
console.info("mockTestingFlag is false/undefined. so proceeding with original requests.")
return;
}
if (!scenario) {
console.error('Invalid scenario provided for mocking.');
return;
}
this.loadMockResponses(scenario);
for (const endpoint in this.mockResponses) {
await page.route(`**/${endpoint}`, async (route) => {
const response = this.mockResponses[endpoint];
if (response) {
route.fulfill({
status: response.status || 200,
body: JSON.stringify(response.body || response),
headers: response.headers || { 'Content-Type': 'application/json' },
});
}
console.info("Mocking Endpoint: " + endpoint)
});
}
}
public async updateReferralDetails(endpoint: string, response: MockResponse): Promise<MockResponse> {
try {
response.body.referralCorrelationId = MockApiManager.referralCorrelationId;
response.body.referralNumber = MockApiManager.referralNumber;
} catch (error) {
}
return response;
}
public async getReferralDetails(endpoint: string, response: MockResponse) {
if (endpoint.includes('order/save-session/iss')) {
MockApiManager.referralNumber = response.body.referralNumber;
MockApiManager.referralSequenceNumber = response.body.referralSequenceNumber;
MockApiManager.referralCorrelationId = response.body.referralCorrelationId;
MockApiManager.savedSessionId = response.body.sessionId;
}
}
}
// Export the instance
export const mockApiManager = MockApiManager.getInstance();
export async function httpGet<T>(client: AxiosInstance, url: string): Promise<T> {
const [isSuccess, response] = await handleHttp(client.get<T>(url));
if (isSuccess) {
return response;
}
console.error(`An error occurred calling GET ${url}\nError:${response}`);
throw response;
}
export async function httpPost<T, D>(client: AxiosInstance, url: string, data: D): Promise<T> {
const [isSuccess, response] = await handleHttp(client.post<T>(url, data));
if (isSuccess) {
return response;
}
console.error(`An error occurred calling POST ${url}\nError:${response}`);
throw response;
}
export function handleHttp<T>(request: Promise<AxiosResponse<T>>): Promise<[isSuccess: true, data: T] | [isSuccess: false, error: Error]> {
return request.then(data => {
return [true, data.data] as [true, T]
}).catch((error: Error) => {
return [false, error] as [false, Error]
})
}
export function buildQueryString<T>(data: T): URLSearchParams {
const params: Record<string, string> = {};
for (const key in data) {
const value = data[key];
params[key] = `${value}`;
}
return new URLSearchParams(params);
}
export function forceAPIError(page: Page, endpoint: string) {
page.route('**/*', (route) => {
return route.request().url().includes(endpoint)
? route.abort()
: route.continue()
});
}