192 lines
6.9 KiB
TypeScript
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()
|
|
});
|
|
}
|