Repository: pactumjs/pactum
Pull request #360 (2024-06-16 11:36:20)

build(deps-dev): bump braces from 3.0.2 to 3.0.3
Bumps [braces](https://github.com/micromatch/braces) from 3.0.2 to 3.0.3.
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/micromatch/braces/commit/74b2db2938fad48a2ea54a9c8bf27a37a62c350d"><code>74b2db2</code></a> 3.0.3</li>
<li><a href="https://github.com/micromatch/braces/commit/88f1429a0f47e1dd3813de35211fc97ffda27f9e"><code>88f1429</code></a> update eslint. lint, fix unit tests.</li>
<li><a href="https://github.com/micromatch/braces/commit/415d660c3002d1ab7e63dbf490c9851da80596ff"><code>415d660</code></a> Snyk js braces 6838727 (<a href="https://redirect.github.com/micromatch/braces/issues/40">#40</a>)</li>
<li><a href="https://github.com/micromatch/braces/commit/190510f79db1adf21d92798b0bb6fccc1f72c9d6"><code>190510f</code></a> fix tests, skip 1 test in test/braces.expand</li>
<li><a href="https://github.com/micromatch/braces/commit/716eb9f12d820b145a831ad678618731927e8856"><code>716eb9f</code></a> readme bump</li>
<li><a href="https://github.com/micromatch/braces/commit/a5851e57f45c3431a94d83fc565754bc10f5bbc3"><code>a5851e5</code></a> Merge pull request <a href="https://redirect.github.com/micromatch/braces/issues/37">#37</a> from coderaiser/fix/vulnerability</li>
<li><a href="https://github.com/micromatch/braces/commit/2092bd1fb108d2c59bd62e243b70ad98db961538"><code>2092bd1</code></a> feature: braces: add maxSymbols (<a href="https://github.com/micromatch/braces/issues/">https://github.com/micromatch/braces/issues/</a>...</li>
<li><a href="https://github.com/micromatch/braces/commit/9f5b4cf47329351bcb64287223ffb6ecc9a5e6d3"><code>9f5b4cf</code></a> fix: vulnerability (<a href="https://security.snyk.io/vuln/SNYK-JS-BRACES-6838727">https://security.snyk.io/vuln/SNYK-JS-BRACES-6838727</a>)</li>
<li><a href="https://github.com/micromatch/braces/commit/98414f9f1fabe021736e26836d8306d5de747e0d"><code>98414f9</code></a> remove funding file</li>
<li><a href="https://github.com/micromatch/braces/commit/665ab5d561c017a38ba7aafd92cc6655b91d8c14"><code>665ab5d</code></a> update keepEscaping doc (<a href="https://redirect.github.com/micromatch/braces/issues/27">#27</a>)</li>
<li>Additional commits viewable in <a href="https://github.com/micromatch/braces/compare/3.0.2...3.0.3">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=braces&package-manager=npm_and_yarn&previous-version=3.0.2&new-version=3.0.3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

You can trigger a rebase of this PR by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the [Security Alerts page](https://github.com/pactumjs/pactum/network/alerts).

</details>

> **Note**
> Automatic rebases have been disabled on this pull request as it has been open for over 30 days.



Patch:
diff --git a/package-lock.json b/package-lock.json
index 7bfe008..c55fd83 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
 {
   "name": "pactum",
-  "version": "3.7.0",
+  "version": "3.7.1",
   "lockfileVersion": 2,
   "requires": true,
   "packages": {
     "": {
       "name": "pactum",
-      "version": "3.7.0",
+      "version": "3.7.1",
       "license": "MIT",
       "dependencies": {
         "@exodus/schemasafe": "^1.3.0",
@@ -813,12 +813,12 @@
       }
     },
     "node_modules/braces": {
-      "version": "3.0.2",
-      "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
-      "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+      "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
       "dev": true,
       "dependencies": {
-        "fill-range": "^7.0.1"
+        "fill-range": "^7.1.1"
       },
       "engines": {
         "node": ">=8"
@@ -1206,9 +1206,9 @@
       }
     },
     "node_modules/fill-range": {
-      "version": "7.0.1",
-      "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
-      "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+      "version": "7.1.1",
+      "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
+      "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
       "dev": true,
       "dependencies": {
         "to-regex-range": "^5.0.1"
@@ -3563,12 +3563,12 @@
       }
     },
     "braces": {
-      "version": "3.0.2",
-      "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
-      "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+      "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
       "dev": true,
       "requires": {
-        "fill-range": "^7.0.1"
+        "fill-range": "^7.1.1"
       }
     },
     "browser-stdout": {
@@ -3860,9 +3860,9 @@
       "dev": true
     },
     "fill-range": {
-      "version": "7.0.1",
-      "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
-      "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+      "version": "7.1.1",
+      "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
+      "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
       "dev": true,
       "requires": {
         "to-regex-range": "^5.0.1"
diff --git a/package.json b/package.json
index 03b010a..229d8a0 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "pactum",
-  "version": "3.7.0",
+  "version": "3.7.1",
   "description": "REST API Testing Tool for all levels in a Test Pyramid",
   "main": "./src/index.js",
   "types": "./src/index.d.ts",
diff --git a/src/exports/events.d.ts b/src/exports/events.d.ts
index 9e5a41f..995fd7b 100644
--- a/src/exports/events.d.ts
+++ b/src/exports/events.d.ts
@@ -5,4 +5,9 @@ export const EVENT_TYPES: {
   AFTER_RESPONSE: 'AFTER_RESPONSE';
 };
 
-export const events: EventEmitter;
\ No newline at end of file
+export const pactumEvents: EventEmitter;
+
+/**
+ * @deprecated
+ */
+export const events: EventEmitter;
diff --git a/src/exports/events.js b/src/exports/events.js
index fb837e1..bcfcb4c 100644
--- a/src/exports/events.js
+++ b/src/exports/events.js
@@ -1,7 +1,12 @@
 const { EventEmitter } = require('events');
 
+/**
+ * @deprecated
+ */
 const events = new EventEmitter();
 
+const pactumEvents = new EventEmitter();
+
 const EVENT_TYPES = {
   BEFORE_REQUEST: "BEFORE_REQUEST",
   AFTER_RESPONSE: "AFTER_RESPONSE",
@@ -9,5 +14,6 @@ const EVENT_TYPES = {
 
 module.exports = {
   events,
+  pactumEvents,
   EVENT_TYPES
 }
\ No newline at end of file
diff --git a/src/exports/expect.js b/src/exports/expect.js
index 165c7d9..891f52f 100644
--- a/src/exports/expect.js
+++ b/src/exports/expect.js
@@ -1,5 +1,6 @@
 const ExpectModel = require('../models/expect');
 const utils = require('../helpers/utils');
+const http = require('http');
 
 class Have {
 
@@ -143,7 +144,11 @@ class Expect {
 }
 
 function expect(response, spec) {
-  return new Expect(response, spec);
+  if (response instanceof http.IncomingMessage) {
+    return new Expect(response, spec);
+  }
+  const res = { json: response };
+  return new Expect(res, spec);
 }
 
 module.exports = expect;
\ No newline at end of file
diff --git a/src/exports/request.d.ts b/src/exports/request.d.ts
index fb302c3..77ea7ed 100644
--- a/src/exports/request.d.ts
+++ b/src/exports/request.d.ts
@@ -26,14 +26,9 @@ export function setBaseUrl(url: string): void;
 export function setFollowRedirects(follow: boolean): void;
 
 /**
- * removes default header
+ * removes all or selective default headers
  */
-export function removeDefaultHeader(key: string): void;
-
-/**
- * removes all default headers
- */
-export function removeDefaultHeaders(): void;
+export function removeDefaultHeaders(key?: string): void;
 
 /**
  * records data that will be available in reports
diff --git a/src/exports/request.js b/src/exports/request.js
index bcf43ce..2368ce5 100644
--- a/src/exports/request.js
+++ b/src/exports/request.js
@@ -46,15 +46,12 @@ const request = {
     config.request.followRedirects = follow;
   },
 
-  removeDefaultHeader(key) {
-    if (!key) {
-      throw new PactumRequestError(`Invalid header key provided - ${key}`);
-    }
-    delete config.request.headers[key];
-  },
-
-  removeDefaultHeaders() {
-    config.request.headers = {};
+  removeDefaultHeaders(key) {
+    if(key) {
+      delete config.request.headers[key];
+    } else {
+      config.request.headers = {};
+    } 
   },
 
   setDefaultRecorders(name, path) {
diff --git a/src/exports/utils.d.ts b/src/exports/utils.d.ts
new file mode 100644
index 0000000..ea744fc
--- /dev/null
+++ b/src/exports/utils.d.ts
@@ -0,0 +1,15 @@
+export function clone<T>(input: T): T;
+
+/**
+ * sleeps for a certain amount of time
+ * @param {number} ms the amount of time to sleep in milliseconds
+ * @returns
+ */
+export function sleep(ms: number): Promise<void>;
+
+/**
+ * find a file recursively in a directory
+ * @param name  the name of the file
+ * @param dir the directory to search in. Defaults to config.data.dir
+ */
+export function findFile(name: string, dir?: string): string;
\ No newline at end of file
diff --git a/src/exports/utils.js b/src/exports/utils.js
new file mode 100644
index 0000000..7d52e7f
--- /dev/null
+++ b/src/exports/utils.js
@@ -0,0 +1,35 @@
+const { findFileRecursively } = require("../helpers/file.utils");
+const config = require("../config");
+const { klona } = require("klona");
+
+const utils = {
+
+  clone(value) {
+    return klona(value);
+  },
+
+  /**
+   * sleeps for a certain amount of time
+   * @param {number} ms the amount of time to sleep in milliseconds
+   * @returns
+   */
+  sleep(ms) {
+    return new Promise(resolve => setTimeout(resolve, ms));
+  },
+
+  /**
+   * finds a file recursively in a directory
+   * @param {string} name
+   * @param {string} dir
+   * @returns
+   */
+  findFile(name, dir = config.data.dir) {
+    const result = findFileRecursively(name, dir);
+    if (result) {
+      return result;
+    }
+    throw new Error(`File Not Found - '${name}'`);
+  }
+}
+
+module.exports = utils;
\ No newline at end of file
diff --git a/src/helpers/dataProcessor.js b/src/helpers/dataProcessor.js
index 8f72128..588e90b 100644
--- a/src/helpers/dataProcessor.js
+++ b/src/helpers/dataProcessor.js
@@ -1,7 +1,7 @@
 const override = require('deep-override');
 const jq = require('json-query');
-const { klona } = require("klona");
 
+const { clone } = require('../exports/utils');
 const stash = require('../exports/stash');
 const handler = require('../exports/handler');
 const log = require('../plugins/logger');
@@ -17,7 +17,7 @@ const dataProcessor = {
   processMaps() {
     if (!config.data.ref.map.processed) {
       const orgMap = stash.getDataMap();
-      this.map = klona(orgMap);
+      this.map = clone(orgMap);
       this.map = this.processDataRefs(this.map);
       config.data.ref.map.processed = true;
       if (Object.keys(this.map).length > 0) {
@@ -29,7 +29,7 @@ const dataProcessor = {
   processTemplates() {
     if (!config.data.template.processed) {
       const orgTemplate = stash.getDataTemplate();
-      this.template = klona(orgTemplate);
+      this.template = clone(orgTemplate);
       this.template = this.processDataTemplates(this.template);
       config.data.template.processed = true;
       if (Object.keys(this.template).length > 0) {
@@ -58,7 +58,7 @@ const dataProcessor = {
     if (templateName) {
       const templateValue = this.template[templateName];
       if (templateValue) {
-        data = klona(templateValue);
+        data = clone(templateValue);
         data = this.processDataTemplates(data);
         if (overrides) {
           override(data, overrides);
@@ -134,7 +134,7 @@ const dataProcessor = {
 
   getOverrides(data) {
     if (config.data.template.direct_override) {
-      const cloned_data = klona(data);
+      const cloned_data = clone(data);
       delete cloned_data['@DATA:TEMPLATE@'];
       delete cloned_data['@REMOVES@'];
       return cloned_data;
diff --git a/src/helpers/file.utils.js b/src/helpers/file.utils.js
index 2049198..6fad142 100644
--- a/src/helpers/file.utils.js
+++ b/src/helpers/file.utils.js
@@ -28,19 +28,8 @@ function saveSnapshot(name, data) {
   fs.writeFileSync(`${snapshotDir}/${snapshotFile}`, JSON.stringify(data, null, 2));
 }
 
-/**
- * 
- * @param {string} name 
- */
-function findFile(name, dir = config.data.dir) {
-  const result = _findFile(name, dir);
-  if (result) {
-    return result;
-  }
-  throw new Error(`File Not Found - '${name}'`);
-}
 
-function _findFile(name, dir = config.data.dir) {
+function findFileRecursively(name, dir = config.data.dir) {
   if (fs.existsSync(name)) {
     return fs.readFileSync(name);
   }
@@ -55,7 +44,7 @@ function _findFile(name, dir = config.data.dir) {
       const dirPath = path.resolve(dir, file);
       const stats = fs.statSync(dirPath);
       if (stats.isDirectory()) {
-        const result = _findFile(name, dirPath);
+        const result = findFileRecursively(name, dirPath);
         if (result) {
           return result;
         }
@@ -67,5 +56,5 @@ function _findFile(name, dir = config.data.dir) {
 module.exports = {
   getSnapshotFile,
   saveSnapshot,
-  findFile
+  findFileRecursively
 };
\ No newline at end of file
diff --git a/src/index.d.ts b/src/index.d.ts
index 0dabbf7..2d22b7a 100644
--- a/src/index.d.ts
+++ b/src/index.d.ts
@@ -14,6 +14,7 @@ export * as response from './exports/response';
 export * as settings from './exports/settings';
 export * as stash from './exports/stash';
 export * as state from './exports/state';
+export * as utils from './exports/utils';
 
 export interface SpecOptions {
   memo?: any
diff --git a/src/index.js b/src/index.js
index ae561be..60ccd19 100644
--- a/src/index.js
+++ b/src/index.js
@@ -4,8 +4,6 @@ require('./plugins/json.match').setAdapter(require('./adapters/json.match'));
 require('./plugins/json.like').setAdapter(require('./adapters/json.like'));
 require('./plugins/form.data').setAdapter(require('./adapters/form.data'));
 
-const { klona } = require('klona')
-
 const Spec = require('./models/Spec');
 const Fuzz = require('./models/Fuzz');
 const E2E = require('./models/E2E');
@@ -22,6 +20,7 @@ const stash = require('./exports/stash');
 const expect = require('./exports/expect');
 const reporter = require('./exports/reporter');
 const events = require('./exports/events');
+const utils = require('./exports/utils');
 
 const processor = require('./helpers/dataProcessor');
 
@@ -43,6 +42,7 @@ const pactum = {
   expect,
   reporter,
   events,
+  utils,
 
   spec(name, data, opts) {
     return new Spec(name, data, opts);
@@ -68,7 +68,7 @@ const pactum = {
   },
 
   clone(value) {
-    return klona(value);
+    return utils.clone(value);
   },
 
   parse,
diff --git a/src/models/Interaction.model.js b/src/models/Interaction.model.js
index b95cbf1..b12930d 100644
--- a/src/models/Interaction.model.js
+++ b/src/models/Interaction.model.js
@@ -3,7 +3,7 @@ const { setMatchingRules, getValue } = require('pactum-matchers').utils;
 const processor = require('../helpers/dataProcessor');
 const helper = require('../helpers/helper');
 const { PactumInteractionError } = require('../helpers/errors');
-const { klona: clone } = require('klona');
+const { clone } = require('../exports/utils');
 const ALLOWED_REQUEST_METHODS = new Set([
   'GET',
   'POST',
@@ -122,7 +122,7 @@ class InteractionRequest {
     }
     if (request.cookies && typeof request.cookies === 'object') {
       const cookie = lc.serialize(request.cookies);
-      if(!this.headers) {
+      if (!this.headers) {
         this.headers = {};
       }
       this.headers['cookie'] = cookie;
@@ -169,9 +169,9 @@ class InteractionResponse {
     this.headers = getValue(response.headers);
     setMatchingRules(this.matchingRules, response.body, '$.body');
     this.body = getValue(response.body);
-    if(response.cookies) {
+    if (response.cookies) {
       const cookie = lc.serialize(response.cookies);
-      if(!this.headers) {
+      if (!this.headers) {
         this.headers = {};
       }
       this.headers['set-cookie'] = cookie;
diff --git a/src/models/Spec.js b/src/models/Spec.js
index 1a7da3b..a9f8cb4 100644
--- a/src/models/Spec.js
+++ b/src/models/Spec.js
@@ -14,7 +14,7 @@ const responseExpect = require('../exports/expect');
 const hr = require('../helpers/handler.runner');
 const rlc = require('../helpers/reporter.lifeCycle');
 const config = require('../config');
-const { findFile } = require('../helpers/file.utils');
+const { findFile } = require('../exports/utils');
 const stash = require('../exports/stash');
 const { memorize_spec, is_spec_memoized } = require('../helpers/memo');
 
@@ -45,7 +45,7 @@ class Spec {
     this._opts.handler_name = name;
     this._expect.setDefaultResponseExpectations();
   }
-  
+
   sleep(ms) {
     this._sleep = ms;
     return this;
@@ -209,7 +209,7 @@ class Spec {
 
   withJson(json) {
     if (typeof json === 'string') {
-      json = get_json_from_template_or_file(json);
+      json = getJsonFromTemplateOrFile(json);
     } else if (typeof json !== 'object') {
       throw new PactumRequestError(`Invalid json in request - ${json}`);
     }
@@ -400,13 +400,13 @@ class Spec {
   }
 
   expectJson(path, value) {
-    typeof value === 'undefined' ? this._expect.json.push(get_json_from_template_or_file(path)) : this._expect.jsonQuery.push({ path, value });
+    typeof value === 'undefined' ? this._expect.json.push(getJsonFromTemplateOrFile(path)) : this._expect.jsonQuery.push({ path, value });
     return this;
   }
   expectJsonAt(...args) { return this.expectJson(...args); }
 
   expectJsonLike(path, value) {
-    typeof value === 'undefined' ? this._expect.jsonLike.push(get_json_from_template_or_file(path)) : this._expect.jsonQueryLike.push({ path, value });
+    typeof value === 'undefined' ? this._expect.jsonLike.push(getJsonFromTemplateOrFile(path)) : this._expect.jsonQueryLike.push({ path, value });
     return this;
   }
   expectJsonLikeAt(...args) { return this.expectJsonLike(...args); }
@@ -416,7 +416,7 @@ class Spec {
       this._expect.jsonSchemaQuery.push({ path, value, options });
     } else {
       if (typeof value === 'undefined') {
-        this._expect.jsonSchema.push({ value: get_json_from_template_or_file(path) });
+        this._expect.jsonSchema.push({ value: getJsonFromTemplateOrFile(path) });
       } else {
         if (typeof path === 'object' && typeof value === 'object') {
           this._expect.jsonSchema.push({ value: path, options: value });
@@ -430,13 +430,13 @@ class Spec {
   expectJsonSchemaAt(...args) { return this.expectJsonSchema(...args); }
 
   expectJsonMatch(path, value) {
-    typeof value === 'undefined' ? this._expect.jsonMatch.push(get_json_from_template_or_file(path)) : this._expect.jsonMatchQuery.push({ path, value });
+    typeof value === 'undefined' ? this._expect.jsonMatch.push(getJsonFromTemplateOrFile(path)) : this._expect.jsonMatchQuery.push({ path, value });
     return this;
   }
   expectJsonMatchAt(...args) { return this.expectJsonMatch(...args); }
 
   expectJsonMatchStrict(path, value) {
-    typeof value === 'undefined' ? this._expect.jsonMatchStrict.push(get_json_from_template_or_file(path)) : this._expect.jsonMatchStrictQuery.push({ path, value });
+    typeof value === 'undefined' ? this._expect.jsonMatchStrict.push(getJsonFromTemplateOrFile(path)) : this._expect.jsonMatchStrictQuery.push({ path, value });
     return this;
   }
   expectJsonMatchStrictAt(...args) { return this.expectJsonMatchStrict(...args); }
@@ -572,7 +572,7 @@ function validateRequestUrl(request, url) {
   }
 }
 
-function get_json_from_template_or_file(path) {
+function getJsonFromTemplateOrFile(path) {
   if (typeof path === 'string') {
     if (stash.getDataTemplate()[path]) {
       return { '@DATA:TEMPLATE@': path };
diff --git a/src/models/Tosser.js b/src/models/Tosser.js
index 5cca5ca..5882273 100644
--- a/src/models/Tosser.js
+++ b/src/models/Tosser.js
@@ -10,7 +10,7 @@ const mock = require('../exports/mock');
 const request = require('../exports/request');
 const config = require('../config');
 const hr = require('../helpers/handler.runner');
-const { events, EVENT_TYPES } = require('../exports/events');
+const { events, pactumEvents, EVENT_TYPES } = require('../exports/events');
 
 class Tosser {
 
@@ -257,6 +257,7 @@ async function getResponse(tosser) {
   const requestStartTime = Date.now();
   try {
     events.emit(EVENT_TYPES.BEFORE_REQUEST, request);
+    pactumEvents.emit(EVENT_TYPES.BEFORE_REQUEST, { request });
     log.debug(`${request.method} ${request.url}`);
     res = await phin(request);
     res.buffer = res.body;
@@ -274,6 +275,7 @@ async function getResponse(tosser) {
   } finally {
     res.responseTime = Date.now() - requestStartTime;
     events.emit(EVENT_TYPES.AFTER_RESPONSE, res);
+    pactumEvents.emit(EVENT_TYPES.AFTER_RESPONSE, { request, response: res });
   }
   return res;
 }
diff --git a/src/models/expect.js b/src/models/expect.js
index 5916884..361afbe 100644
--- a/src/models/expect.js
+++ b/src/models/expect.js
@@ -1,7 +1,6 @@
 const assert = require('assert');
 const jqy = require('json-query');
 const lc = require('lightcookie');
-const { klona: clone } = require('klona');
 
 const config = require('../config');
 const utils = require('../helpers/utils');
@@ -10,6 +9,7 @@ const file = require('../helpers/file.utils');
 const log = require('../plugins/logger');
 const processor = require('../helpers/dataProcessor');
 const handler = require('../exports/handler');
+const { clone } = require('../exports/utils');
 const jsv = require('../plugins/json.schema');
 const jmv = require('../plugins/json.match');
 const jlv = require('../plugins/json.like');
@@ -348,7 +348,7 @@ class Expect {
         }
         if (value) {
           const current_rules = jmv.getMatchingRules(value, '$.body');
-          let errors = jmv.validate(actual,  jmv.getRawValue(value), current_rules, '$.body');
+          let errors = jmv.validate(actual, jmv.getRawValue(value), current_rules, '$.body');
           if (errors) {
             this.fail(errors.replace('$.body', '$'));
           }


Test patch:
diff --git a/test/component/events.spec.js b/test/component/events.spec.js
index c9bfdf4..2efaa46 100644
--- a/test/component/events.spec.js
+++ b/test/component/events.spec.js
@@ -1,19 +1,19 @@
 const { spec } = require('../../src');
-const { events, EVENT_TYPES } = require('../../src').events;
+const { pactumEvents, EVENT_TYPES } = require('../../src').events;
 
 describe('events', () => {
 
   before(() => {
-    events.on(EVENT_TYPES.BEFORE_REQUEST, (r) => {
+    pactumEvents.on(EVENT_TYPES.BEFORE_REQUEST, (r) => {
       console.log(r);
     });
-    events.on(EVENT_TYPES.AFTER_RESPONSE, (r) => {
-      console.log(r.body);
+    pactumEvents.on(EVENT_TYPES.AFTER_RESPONSE, (r) => {
+      console.log(r.response.body);
     });
   });
 
   after(() => {
-    events.removeAllListeners();
+    pactumEvents.removeAllListeners();
   });
 
   it('get', async () => {
diff --git a/test/unit/expect.spec.js b/test/unit/expect.spec.js
index b57936a..0a408ab 100644
--- a/test/unit/expect.spec.js
+++ b/test/unit/expect.spec.js
@@ -1,4 +1,6 @@
+const { expect } = require('../../src');
 const Expect = require('../../src/models/expect');
+const ce = require('chai').expect;
 
 describe('Expect', () => {
 
@@ -13,4 +15,29 @@ describe('Expect', () => {
     ex._validateHeaders({ headers: { c: 'ss'}});
   });
 
+});
+
+describe('expect', () => {
+
+  it('empty objects', () => {
+    expect({}).to.have.jsonLike({});
+  });
+
+  it('objects with properties', () => {
+    expect({ name: 'mom' }).to.have.jsonLike({ name: 'mom' });
+  });
+
+  it('objects with extra properties in actual json', () => {
+    expect({ name: 'mom', age: 50 }).to.have.jsonLike({ name: 'mom' });
+  });
+
+  it('objects with different properties', () => {
+    let err;
+    try {
+      expect({ name: 'mom' }).to.have.jsonLike({ role: 'mom' });
+    } catch (error) {
+      err = error;
+    }
+    ce(err.message).equals(`Json doesn't have property 'role' at '$'`);
+  });
 });
\ No newline at end of file
diff --git a/test/unit/request.spec.js b/test/unit/request.spec.js
index 9df28c7..c96f939 100644
--- a/test/unit/request.spec.js
+++ b/test/unit/request.spec.js
@@ -21,12 +21,8 @@ describe('request', () => {
     expect(() => request.setDefaultHeaders()).throws('Invalid header key provided - undefined');
   });
 
-  it('removeDefaultHeader - undefined', () => {
-    expect(() => request.removeDefaultHeader()).throws('Invalid header key provided - undefined');
-  });
-
-  it('removeDefaultHeader - which is not present', () => {
-    request.removeDefaultHeader('present');
+  it('removeDefaultHeaders - which is not present', () => {
+    request.removeDefaultHeaders('present');
   });
 
   it('setDefaultHeader & setDefaultHeaders & remove', () => {
@@ -41,7 +37,7 @@ describe('request', () => {
       'no': 'space',
       'gta': 'v'
     });
-    request.removeDefaultHeader('no');
+    request.removeDefaultHeaders('no');
     expect(config.request.headers).deep.equals({
       'hello': 'space',
       'gta': 'v'
@@ -62,6 +58,35 @@ describe('request', () => {
     expect(() => request.setDefaultTimeout('100')).throws('Invalid timeout provided - 100');
   });
 
+  it('setting default headers and removing it', () => {
+    request.setDefaultHeaders({
+      'pactumjs': 'userfriendly',
+      'apitesting': 'pactumjs'
+    });
+    expect(config.request.headers).deep.equals({
+      'pactumjs': 'userfriendly',
+      'apitesting': 'pactumjs'
+    });
+    request.removeDefaultHeaders();
+    expect(config.request.headers).deep.equals({});
+  });
+
+  it('setting duplicate headers and removing it', () => {
+    request.setDefaultHeaders({
+      'pactumjs': 'lightweight',
+      'test': 'testing',
+      'test': 'tested'
+    });
+    expect(config.request.headers).deep.equals({
+      'pactumjs': 'lightweight',
+      'test': 'tested'
+    });
+    request.removeDefaultHeaders('test');
+    expect(config.request.headers).deep.equals({
+      'pactumjs': 'lightweight'
+    });
+  });
+  
   afterEach(() => {
    config.request.headers = {};
   });