Repository: pactumjs/pactum
Pull request #275 (2023-04-11 03:43:45)

Feat store with custom function
the issue link: https://github.com/pactumjs/pactum/issues/274


Patch:
diff --git a/src/helpers/toss.helper.js b/src/helpers/toss.helper.js
index 8a92dd1..7332858 100644
--- a/src/helpers/toss.helper.js
+++ b/src/helpers/toss.helper.js
@@ -40,6 +40,11 @@ function storeSpecData(spec, stores) {
   const ctx = { req: spec._request, res: spec._response, store: stash.getDataStore() };
   for (let i = 0; i < stores.length; i++) {
     const store = stores[i];
+    if (typeof store === 'function') {
+      const specData = store(spec._request, spec._response);
+      stash.addDataStore(specData);
+      continue;
+    }
     const specData = {};
     const captureHandler = getCaptureHandlerName(store.path);
     if (captureHandler) {
diff --git a/src/models/Spec.d.ts b/src/models/Spec.d.ts
index 014a15f..77fca6f 100644
--- a/src/models/Spec.d.ts
+++ b/src/models/Spec.d.ts
@@ -368,6 +368,7 @@ declare class Spec {
    */
   stores(name: string, path: string): Spec;
   stores(name: string, handlerName: string): Spec;
+  stores<T extends Record<string, any>>(fn: (request: Request, response: IncomingMessage) => T): Spec;
 
   /**
    * returns custom response from json response using custom handler
diff --git a/src/models/Spec.js b/src/models/Spec.js
index 993b5bc..fd6e142 100644
--- a/src/models/Spec.js
+++ b/src/models/Spec.js
@@ -453,11 +453,21 @@ class Spec {
     return this;
   }
 
-  stores(name, path) {
-    if (this._response) {
-      th.storeSpecData(this, [{ name, path }]);
-    } else {
-      this._stores.push({ name, path });
+  stores(...args) {
+    if (args.length === 1 && typeof args[0] === 'function') {
+      const fn = args[0];
+      if (this._response) {
+        th.storeSpecData(this, [fn]);
+      } else {
+        this._stores.push(fn);
+      }
+    } else if (args.length === 2) {
+      const [name, path] = args;
+      if (this._response) {
+        th.storeSpecData(this, [{ name, path }]);
+      } else {
+        this._stores.push({ name, path });
+      }
     }
     return this;
   }


Test patch:
diff --git a/test/component/stores.spec.js b/test/component/stores.spec.js
index 59de148..dfaeed4 100644
--- a/test/component/stores.spec.js
+++ b/test/component/stores.spec.js
@@ -169,6 +169,92 @@ describe('Stores', () => {
       .expectStatus(200);
   });
 
+  it ('store single value by custom function', async () => {
+    await pactum.spec()
+      .useInteraction({
+        request: {
+          method: 'GET',
+          path: '/api/stores'
+        },
+        response: {
+          status: 200,
+          body: {
+            id: 1
+          }
+        }
+      })
+      .get('http://localhost:9393/api/stores')
+      .expectStatus(200)
+      .stores((request, response) => {
+        return {
+            custom_func_id: response.body.id
+        };
+      });
+      await pactum.spec()
+      .useInteraction({
+        request: {
+          method: 'POST',
+          path: '/api/stores',
+          body: {
+            UserId: 1
+          }
+        },
+        response: {
+          status: 200
+        }
+      })
+      .post('http://localhost:9393/api/stores')
+      .withJson({
+        UserId: '$S{custom_func_id}'
+      })
+      .expectStatus(200);
+  });
+
+  it ('store multiple value by custom function', async () => {
+    await pactum.spec()
+      .useInteraction({
+        request: {
+          method: 'GET',
+          path: '/api/stores'
+        },
+        response: {
+          status: 200,
+          body: {
+            id: 1,
+            email: 'test@gmail.com'
+          }
+        }
+      })
+      .get('http://localhost:9393/api/stores')
+      .expectStatus(200)
+      .stores((request, response) => {
+        return {
+            custom_func_id: response.body.id,
+            custom_func_email: response.body.email
+        };
+      });
+      await pactum.spec()
+      .useInteraction({
+        request: {
+          method: 'POST',
+          path: '/api/stores',
+          body: {
+            UserId: 1,
+            UserEmail: 'test@gmail.com'
+          }
+        },
+        response: {
+          status: 200
+        }
+      })
+      .post('http://localhost:9393/api/stores')
+      .withJson({
+        UserId: '$S{custom_func_id}',
+        UserEmail: '$S{custom_func_email}'
+      })
+      .expectStatus(200);
+  });
+
   it('store single value after response', async () => {
     const spec = pactum.spec();
     await spec
@@ -189,6 +275,30 @@ describe('Stores', () => {
       .expectStatus(200);
   });
 
+  it('store single value after response by custom function', async () => {
+    const spec = pactum.spec();
+    await spec
+      .useInteraction('get stores')
+      .get('http://localhost:9393/api/stores')
+      .expectStatus(200);
+    spec.stores((request, response) => {
+        return {
+            UserId: response.body.id
+        };
+    });
+    await pactum.spec()
+      .useInteraction('post stores')
+      .post('http://localhost:9393/api/stores')
+      .withJson({
+        UserId: '$S{UserId}'
+      })
+      .expectStatus(200);
+    await pactum.spec()
+      .useInteraction('post stores with id')
+      .post('http://localhost:9393/api/stores/$S{UserId}')
+      .expectStatus(200);
+  });
+
   afterEach(() => {
     stash.clearDataStores();
   });