How to test Tailor Platform apps
Introduction
Ensuring the reliability and robustness of applications is essential. To verify that the business logic in your Pipeline resolver is working as expected, we strongly recommend writing API tests for your application.
In this guide, you will learn how to test Tailor DB and Pipeline using the API Test Library.
Setup
Folder Structure
Create a folder in your template to store the test files using the following folder structure. Here, we use a tests
folder as an example.
<span><span style="color: var(--shiki-color-text)">tempalate </span><span style="color: var(--shiki-token-comment)">// Root folder for an app</span></span>
<span><span style="color: var(--shiki-color-text)">├── tests</span></span>
<span><span style="color: var(--shiki-color-text)">│ └── data </span><span style="color: var(--shiki-token-comment)">// contains the data in the json format</span></span>
<span><span style="color: var(--shiki-color-text)">│ └── </span><span style="color: var(--shiki-token-constant)">salesOrder</span><span style="color: var(--shiki-color-text)">.json</span></span>
<span><span style="color: var(--shiki-color-text)">│ └── tests</span></span>
<span><span style="color: var(--shiki-color-text)">│ └── </span><span style="color: var(--shiki-token-constant)">createShipmentFromSalesOrder</span><span style="color: var(--shiki-color-text)">.</span><span style="color: var(--shiki-token-constant)">test</span><span style="color: var(--shiki-color-text)">.js</span></span>
<span></span>
Create test data
Create json files with the following format.
<span><span style="color: var(--shiki-color-text)">{</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">"TableName"</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">"customName"</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">"key1"</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"value1"</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">"key2"</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"value2"</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span></span>
<span><span style="color: var(--shiki-color-text)">}</span></span>
<span></span>
For example:
<span><span style="color: var(--shiki-color-text)">{</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">"SalesOrder"</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">"salesOrder1"</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">"name"</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"Test SalesOrder1"</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span></span>
<span><span style="color: var(--shiki-color-text)">}</span></span>
<span></span>
The file names can be arbitrary as they do not affect the operation of the tests.
Write a test with API Test Library
Understanding context.env
The JSON files located in the data folder is loaded to the context.env
object. All fields of the data type will automatically be fetched even if they are not defined in the JSON file.
For example, you can access salesOrder1.createdAt even if its not defined. You can access data to a depth of up to 3 levels in the context. For example, you can access context.env.SalesOrder.salesOrder1.shipment.customerID
.
To create a new record, add it to the context. Below is an example that demonstrates adding a new sales order to the context.
<span><span style="color: var(--shiki-token-keyword)">const</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">newSalesOrder</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">context</span><span style="color: var(--shiki-token-function)">.create</span><span style="color: var(--shiki-color-text)">(</span><span style="color: var(--shiki-token-string-expression)">"SalesOrder"</span><span style="color: var(--shiki-token-punctuation)">,</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)"> shippedAt</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"2024-06-25T19:34:42Z"</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)"> customerID</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"e9685c48-621e-5bdf-8745-95e2a7864e23"</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)"> orderNumber</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"123"</span></span>
<span><span style="color: var(--shiki-color-text)">});</span></span>
<span><span style="color: var(--shiki-token-constant)">context</span><span style="color: var(--shiki-token-function)">.addToEnv</span><span style="color: var(--shiki-color-text)">(</span><span style="color: var(--shiki-token-string-expression)">"SalesOrder"</span><span style="color: var(--shiki-token-punctuation)">,</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">" salesOrder2"</span><span style="color: var(--shiki-token-punctuation)">,</span><span style="color: var(--shiki-color-text)"> newSalesOrder);</span></span>
<span></span>
All of the data in context.env will automatically be deleted after running the test.
Test Pipelines
If you create a pipeline in your app and want to test it, you can achieve this by running the runPipeline
method with the first argument as the pipeline name and the second argument as the input to the pipeline.
Here's how you can test createShipmentFromSalesOrder
pipeline in the Inventory Management System template.
<span><span style="color: var(--shiki-token-keyword)">import</span><span style="color: var(--shiki-color-text)"> { context } </span><span style="color: var(--shiki-token-keyword)">from</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"@tailor-platform/api-test-library"</span><span style="color: var(--shiki-color-text)">;</span></span>
<span></span>
<span><span style="color: var(--shiki-token-comment)">/**</span></span>
<span><span style="color: var(--shiki-token-comment)"> * Test createShipmentFromSalesOrder</span></span>
<span><span style="color: var(--shiki-token-comment)"> * Creates ShipOut from the sales order</span></span>
<span><span style="color: var(--shiki-token-comment)"> * and checks if the ship out is created</span></span>
<span><span style="color: var(--shiki-token-comment)">*/</span></span>
<span><span style="color: var(--shiki-token-function)">test</span><span style="color: var(--shiki-color-text)">(</span><span style="color: var(--shiki-token-string-expression)">"1. createShipmentFromSalesOrder"</span><span style="color: var(--shiki-token-punctuation)">,</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">async</span><span style="color: var(--shiki-color-text)"> () </span><span style="color: var(--shiki-token-keyword)">=></span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-comment)">// get sales order</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">const</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">salesOrder</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">context</span><span style="color: var(--shiki-color-text)">.</span><span style="color: var(--shiki-token-constant)">env</span><span style="color: var(--shiki-color-text)">.</span><span style="color: var(--shiki-token-constant)">SalesOrder</span><span style="color: var(--shiki-color-text)">.salesOrder1;</span></span>
<span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-comment)">// run the pipeline</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">await</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">context</span><span style="color: var(--shiki-token-function)">.runPipeline</span><span style="color: var(--shiki-color-text)">(</span><span style="color: var(--shiki-token-string-expression)">"createShipmentFromSalesOrder"</span><span style="color: var(--shiki-token-punctuation)">,</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)"> input</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)"> salesOrderID</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">salesOrder</span><span style="color: var(--shiki-color-text)">.id</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)"> markAsShipped</span><span style="color: var(--shiki-token-keyword)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">false</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span></span>
<span><span style="color: var(--shiki-color-text)"> });</span></span>
<span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-comment)">// Fetch ship out created from sales order</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">const</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">shipmentAll</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">await</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">context</span><span style="color: var(--shiki-token-function)">.fetchAll</span><span style="color: var(--shiki-color-text)">(</span><span style="color: var(--shiki-token-string-expression)">"Shipment"</span><span style="color: var(--shiki-color-text)">);</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">const</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">shipment</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">shipmentAll</span><span style="color: var(--shiki-token-function)">.find</span><span style="color: var(--shiki-color-text)">(shipmentItem </span><span style="color: var(--shiki-token-keyword)">=></span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">shipmentItem</span><span style="color: var(--shiki-color-text)">.salesOrderID </span><span style="color: var(--shiki-token-keyword)">===</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">salesOrder</span><span style="color: var(--shiki-color-text)">.id);</span></span>
<span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-comment)">// Add shipment to the context </span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">context</span><span style="color: var(--shiki-token-function)">.addToEnv</span><span style="color: var(--shiki-color-text)">(</span><span style="color: var(--shiki-token-string-expression)">"Shipment"</span><span style="color: var(--shiki-token-punctuation)">,</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">shipment</span><span style="color: var(--shiki-color-text)">.id</span><span style="color: var(--shiki-token-punctuation)">,</span><span style="color: var(--shiki-color-text)"> shipment);</span></span>
<span><span style="color: var(--shiki-color-text)"> </span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">expect</span><span style="color: var(--shiki-color-text)">(</span><span style="color: var(--shiki-token-constant)">shipment</span><span style="color: var(--shiki-color-text)">.customerID)</span><span style="color: var(--shiki-token-function)">.toBe</span><span style="color: var(--shiki-color-text)">(</span><span style="color: var(--shiki-token-constant)">shipment</span><span style="color: var(--shiki-color-text)">.</span><span style="color: var(--shiki-token-constant)">salesOrder</span><span style="color: var(--shiki-color-text)">.customerID);</span></span>
<span><span style="color: var(--shiki-color-text)"> </span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">console</span><span style="color: var(--shiki-token-function)">.info</span><span style="color: var(--shiki-color-text)">(</span><span style="color: var(--shiki-token-string-expression)">"Shipment created from sales order"</span><span style="color: var(--shiki-color-text)">);</span></span>
<span><span style="color: var(--shiki-color-text)">}</span><span style="color: var(--shiki-token-punctuation)">,</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">30000</span><span style="color: var(--shiki-color-text)">); </span></span>
<span></span>
The data in context.env will be automatically refreshed after the runPipeline
runs.