Skip to content

Commit

Permalink
Merge pull request #165 from pactumjs/164-save-files-from-response-to-fs
Browse files Browse the repository at this point in the history
164 save files from response to fs
  • Loading branch information
ASaiAnudeep authored May 27, 2022
2 parents e61ba2a + 033bc12 commit a61d428
Show file tree
Hide file tree
Showing 11 changed files with 194 additions and 18 deletions.
2 changes: 1 addition & 1 deletion package-lock.json

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

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "pactum",
"version": "3.1.8",
"version": "3.1.9",
"description": "REST API Testing Tool for all levels in a Test Pyramid",
"main": "./src/index.js",
"types": "./src/index.d.ts",
Expand Down
16 changes: 9 additions & 7 deletions src/exports/mock.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export interface InteractionRequest {
queryParams?: object;
graphQL?: GraphQLRequest;
body?: any;
form?: object;
}

export interface InteractionResponse {
Expand Down Expand Up @@ -70,21 +71,22 @@ export interface Handler {

/**
* starts the mock server
* @see https://pactumjs.github.io/#/mock-server
* @see https://pactumjs.github.io/guides/mock-server.html
*/
export function start(): Promise<void>;
export function start(port: number): Promise<void>;
export function start(port: number, host: string): Promise<void>;

/**
* stops the mock server
* @see https://pactumjs.github.io/#/mock-server
* @see https://pactumjs.github.io/guides/mock-server.html
*/
export function stop(): Promise<void>;

/**
* adds a interaction
* @see https://pactumjs.github.io/#/mock-server
* @see https://pactumjs.github.io/guides/mock-server.html
* @see https://pactumjs.github.io/api/mock/interaction.html
*/
export function addInteraction(interaction: Interaction): string | Promise<string>;
export function addInteraction(interactions: Interaction[]): string[] | Promise<string[]>;
Expand All @@ -95,27 +97,27 @@ export function addInteraction(handlers: Handler[], data?: any): string[] | Prom

/**
* returns interaction details
* @see https://pactumjs.github.io/#/mock-server
* @see https://pactumjs.github.io/guides/mock-server.html
*/
export function getInteraction(id: string): InteractionDetails | Promise<InteractionDetails>;
export function getInteraction(ids: string[]): InteractionDetails[] | Promise<InteractionDetails[]>;

/**
* removes specified interaction from the mock server
* @see https://pactumjs.github.io/#/mock-server
* @see https://pactumjs.github.io/guides/mock-server.html
*/
export function removeInteraction(id: string): void | Promise<void>;
export function removeInteraction(ids: string[]): void | Promise<void>;

/**
* clears all interactions from the server
* @see https://pactumjs.github.io/#/mock-server
* @see https://pactumjs.github.io/guides/mock-server.html
*/
export function clearInteractions(): void;

/**
* use remote pactum server
* all methods in mock will return promises
* @see https://pactumjs.github.io/#/mock-server
* @see https://pactumjs.github.io/guides/mock-server.html
*/
export function useRemoteServer(url: string): void;
4 changes: 2 additions & 2 deletions src/exports/reporter.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,12 @@ export interface Reporter {

/**
* adds custom reporters
* @see https://pactumjs.github.io/#/api-reporter
* @see https://pactumjs.github.io/guides/reporting.html
*/
export function add(reporter: Reporter): void;

/**
* runs end function of all added reporters
* @see https://pactumjs.github.io/#/api-reporter
* @see https://pactumjs.github.io/guides/reporting.html
*/
export function end(): Promise<void>;
21 changes: 16 additions & 5 deletions src/helpers/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -147,19 +147,30 @@ function validateHeaders(req, interaction) {

function validateBody(req, interaction) {
const { strict, request } = interaction;
const actual_request_body = request.form ? parseFormBody(req.body) : req.body;
const expected_request_body = request.form ? request.form : request.body;
if (request.graphQL && req.method !== 'GET') {
return graphQL.compare(req.body, request.body, strict);
return graphQL.compare(actual_request_body, expected_request_body, strict);
}
if (strict) {
if (req.body || request.body) {
return compare(req.body, request.body, request.matchingRules, '$.body', strict);
if (actual_request_body || expected_request_body) {
return compare(actual_request_body, expected_request_body, request.matchingRules, '$.body', strict);
}
} else {
if (request.body) {
return compare(req.body, request.body, request.matchingRules, '$.body', strict);
if (expected_request_body) {
return compare(actual_request_body, expected_request_body, request.matchingRules, '$.body', strict);
}
}
return { message: '', equal: true };
}

function parseFormBody(form_string) {
const form = {};
const params = new URLSearchParams(form_string);
for (const [name, value] of params) {
form[name] = value;
}
return form;
}

module.exports = utils;
4 changes: 4 additions & 0 deletions src/models/Interaction.model.js
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,10 @@ class InteractionRequest {
};
}
}
if (request.form) {
setMatchingRules(this.matchingRules, request.form, '$.body');
this.form = getValue(request.form);
}
}
}

Expand Down
10 changes: 8 additions & 2 deletions src/models/Spec.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { RequestOptions } from 'http';
import { RequestOptions, IncomingMessage } from 'http';
import FormData from 'form-data-lite';
import { Interaction } from '../exports/mock';
import { ExpectHandlerFunction, RetryHandlerFunction, CaptureHandlerFunction } from '../exports/handler';
Expand Down Expand Up @@ -385,11 +385,17 @@ declare class Spec {
*/
inspect(): Spec;

/**
* saves response in file system
* @see https://pactumjs.github.io/api/requests/save.html
*/
save(path: string): Spec;

/**
* executes the test case
* @see https://pactumjs.github.io/api/requests/toss.html
*/
toss(): Promise<any>;
toss(): Promise<IncomingMessage> | Promise<any>;

/**
* returns chai like assertions
Expand Down
6 changes: 6 additions & 0 deletions src/models/Spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class Spec {
this.previousLogLevel = null;
this.interactions = [];
this._wait = null;
this._save = null;
this._specHandlerData = data;
hr.spec(name, data, this);
this._expect.setDefaultResponseExpectations();
Expand Down Expand Up @@ -472,6 +473,11 @@ class Spec {
return this;
}

save(path) {
this._save = path;
return this;
}

async toss() {
const tosser = new Tosser(this);
return tosser.toss();
Expand Down
8 changes: 8 additions & 0 deletions src/models/Tosser.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
const phin = require('phin');
const fs = require('fs');
const helper = require('../helpers/helper');
const log = require('../plugins/logger');
const rlc = require('../helpers/reporter.lifeCycle');
Expand Down Expand Up @@ -37,6 +38,7 @@ class Tosser {
await this.staticWait();
}
await this.getInteractionsFromServer();
this.saveDataInFileSystem();
this.recordData();
th.storeSpecData(this.spec, this.spec._stores);
await this.validate();
Expand Down Expand Up @@ -165,6 +167,12 @@ class Tosser {
}
}

saveDataInFileSystem() {
if (this.spec._save && this.response.buffer) {
fs.writeFileSync(this.spec._save, this.response.buffer);
}
}

recordData() {
const defaultRecorders = request.getDefaultRecorders();
th.recordSpecData(this.spec, defaultRecorders);
Expand Down
126 changes: 126 additions & 0 deletions test/component/form.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
const { spec } = require('../../src/index');
const { like } = require('pactum-matchers');
const { expect } = require('chai');

describe('Form', () => {

it('single pair of form data', async () => {
await spec()
.useInteraction({
request: {
method: 'POST',
path: '/api/projects',
headers: {
'content-type': 'application/x-www-form-urlencoded'
},
form: {
'user': 'drake'
}
},
response: {
status: 200
}
})
.post('http://localhost:9393/api/projects')
.withForm({ 'user': 'drake' })
.expectStatus(200);
});

it('multiple pairs of form data', async () => {
await spec()
.useInteraction({
request: {
method: 'POST',
path: '/api/projects',
headers: {
'content-type': 'application/x-www-form-urlencoded'
},
form: {
'user': 'drake',
'age': '10'
}
},
response: {
status: 200
}
})
.post('http://localhost:9393/api/projects')
.withForm({ 'user': 'drake', 'age': 10 })
.expectStatus(200);
});

it('using matchers', async () => {
await spec()
.useInteraction({
request: {
method: 'POST',
path: '/api/projects',
headers: {
'content-type': 'application/x-www-form-urlencoded'
},
form: {
'user': like('drake')
}
},
response: {
status: 200
}
})
.post('http://localhost:9393/api/projects')
.withForm({ 'user': 'brake' })
.expectStatus(200);
});

it('fails to match', async () => {
let err;
try {
await spec()
.useInteraction({
request: {
method: 'POST',
path: '/api/projects',
headers: {
'content-type': 'application/x-www-form-urlencoded'
},
form: {
'user': 'drake'
}
},
response: {
status: 200
}
})
.post('http://localhost:9393/api/projects')
.withForm({ 'user': 'drake', 'age': 10 })
.useLogLevel('SILENT')
.expectStatus(200);
} catch (error) {
err = error;
}
expect(err).not.undefined;
});

it('disabling strict', async () => {
await spec()
.useInteraction({
strict: false,
request: {
method: 'POST',
path: '/api/projects',
headers: {
'content-type': 'application/x-www-form-urlencoded'
},
form: {
'user': 'drake'
}
},
response: {
status: 200
}
})
.post('http://localhost:9393/api/projects')
.withForm({ 'user': 'drake', 'age': 10 })
.expectStatus(200);
});

});
13 changes: 13 additions & 0 deletions test/component/save.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
const { spec } = require('../../src/index');

describe('Save', () => {

it('save json file', async () => {
await spec()
.useInteraction('get people')
.get('http://localhost:9393/api/people')
.save('.pactum/users.json')
.expectStatus(200);
});

});

0 comments on commit a61d428

Please sign in to comment.