Skip to content

Commit

Permalink
pet store entity and added small sanity tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Romario authored and Romario committed Nov 28, 2023
1 parent 8b6ad9e commit 70f3743
Show file tree
Hide file tree
Showing 9 changed files with 169 additions and 16 deletions.
16 changes: 8 additions & 8 deletions infra/api/apiRequests/ApiRequests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,18 @@ export class ApiRequests {
}

/**
* @description this functions provides a genneric encapsulated HTTP methods with variety of options depends on your individual request
* @description this functions provides a generic encapsulated HTTP methods with variety of options depends on your individual request
* @param method
* @param url
* @param options
* @returns
*/
private async makeRequest<T>(method: RequestMethods, url: string, options?: { queryParams?: { [key: string]: T | any }, requestData?: { [key: string]: T }, authoriaztionRequired?: boolean, multiPartFormData?: boolean, multipartObject?: { [key: string]: string } }): Promise<APIResponse | undefined> {
private async makeRequest<T>(method: RequestMethods, url: string, options?: { queryParams?: { [key: string]: T | any }, requestData?: { [key: string]: T }, authoriaztionRequired?: boolean, isMultiPart?: boolean, multipartObject?: { [key: string]: any } }): Promise<APIResponse | undefined> {
let response: APIResponse | undefined
let headers: Record<string, string> = {
'Accept': '*/*'
}
if (options?.multiPartFormData) {
if (options?.isMultiPart) {
headers["Content-Type"] = 'multipart/form-data'
} else {
headers["Content-Type"] = 'application/json'
Expand All @@ -57,13 +57,13 @@ export class ApiRequests {
response = await this.apiRequestContext.get(url, { headers, params: options?.queryParams })
break;
case RequestMethods.POST:
response = await this.apiRequestContext.post(url, { headers, data: options?.requestData, multipart: options?.multipartObject })
response = await this.apiRequestContext.post(url, { headers, data: options?.requestData, multipart: options?.multipartObject! })
break;
case RequestMethods.PUT:
response = await this.apiRequestContext.put(url, { headers, data: options?.requestData, multipart: options?.multipartObject })
response = await this.apiRequestContext.put(url, { headers, data: options?.requestData, multipart: options?.multipartObject! })
break;
case RequestMethods.PATCH:
response = await this.apiRequestContext.patch(url, { headers, data: options?.requestData, multipart: options?.multipartObject })
response = await this.apiRequestContext.patch(url, { headers, data: options?.requestData, multipart: options?.multipartObject! })
break;
case RequestMethods.DELETE:
response = await this.apiRequestContext.delete(url)
Expand All @@ -77,8 +77,8 @@ export class ApiRequests {
return response;
}

public async post<T>(url: string, data?: { [key: string]: T }) {
let response = await this.makeRequest(RequestMethods.POST, url, { requestData: data })
public async post<T>(url: string, options?: { data?: { [key: string]: T }, isMultiPart?: boolean, multiPartData?: { [key: string]: T } }) {
let response = await this.makeRequest(RequestMethods.POST, url, { isMultiPart: options?.isMultiPart, requestData: options?.data, multipartObject: options?.multiPartData })
return response;
}

Expand Down
3 changes: 2 additions & 1 deletion infra/api/endpoints/ApiEndpoints.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export enum ApiEndpoints {
PET_STORE_ENDPOINT = 'pet',
PET = 'pet',
UPLOAD_IMAGE = 'uploadImage',
POKEMON_API = '',
GO_REST_API = '',
}
46 changes: 45 additions & 1 deletion infra/api/entities/petStore/PetStoreCrudActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,56 @@ import { APIRequestContext } from "@playwright/test";
import { ApiRequests } from "../../apiRequests/ApiRequests";
import { ApiEndpoints } from "../../endpoints/ApiEndpoints";
import { ApplicationUrl } from "../../helpers/urls/ApplicationUrl";
import path from "path";
import Randomizer from "../../helpers/faker/Randomizer";
import fs from 'fs'

export class PetStoreCrudActions extends ApiRequests {
private petStorePetEndpoint = `${ApplicationUrl.PET_STORE_URL}/${ApiEndpoints.PET_STORE_ENDPOINT}`

private petStorePetEndpoint = `${ApplicationUrl.PET_STORE_URL}/${ApiEndpoints.PET}`

public async getPet(petId: number) {
let response = await this.get(`${this.petStorePetEndpoint}/${petId}`)
return response;
}

public async createNewPet<T>(petData: { [key: string]: T }) {
let response = await this.post(this.petStorePetEndpoint, { data: petData })
return response;
}

/**
* @description this function uploads a pet image via reading a file and uploading it as a buffer file using the playwright multipart photo upload
*/
public async uploadPetImage<T>(petId: number, fileName: string) {
const rootDir = '.'
const file = path.resolve(rootDir, fileName);
const image = fs.readFileSync(file);
const multiPartData = {
file: {
name: file,
mimeType: "image/png",
buffer: image,
},
}
let response = await this.post(`${this.petStorePetEndpoint}/${petId}/${ApiEndpoints.UPLOAD_IMAGE}`, { isMultiPart: true, multiPartData })
return response;
// let res = await this.apiRequestContext.post(``, {
// headers: {
// 'Accept': "*/*",
// 'Content-Type': "multipart/form-data",
// },
// multipart: {
// file: {
// name: file,
// mimeType: "image/png",
// buffer: image,
// },

// }
// })

// return res;

}
}
20 changes: 20 additions & 0 deletions infra/api/helpers/faker/Randomizer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { fa, faker } from "@faker-js/faker";

export default class Randomizer {

public static getDogNameBreed(): string {
return faker.animal.dog()
}

public static getCatNameBreed(): string {
return faker.animal.cat()
}

public static getRandomLongNumber(): number {
return faker.number.int({ min: 1000, max: 5000 })
}

public static getRandomName(): string {
return faker.internet.domainName()
}
}
16 changes: 14 additions & 2 deletions infra/api/interfaces/ApiObjectsInterfaces.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
export interface Ipet<T> {
export interface Ipet {
id?: number,
category?: { [key: string]: T },
category?: { [key: string]: any },
name: string,
photoUrls: string[]
tags?: { [key: string]: any },
status?: string,
}

export interface Ipokemon {

}


export interface IgoRestApi {

}
16 changes: 16 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"typescript": "^5.3.2"
},
"dependencies": {
"@faker-js/faker": "^8.3.1",
"@types/npm": "^7.19.3",
"dotenv": "^16.3.1"
}
Expand Down
Binary file added pug.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
67 changes: 63 additions & 4 deletions tests/api_tests/petStore/PetStoreCrudTests.spec.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,80 @@
import { expect, test } from '@playwright/test'
import { PetStoreCrudActions } from '../../../infra/api/entities/petStore/PetStoreCrudActions'
import { STATUS_CODES } from 'http';
import { StatusCode } from '../../../infra/api/apiRequests/ApiRequests';
import { Ipet } from '../../../infra/api/interfaces/ApiObjectsInterfaces';
import Randomizer from '../../../infra/api/helpers/faker/Randomizer';

test.describe('CRUD API tests for the Pet Store API', async () => {
let petStoreCrudActions: PetStoreCrudActions;
let petId: number = 10;
let createdPedtId: number = 3193;


test.beforeEach(async ({ request }) => {
petStoreCrudActions = new PetStoreCrudActions(request)
})

test('get a specific pet resource', async () => {
test('get a specific pet for sanity checkup @PET_STORE', async () => {
await test.step('make an api request to a specific pet ID', async () => {
let response = await petStoreCrudActions.getPet(petId)
let responseJson = await response?.json()
console.log(responseJson);
expect(response?.status()).toBe(200)
let responseJson: Ipet = await response?.json()
expect(response?.status()).toBe(StatusCode.OK)
expect(responseJson.name).toBe('doggie')
})
})

test('create a new pet @PET_STORE', async () => {
await test.step('create a new pet via post request', async () => {
let petData = {
id: Randomizer.getRandomLongNumber(),
category: {
id: Randomizer.getRandomLongNumber(),
name: Randomizer.getRandomName()
},
name: Randomizer.getDogNameBreed(),
photoUrls: ['https://ibb.co/wLWCrSX'],
tags: [
{
id: Randomizer.getRandomLongNumber(),
name: Randomizer.getRandomName(),
}
],
status: 'available'
}
let response = await petStoreCrudActions.createNewPet(petData)
let responseBody: Ipet = await response?.json();
expect(response?.status()).toBe(StatusCode.OK);
expect(responseBody).toEqual(petData);
expect(response?.statusText()).toBe('OK');
})
})

test('validate the pet existance', async () => {
await test.step('validate the pet that was created from previous test now exists', async () => {
let response = await petStoreCrudActions.getPet(createdPedtId)
let responseBody: Ipet = await response?.json();
expect(response).toBeTruthy()
expect(response?.status()).toBe(StatusCode.OK)
expect(responseBody.id).toEqual(createdPedtId)
expect(responseBody.name).toEqual('Shiloh Shepherd')
})
})

test('create pet image', async () => {
await test.step('upload another image to the pet that was created in the previous test', async () => {
let imageFileName: string = 'pug.png'
let response = await petStoreCrudActions.uploadPetImage(createdPedtId, imageFileName);
expect(response?.status()).toBe(StatusCode.OK);

})
})

// (property) multipart?: {
// [key: string]: string | number | boolean | ReadStream | {
// name: string;
// mimeType: string;
// };
// } | undefined

})

0 comments on commit 70f3743

Please sign in to comment.