Repository: pactumjs/pactum
Pull request #82 (2021-09-05 16:52:00)

3.0.19
- expectJsonLength
- mock server stops on SIGTERM


Patch:
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 3bc45a9..cc1c632 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -22,7 +22,7 @@ jobs:
     strategy:
       matrix:
         os: [windows-latest, ubuntu-latest, macos-latest]
-        node-version: [10.x, 12.x, 14.x]
+        node-version: [10.x, 12.x, 14.x, 16.x]
 
     steps:
     - uses: actions/checkout@v2
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
new file mode 100644
index 0000000..7c5cd16
--- /dev/null
+++ b/.github/workflows/publish.yml
@@ -0,0 +1,19 @@
+name: Publish
+on:
+  release:
+    types: [created]
+jobs:
+  build:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v2
+      # Setup .npmrc file to publish to npm
+      - uses: actions/setup-node@v2
+        with:
+          node-version: '12.x'
+          registry-url: 'https://registry.npmjs.org'
+      - run: npm install
+      - run: npm test
+      - run: npm publish
+        env:
+          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
\ No newline at end of file
diff --git a/README.md b/README.md
index 1fbe161..9df4033 100644
--- a/README.md
+++ b/README.md
@@ -10,8 +10,8 @@
 ![Size](https://img.shields.io/bundlephobia/minzip/pactum)
 ![Platform](https://img.shields.io/node/v/pactum)
 
-![Stars](https://img.shields.io/github/stars/pactumjs/pactum?style=social)
-![Twitter](https://img.shields.io/twitter/follow/pactumjs?label=Follow&style=social)
+[![Stars](https://img.shields.io/github/stars/pactumjs/pactum?style=social)](https://github.com/pactumjs/pactum/stargazers)
+[![Twitter](https://img.shields.io/twitter/follow/pactumjs?label=Follow&style=social)](https://twitter.com/pactumjs)
 
 #### REST API Testing Tool for all levels in a Test Pyramid
 
@@ -125,7 +125,7 @@ Scenario: Check Tea Pot
 ```js
 // steps.js
 const pactum = require('pactum');
-const { Given, When, Then, Before } = require('cucumber');
+const { Given, When, Then, Before } = require('@cucumber/cucumber');
 
 let spec = pactum.spec();
 
@@ -180,7 +180,7 @@ Inspired from [frisby](https://docs.frisbyjs.com/) and [pact](https://docs.pact.
 
 ## Support
 
-Like this project! Star it on [Github](https://github.com/pactumjs/pactum/stargazers). Your support means a lot to us.
+Like this project! Star it on [Github](https://github.com/pactumjs/pactum/stargazers) and follow on [Twitter](https://twitter.com/pactumjs). Your support means a lot to us.
 
 ## Contributors
 
diff --git a/package-lock.json b/package-lock.json
index afdda90..b702685 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
 {
   "name": "pactum",
-  "version": "3.0.18",
+  "version": "3.0.19",
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {
@@ -299,9 +299,9 @@
       }
     },
     "@exodus/schemasafe": {
-      "version": "1.0.0-rc.3",
-      "resolved": "https://registry.npmjs.org/@exodus/schemasafe/-/schemasafe-1.0.0-rc.3.tgz",
-      "integrity": "sha512-GoXw0U2Qaa33m3eUcxuHnHpNvHjNlLo0gtV091XBpaRINaB4X6FGCG5XKxSFNFiPpugUDqNruHzaqpTdDm4AOg=="
+      "version": "1.0.0-rc.4",
+      "resolved": "https://registry.npmjs.org/@exodus/schemasafe/-/schemasafe-1.0.0-rc.4.tgz",
+      "integrity": "sha512-zHISeJ5jcHSo3i2bI5RHb0XEJ1JGxQ/QQzU2FLPcJxohNohJV8jHCM1FSrOUxTspyDRSSULg3iKQa1FJ4EsSiQ=="
     },
     "@istanbuljs/load-nyc-config": {
       "version": "1.1.0",
@@ -580,9 +580,9 @@
       "dev": true
     },
     "centra": {
-      "version": "2.4.2",
-      "resolved": "https://registry.npmjs.org/centra/-/centra-2.4.2.tgz",
-      "integrity": "sha512-f1RaP0V1HqVNEXfLfjNBthB2yy3KnSGnPCnOPCFLUk9e/Z4rNJ8nBaJNnghflnp88mi1IT8mfmW+HlMS1/H+bg=="
+      "version": "2.5.0",
+      "resolved": "https://registry.npmjs.org/centra/-/centra-2.5.0.tgz",
+      "integrity": "sha512-CnSF1HD8vOOgNbE4P2fZEhdhfAohvpcF3DSdSvEcSHDAZvr+Xfw73isT8SXJJc3VMBqSwjXhr29/ikHUgFcypg=="
     },
     "chai": {
       "version": "4.3.4",
@@ -1701,9 +1701,9 @@
       "dev": true
     },
     "phin": {
-      "version": "3.5.1",
-      "resolved": "https://registry.npmjs.org/phin/-/phin-3.5.1.tgz",
-      "integrity": "sha512-jgFO28IaiWAl0xk+zmqVx7neKVokWKU8YTQC5QlB45SZnEE53LH2saqJIcyIV557VX3Gk+TdR4rwWTc3P83DSA==",
+      "version": "3.6.0",
+      "resolved": "https://registry.npmjs.org/phin/-/phin-3.6.0.tgz",
+      "integrity": "sha512-nYY4Qh/yGCoxcwOAS2UfCM8+nVJcbI4f9NC4M4zPAsuswnIIS2aB14uYAbvdxP/4DqzXfrpadT2WQOx9mLDyTA==",
       "requires": {
         "centra": "^2.4.2"
       }
diff --git a/package.json b/package.json
index 1df976c..7e0fa70 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "pactum",
-  "version": "3.0.18",
+  "version": "3.0.19",
   "description": "REST API Testing Tool for all levels in a Test Pyramid",
   "main": "./src/index.js",
   "types": "./src/index.d.ts",
@@ -59,7 +59,7 @@
   "author": "Anudeep <asa.anudeep4@gmail.com>",
   "license": "MIT",
   "dependencies": {
-    "@exodus/schemasafe": "^1.0.0-rc.3",
+    "@exodus/schemasafe": "^1.0.0-rc.4",
     "deep-override": "^1.0.2",
     "form-data": "^4.0.0",
     "json-query": "^2.2.2",
@@ -68,7 +68,7 @@
     "openapi-fuzzer-core": "^1.0.6",
     "pactum-matchers": "^1.0.2",
     "parse-graphql": "^1.0.0",
-    "phin": "^3.5.1",
+    "phin": "^3.6.0",
     "polka": "^0.5.2"
   },
   "devDependencies": {
diff --git a/src/exports/expect.d.ts b/src/exports/expect.d.ts
index 83b22e6..09671f1 100644
--- a/src/exports/expect.d.ts
+++ b/src/exports/expect.d.ts
@@ -18,6 +18,8 @@ export interface Have {
   jsonMatch(path: string, value: object): void;
   jsonMatchStrict(value: object): void;
   jsonMatchStrict(path: string, value: object): void;
+  jsonLength(value: number): void;
+  jsonLength(path: string, value: number): void;
   responseTimeLessThan(ms: number): void;
   error(err?: string | object): void;
   _(handler: string, data: any): Promise<void>;
diff --git a/src/exports/expect.js b/src/exports/expect.js
index b7ad79a..e82251e 100644
--- a/src/exports/expect.js
+++ b/src/exports/expect.js
@@ -81,6 +81,11 @@ class Have {
     this._validate();
   }
 
+  jsonLength(path, value) {
+    typeof value === 'undefined' ? this.expect.jsonLike.push(path) : this.expect.jsonLengthQuery.push({ path, value });
+    this._validate();
+  }
+
   responseTimeLessThan(ms) {
     this.expect.responseTime = ms;
     this._validate();
diff --git a/src/models/Spec.d.ts b/src/models/Spec.d.ts
index 64aa5da..e4e2fa2 100644
--- a/src/models/Spec.d.ts
+++ b/src/models/Spec.d.ts
@@ -316,6 +316,12 @@ declare class Spec {
   expectJsonMatchStrict(value: object): Spec;
   expectJsonMatchStrict(path: string, value: object): Spec;
 
+  /**
+   * expects the json to an array with length
+   */
+   expectJsonLength(value: number): Spec;
+   expectJsonLength(path: string, value: number): Spec;
+
   /**
    * expect network errors
    * @see https://pactumjs.github.io/#/response-validation?id=expecterror
diff --git a/src/models/Spec.js b/src/models/Spec.js
index 4082900..c95edd7 100644
--- a/src/models/Spec.js
+++ b/src/models/Spec.js
@@ -404,6 +404,11 @@ class Spec {
     return this;
   }
 
+  expectJsonLength(path, value) {
+    typeof value === 'undefined' ? this._expect.jsonLength.push(path) : this._expect.jsonLengthQuery.push({ path, value });
+    return this;
+  }
+
   expectError(error) {
     this._expect.errors.push(error);
     return this;
diff --git a/src/models/expect.js b/src/models/expect.js
index e5a64a1..d8d557e 100644
--- a/src/models/expect.js
+++ b/src/models/expect.js
@@ -32,6 +32,8 @@ class Expect {
     this.jsonMatchStrict = [];
     this.jsonMatchStrictQuery = [];
     this.jsonSnapshot = [];
+    this.jsonLength = [];
+    this.jsonLengthQuery = [];
     this.headers = [];
     this.headerContains = [];
     this.responseTime = null;
@@ -57,6 +59,8 @@ class Expect {
     this._validateJsonMatchQuery(response);
     this._validateJsonMatchStrict(response);
     this._validateJsonMatchStrictQuery(response);
+    this._validateJsonLength(response);
+    this._validateJsonLengthQuery(response);
     this._validateJsonSnapshot(response);
     this._validateResponseTime(response);
     this._validateErrors(response);
@@ -354,6 +358,33 @@ class Expect {
     }
   }
 
+  _validateJsonLength(response) {
+    this.jsonLength = processor.processData(this.jsonLength);
+    for (let i = 0; i < this.jsonLength.length; i++) {
+      const expected = this.jsonLength[i];
+      if (response.json && Array.isArray(response.json)) {
+        const actual = response.json.length;
+        assert.strictEqual(actual, expected, `JSON Length ${actual} !== ${expected}`);
+      } else {
+        this.fail('Response does not contain a json array');
+      }
+    }
+  }
+
+  _validateJsonLengthQuery(response) {
+    this.jsonLengthQuery = processor.processData(this.jsonLengthQuery);
+    for (let i = 0; i < this.jsonLengthQuery.length; i++) {
+      const { path, value: expected } = this.jsonLengthQuery[i];
+      const actualValue = jqy(path, { data: response.json }).value;
+      if (actualValue && Array.isArray(actualValue)) {
+        const actual = actualValue.length;
+        assert.strictEqual(actual, expected, `JSON Length ${actual} !== ${expected}`);
+      } else {
+        this.fail(`Response does not contain a json array at '${path}'`);
+      }
+    }
+  }
+
   _validateResponseTime(response) {
     this.responseTime = processor.processData(this.responseTime);
     if (this.responseTime !== null) {
diff --git a/src/models/server.js b/src/models/server.js
index 36631a6..bb40d34 100644
--- a/src/models/server.js
+++ b/src/models/server.js
@@ -27,6 +27,7 @@ class Server {
         registerAllRoutes(this, this.app);
         this.app.listen(config.mock.port, () => {
           log.info(`Mock server is listening on port ${config.mock.port}`);
+          this._registerEvents();
           resolve();
         });
       } else {
@@ -78,6 +79,15 @@ class Server {
     }
   }
 
+  _registerEvents() {
+    process.on('SIGTERM', () => {
+      if (this.app) {
+        log.warn('Termination Signal Received - SIGTERM');
+        this.stop();
+      }
+    });
+  }
+
 }
 
 /**


Test patch:
diff --git a/test/component/base.spec.js b/test/component/base.spec.js
index 86661fe..bd67645 100644
--- a/test/component/base.spec.js
+++ b/test/component/base.spec.js
@@ -82,6 +82,22 @@ function addDefaultMockHandlers() {
       }
     };
   });
+  handler.addInteractionHandler('default users', () => {
+    return {
+      request: {
+        method: 'GET',
+        path: '/default/users'
+      },
+      response: {
+        status: 200,
+        body: [
+          { name: 'Matt', country: 'NZ' },
+          { name: 'Pete', country: 'AU' },
+          { name: 'Mike', country: 'NZ' }
+        ]
+      }
+    };
+  });
 }
 
 before(async () => {
diff --git a/test/component/bdd.spec.js b/test/component/bdd.spec.js
index 734c06c..098efc3 100644
--- a/test/component/bdd.spec.js
+++ b/test/component/bdd.spec.js
@@ -158,6 +158,26 @@ describe('BDD', () => {
     ce(spec.returns('name')).equals('snow');
   });
 
+  it('should not have a json with length', async () => {
+    let err;
+    try {
+      await expect(response).to.have.jsonLength(1);
+    } catch (error) {
+      err = error;
+    }
+    ce(err).not.undefined;
+  });
+
+  it('should not have a json with length at some path', async () => {
+    let err;
+    try {
+      await expect(response).to.have.jsonLength('path', 1);
+    } catch (error) {
+      err = error;
+    }
+    ce(err).not.undefined;
+  });
+
 });
 
 describe('BDD - AutoReportRunner Disabled', () => {
diff --git a/test/component/expects.spec.js b/test/component/expects.spec.js
index 80d185e..2a66680 100644
--- a/test/component/expects.spec.js
+++ b/test/component/expects.spec.js
@@ -65,7 +65,8 @@ describe('Expects', () => {
     try {
       await pactum.spec()
         .get('http://localhost:9393/api/users/1')
-        .expect('isAddress');
+        .expect('isAddress')
+        .useLogLevel('ERROR');
     } catch (error) {
       err = error;
     }
@@ -89,7 +90,8 @@ describe('Expects', () => {
           }
         })
         .get('http://localhost:9393/api/address/1')
-        .expect('hasAddress', 'HOME');
+        .expect('hasAddress', 'HOME')
+        .useLogLevel('ERROR');
     } catch (error) {
       err = error;
     }
@@ -114,7 +116,8 @@ describe('Expects', () => {
         })
         .get('http://localhost:9393/api/users/1')
         .expect((res) => { expect(res.json).deep.equals({ id: 2 }); })
-        .expectStatus(200);
+        .expectStatus(200)
+        .useLogLevel('ERROR');
     } catch (error) {
       err = error;
     }
@@ -126,7 +129,8 @@ describe('Expects', () => {
     try {
       await pactum.spec()
         .get('http://localhost:9393/api/users/1')
-        .expectStatus(200);
+        .expectStatus(200)
+        .useLogLevel('ERROR');
     } catch (error) {
       err = error;
     }
@@ -138,7 +142,8 @@ describe('Expects', () => {
     try {
       await pactum.spec()
         .get('http://localhost:9393/api/users/1')
-        .expectHeader('x-header', 'value');
+        .expectHeader('x-header', 'value')
+        .useLogLevel('ERROR');
     } catch (error) {
       err = error;
     }
@@ -150,7 +155,8 @@ describe('Expects', () => {
     try {
       await pactum.spec()
         .get('http://localhost:9393/api/users/1')
-        .expectHeader('connection', 'value');
+        .expectHeader('connection', 'value')
+        .useLogLevel('ERROR');
     } catch (error) {
       err = error;
     }
@@ -162,7 +168,8 @@ describe('Expects', () => {
     try {
       await pactum.spec()
         .get('http://localhost:9393/api/users/1')
-        .expectHeader('connection', /value/);
+        .expectHeader('connection', /value/)
+        .useLogLevel('ERROR');
     } catch (error) {
       err = error;
     }
@@ -174,7 +181,8 @@ describe('Expects', () => {
     try {
       await pactum.spec()
         .get('http://localhost:9393/api/users/1')
-        .expectHeaderContains('x-header', 'value');
+        .expectHeaderContains('x-header', 'value')
+        .useLogLevel('ERROR');
     } catch (error) {
       err = error;
     }
@@ -186,7 +194,8 @@ describe('Expects', () => {
     try {
       await pactum.spec()
         .get('http://localhost:9393/api/users/1')
-        .expectHeaderContains('connection', 'value');
+        .expectHeaderContains('connection', 'value')
+        .useLogLevel('ERROR');
     } catch (error) {
       err = error;
     }
@@ -198,7 +207,8 @@ describe('Expects', () => {
     try {
       await pactum.spec()
         .get('http://localhost:9393/api/users/1')
-        .expectHeaderContains('connection', /value/);
+        .expectHeaderContains('connection', /value/)
+        .useLogLevel('ERROR');
     } catch (error) {
       err = error;
     }
@@ -210,7 +220,8 @@ describe('Expects', () => {
     try {
       await pactum.spec()
         .get('http://localhost:9393/api/users/1')
-        .expectBody('Hello World');
+        .expectBody('Hello World')
+        .useLogLevel('ERROR');
     } catch (error) {
       err = error;
     }
@@ -222,7 +233,8 @@ describe('Expects', () => {
     try {
       await pactum.spec()
         .get('http://localhost:9393/api/users/1')
-        .expectBodyContains('Hello World');
+        .expectBodyContains('Hello World')
+        .useLogLevel('ERROR');
     } catch (error) {
       err = error;
     }
@@ -234,7 +246,8 @@ describe('Expects', () => {
     try {
       await pactum.spec()
         .get('http://localhost:9393/api/users/1')
-        .expectBodyContains({ msg: 'Hello World' });
+        .expectBodyContains({ msg: 'Hello World' })
+        .useLogLevel('ERROR');
     } catch (error) {
       err = error;
     }
@@ -246,7 +259,8 @@ describe('Expects', () => {
     try {
       await pactum.spec()
         .get('http://localhost:9393/api/users/1')
-        .expectBodyContains(/Hello World/);
+        .expectBodyContains(/Hello World/)
+        .useLogLevel('ERROR');
     } catch (error) {
       err = error;
     }
@@ -258,7 +272,8 @@ describe('Expects', () => {
     try {
       await pactum.spec()
         .get('http://localhost:9393/api/users/1')
-        .expectJsonLike({ id: 1 });
+        .expectJsonLike({ id: 1 })
+        .useLogLevel('ERROR');
     } catch (error) {
       err = error;
     }
@@ -284,7 +299,8 @@ describe('Expects', () => {
         .get('http://localhost:9393/api/users/1')
         .expectJsonSchema({
           "required": ["userId", "id"]
-        });
+        })
+        .useLogLevel('ERROR');
     } catch (error) {
       err = error;
     }
@@ -310,7 +326,8 @@ describe('Expects', () => {
         .get('http://localhost:9393/api/users/1')
         .expectJsonSchema('id', {
           "type": "string"
-        });
+        })
+        .useLogLevel('ERROR');
     } catch (error) {
       err = error;
     }
@@ -322,7 +339,8 @@ describe('Expects', () => {
     try {
       await pactum.spec()
         .get('http://localhost:9393/api/users/1')
-        .expectJsonMatch(like({ id: 1 }));
+        .expectJsonMatch(like({ id: 1 }))
+        .useLogLevel('ERROR');
     } catch (error) {
       err = error;
     }
@@ -336,7 +354,8 @@ describe('Expects', () => {
         .get('http://localhost:9394/api/users/1')
         .expectJsonSchema({
           "required": ["userId", "id"]
-        });
+        })
+        .useLogLevel('ERROR');
     } catch (error) {
       err = error;
     }
@@ -357,7 +376,8 @@ describe('Expects', () => {
           }
         })
         .get('http://localhost:9393/api/users/1')
-        .expectStatus(200);
+        .expectStatus(200)
+        .useLogLevel('ERROR');
     } catch (error) {
       err = error;
     }
@@ -384,7 +404,8 @@ describe('Expects', () => {
           }
         })
         .get('http://localhost:9393/api/users/1')
-        .expectStatus(200);
+        .expectStatus(200)
+        .useLogLevel('ERROR');
     } catch (error) {
       err = error;
     }
@@ -408,7 +429,8 @@ describe('Expects', () => {
           }
         })
         .get('http://localhost:9393/api')
-        .expectStatus(200);
+        .expectStatus(200)
+        .useLogLevel('ERROR');
     } catch (error) {
       err = error;
     }
@@ -432,7 +454,8 @@ describe('Expects', () => {
           }
         })
         .get('http://localhost:9393/api')
-        .expectStatus(200);
+        .expectStatus(200)
+        .useLogLevel('ERROR');
     } catch (error) {
       err = error;
     }
@@ -509,7 +532,8 @@ describe('Expects', () => {
         .get('http://localhost:9393/api/users')
         .expectStatus(200)
         .expectJson('people[country=NZ].name', 'Matt')
-        .expectJson('people[*].name', ['Matt', 'Pete']);
+        .expectJson('people[*].name', ['Matt', 'Pete'])
+        .useLogLevel('ERROR');
     } catch (error) {
       err = error;
     }
@@ -561,7 +585,8 @@ describe('Expects', () => {
         })
         .get('http://localhost:9393/api/users')
         .expectStatus(200)
-        .expectJsonLike('people[*].name', ['Matt', 'Pet']);
+        .expectJsonLike('people[*].name', ['Matt', 'Pet'])
+        .useLogLevel('ERROR');
     } catch (error) {
       err = error;
     }
@@ -573,7 +598,8 @@ describe('Expects', () => {
     try {
       await pactum.spec()
         .get('http://localhost:9393/api/users/1')
-        .expectResponseTime(-1);
+        .expectResponseTime(-1)
+        .useLogLevel('ERROR');
     } catch (error) {
       err = error;
     }
@@ -625,7 +651,8 @@ describe('Expects', () => {
         })
         .get('http://localhost:9393/api/users')
         .expectStatus(200)
-        .expectJsonMatch('people[*].name', eachLike(12));
+        .expectJsonMatch('people[*].name', eachLike(12))
+        .useLogLevel('ERROR');
     } catch (error) {
       err = error;
     }
@@ -647,7 +674,8 @@ describe('Expects', () => {
         .useInteraction('get people')
         .get('http://localhost:9393/api/people')
         .expectStatus(200)
-        .expectJsonMatchStrict('people[*].name', eachLike(12));
+        .expectJsonMatchStrict('people[*].name', eachLike(12))
+        .useLogLevel('ERROR');
     } catch (error) {
       err = error;
     }
@@ -675,7 +703,8 @@ describe('Expects', () => {
         .useInteraction('get people')
         .get('http://localhost:9393/api/people')
         .expectStatus(200)
-        .expectJsonMatchStrict({});
+        .expectJsonMatchStrict({})
+        .useLogLevel('ERROR');
     } catch (error) {
       err = error;
     }
@@ -736,7 +765,8 @@ describe('Expects', () => {
         .name('json snapshot - deep equal')
         .get('http://localhost:9393/api/users/1')
         .expectStatus(200)
-        .expectJsonSnapshot();
+        .expectJsonSnapshot()
+        .useLogLevel('ERROR');
     } catch (error) {
       err = error;
     }
@@ -859,7 +889,8 @@ describe('Expects', () => {
         .expectStatus(200)
         .expectJsonSnapshot({
           id: like('id')
-        });
+        })
+        .useLogLevel('ERROR');
     } catch (error) {
       err = error;
     }
@@ -897,7 +928,8 @@ describe('Expects', () => {
         .expectStatus(200)
         .expectJsonSnapshot({
           id: like('id')
-        });
+        })
+        .useLogLevel('ERROR');
     } catch (error) {
       err = error;
     }
@@ -935,7 +967,8 @@ describe('Expects', () => {
         .expectStatus(200)
         .expectJsonSnapshot({
           id: like('id')
-        });
+        })
+        .useLogLevel('ERROR');
     } catch (error) {
       err1 = error;
     }
@@ -947,7 +980,8 @@ describe('Expects', () => {
         .expectStatus(200)
         .expectJsonSnapshot({
           id: like(1)
-        });
+        })
+        .useLogLevel('ERROR');
     } catch (error) {
       err2 = error;
     }
@@ -997,7 +1031,8 @@ describe('Expects', () => {
       await pactum.spec()
         .useInteraction('default get')
         .get('http://localhost:9393/default/get')
-        .expectError();
+        .expectError()
+        .useLogLevel('ERROR');
     } catch (error) {
       err = error;
     }
@@ -1009,7 +1044,8 @@ describe('Expects', () => {
     try {
       await pactum.spec()
         .get('http://localhost:9392')
-        .expectError('ECONNRESET');
+        .expectError('ECONNRESET')
+        .useLogLevel('ERROR');
     } catch (error) {
       err = error;
     }
@@ -1021,7 +1057,8 @@ describe('Expects', () => {
     try {
       await pactum.spec()
         .get('http://localhost:9392')
-        .expectError({ code: 'ECONNRESET' });
+        .expectError({ code: 'ECONNRESET' })
+        .useLogLevel('ERROR');
     } catch (error) {
       err = error;
     }
@@ -1061,4 +1098,74 @@ describe('Expects', () => {
       });
   });
 
+  it('json length', async () => {
+    await pactum.spec()
+      .useInteraction('default users')
+      .get('http://localhost:9393/default/users')
+      .expectJsonLength(3);
+  });
+
+  it('json length - fail', async () => {
+    let err;
+    try {
+      await pactum.spec()
+        .useInteraction('default users')
+        .get('http://localhost:9393/default/users')
+        .expectJsonLength(2)
+        .useLogLevel('ERROR');
+    } catch (error) {
+      err = error;
+    }
+    expect(err).not.undefined;
+  });
+
+  it('json length - fail - invalid', async () => {
+    let err;
+    try {
+      await pactum.spec()
+        .useInteraction('default get')
+        .get('http://localhost:9393/default/get')
+        .expectJsonLength(2)
+        .useLogLevel('ERROR');
+    } catch (error) {
+      err = error;
+    }
+    expect(err).not.undefined;
+  });
+
+  it('json length query', async () => {
+    await pactum.spec()
+      .useInteraction('get people')
+      .get('http://localhost:9393/api/people')
+      .expectJsonLength('people', 3);
+  });
+
+  it('json length - fail', async () => {
+    let err;
+    try {
+      await pactum.spec()
+        .useInteraction('get people')
+        .get('http://localhost:9393/api/people')
+        .expectJsonLength('people', 2)
+        .useLogLevel('ERROR');
+    } catch (error) {
+      err = error;
+    }
+    expect(err).not.undefined;
+  });
+
+  it('json length - fail - invalid', async () => {
+    let err;
+    try {
+      await pactum.spec()
+        .useInteraction('get people')
+        .get('http://localhost:9393/api/people')
+        .expectJsonLength('people[0]', 2)
+        .useLogLevel('ERROR');
+    } catch (error) {
+      err = error;
+    }
+    expect(err).not.undefined;
+  });
+
 });
\ No newline at end of file