Skip to content

Commit

Permalink
feat: memo spec handlers (#343)
Browse files Browse the repository at this point in the history
  • Loading branch information
ASaiAnudeep authored Apr 5, 2024
1 parent 81dbe6d commit 47dbb61
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 4 deletions.
30 changes: 30 additions & 0 deletions src/helpers/memo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
const jmv = require('../plugins/json.match');

const specs = {};

function memorize_spec(name, props) {
if (!specs[name]) {
specs[name] = [];
}
specs[name].push({ props });
}

function is_spec_memoized(name, new_props) {
const items = specs[name];
if (!items) {
return false;
}
for (const item of items) {
const rules = jmv.getMatchingRules(item.props, '$');
const errors = jmv.validate(item.props, new_props, rules, '$', true);
if (!errors) {
return true;
}
}
return false;
}

module.exports = {
memorize_spec,
is_spec_memoized
}
6 changes: 5 additions & 1 deletion src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ export * as settings from './exports/settings';
export * as stash from './exports/stash';
export * as state from './exports/state';

export interface SpecOptions {
memo?: any
}

/**
* returns an instance of a spec
* @see https://pactumjs.github.io/api/requests/spec.html
Expand All @@ -25,7 +29,7 @@ export function spec(): Spec;
* returns an instance of a spec & runs custom spec handler
* @see https://pactumjs.github.io/api/requests/spec.html
*/
export function spec<T = any>(name: string, data?: T): Spec;
export function spec<T = any>(name: string, data?: T, opts?: SpecOptions): Spec;

/**
* returns an instance of spec
Expand Down
4 changes: 2 additions & 2 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ const pactum = {
reporter,
events,

spec(name, data) {
return new Spec(name, data);
spec(name, data, opts) {
return new Spec(name, data, opts);
},

flow(name) {
Expand Down
11 changes: 10 additions & 1 deletion src/models/Spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ const rlc = require('../helpers/reporter.lifeCycle');
const config = require('../config');
const { findFile } = require('../helpers/file.utils');
const stash = require('../exports/stash');
const { memorize_spec, is_spec_memoized } = require('../helpers/memo');

class Spec {
constructor(name, data) {
constructor(name, data, opts) {
this.id = helper.getRandomId();
this.flow = '';
this._name = '';
Expand All @@ -38,6 +39,8 @@ class Spec {
this._save = null;
this._specHandlerData = data;
hr.spec(name, data, this);
this._opts = opts || {};
this._opts.handler_name = name;
this._expect.setDefaultResponseExpectations();
}

Expand Down Expand Up @@ -513,6 +516,12 @@ class Spec {
}

async toss() {
if (this._opts.handler_name && typeof this._opts.memo !== 'undefined') {
if (is_spec_memoized(this._opts.handler_name, this._opts.memo)) {
return Promise.resolve();
}
memorize_spec(this._opts.handler_name, this._opts.memo);
}
const tosser = new Tosser(this);
return tosser.toss();
}
Expand Down
58 changes: 58 additions & 0 deletions test/component/memo.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
const { spec, handler } = require('../../src');
const expect = require('chai').expect;

describe('Memo', () => {

before(() => {
handler.addSpecHandler('default get memo', ({ spec }) => {
spec.useInteraction('default get');
spec.get('http://localhost:9393/default/get');
spec.expectStatus(200);
});
handler.addSpecHandler('default get memo duplicate', ({ spec }) => {
spec.useInteraction('default get');
spec.get('http://localhost:9393/default/get');
spec.expectStatus(200);
});
});

it('should memoize with boolean', async () => {
let response = await spec('default get memo', null, { memo: true }).returns('method');
expect(response).equals('GET')
response = await spec('default get memo', null, { memo: true }).returns('method');
expect(response).to.be.undefined;
response = await spec('default get memo', null, { memo: false }).returns('method');
expect(response).equals('GET')
});

it('should memoize with string', async () => {
let response = await spec('default get memo', null, { memo: 'free' }).returns('method');
expect(response).equals('GET');
response = await spec('default get memo', null, { memo: 'paid' }).returns('method');
expect(response).equals('GET');
response = await spec('default get memo', null, { memo: 'free' }).returns('method');
expect(response).to.be.undefined;
response = await spec('default get memo', null, { memo: 'paid' }).returns('method');
expect(response).to.be.undefined;
});

it('should memoize with object with multiple specs', async () => {
let response = await spec('default get memo', null, { memo: { plan: 'free' } }).returns('method');
expect(response).equals('GET');
response = await spec('default get memo', null, { memo: { plan: 'paid' } }).returns('method');
expect(response).equals('GET');
response = await spec('default get memo', null, { memo: { plan: 'free' } }).returns('method');
expect(response).to.be.undefined;
response = await spec('default get memo', null, { memo: { plan: 'paid' } }).returns('method');
expect(response).to.be.undefined;
response = await spec('default get memo duplicate', null, { memo: { plan: 'free' } }).returns('method');
expect(response).equals('GET');
response = await spec('default get memo duplicate', null, { memo: { plan: 'paid' } }).returns('method');
expect(response).equals('GET');
response = await spec('default get memo duplicate', null, { memo: { plan: 'free' } }).returns('method');
expect(response).to.be.undefined;
response = await spec('default get memo duplicate', null, { memo: { plan: 'paid' } }).returns('method');
expect(response).to.be.undefined;
});

});

0 comments on commit 47dbb61

Please sign in to comment.