11# Shopify Functions WASM Testing Helpers
22
3- A JavaScript library that rpovides helpers for testing Shopify Functions WASM (WebAssembly) modules. This library provides four core utilities: ` loadFixture ` , ` validateFixture ` , ` buildFunction ` , and ` runFunction ` .
3+ A JavaScript library that provides helpers for testing Shopify Functions WASM (WebAssembly) modules. This library provides utilities for loading fixtures, validating test assets, building functions , and running functions .
44
55## Installation
66
@@ -13,70 +13,258 @@ npm install @shopify/shopify-function-test-helpers
1313### Basic Usage
1414
1515``` javascript
16- const {
16+ import {
17+ buildFunction ,
1718 loadFixture ,
18- validateFixture ,
19+ loadSchema ,
20+ loadInputQuery ,
21+ validateTestAssets ,
22+ runFunction ,
23+ } from " @shopify/shopify-function-test-helpers" ;
24+
25+ // Load the GraphQL schema and input query
26+ const schema = await loadSchema (" /path/to/schema.graphql" );
27+ const inputQueryAST = await loadInputQuery (" /path/to/src/run.graphql" );
28+
29+ // Load a test fixture
30+ const fixture = await loadFixture (" /path/to/fixtures/my-test.json" );
31+
32+ // Build the function
33+ await buildFunction (" /path/to/function" );
34+
35+ // Validate the test assets
36+ const validationResult = await validateTestAssets ({
37+ schema,
38+ fixture,
39+ inputQueryAST,
40+ });
41+
42+ console .log (` Input Query: ${ validationResult .inputQuery .valid ? ' ✅' : ' ❌' } ` );
43+ console .log (` Input Fixture: ${ validationResult .inputFixture .valid ? ' ✅' : ' ❌' } ` );
44+ console .log (` Input Query-Fixture Match: ${ validationResult .inputQueryFixtureMatch .valid ? ' ✅' : ' ❌' } ` );
45+ console .log (` Output Fixture: ${ validationResult .outputFixture .valid ? ' ✅' : ' ❌' } ` );
46+
47+ // Run the function
48+ const runResult = await runFunction (
49+ fixture .export ,
50+ fixture .input ,
51+ " /path/to/function"
52+ );
53+
54+ console .log (" Output:" , runResult .result .output );
55+ console .log (" Expected:" , fixture .expectedOutput );
56+ ```
57+
58+ ### Complete Test Example
59+
60+ For a full test suite that runs multiple fixtures:
61+
62+ ``` javascript
63+ import path from " path" ;
64+ import fs from " fs" ;
65+ import {
1966 buildFunction ,
20- runFunction
21- } = require (' @shopify/shopify-function-test-helpers' );
67+ loadFixture ,
68+ runFunction ,
69+ validateTestAssets ,
70+ loadSchema ,
71+ loadInputQuery ,
72+ } from " @shopify/shopify-function-test-helpers" ;
73+
74+ describe (" Function Tests" , () => {
75+ let schema;
76+ let inputQueryAST;
77+ let functionDir;
78+
79+ beforeAll (async () => {
80+ functionDir = path .dirname (__dirname );
81+ await buildFunction (functionDir);
82+
83+ const schemaPath = path .join (functionDir, " schema.graphql" );
84+ const inputQueryPath = path .join (functionDir, " src/run.graphql" );
85+
86+ schema = await loadSchema (schemaPath);
87+ inputQueryAST = await loadInputQuery (inputQueryPath);
88+ }, 10000 );
89+
90+ const fixturesDir = path .join (__dirname , " fixtures" );
91+ const fixtureFiles = fs
92+ .readdirSync (fixturesDir)
93+ .filter ((file ) => file .endsWith (" .json" ))
94+ .map ((file ) => path .join (fixturesDir, file));
95+
96+ fixtureFiles .forEach ((fixtureFile ) => {
97+ test (` runs ${ path .basename (fixtureFile)} ` , async () => {
98+ const fixture = await loadFixture (fixtureFile);
99+
100+ const validationResult = await validateTestAssets ({
101+ schema,
102+ fixture,
103+ inputQueryAST,
104+ });
105+
106+ expect (validationResult .inputQuery .valid ).toBe (true );
107+ expect (validationResult .inputFixture .valid ).toBe (true );
108+ expect (validationResult .inputQueryFixtureMatch .valid ).toBe (true );
109+ expect (validationResult .outputFixture .valid ).toBe (true );
110+
111+ const runResult = await runFunction (
112+ fixture .export ,
113+ fixture .input ,
114+ functionDir
115+ );
116+
117+ expect (runResult .error ).toBeNull ();
118+ expect (runResult .result .output ).toEqual (fixture .expectedOutput );
119+ }, 10000 );
120+ });
121+ });
122+ ```
22123
23- // Load a fixture from test data
24- const fixture = loadFixture (' 20250915_184036_156Z_extensions_cart-checkout-validation_ba711d.json' );
124+ ## API Reference
125+
126+ ### Core Functions
127+
128+ #### ` loadFixture(fixturePath) `
129+
130+ Loads a fixture file from the specified path.
25131
26- // Validate the fixture structure
27- const validation = validateFixture (fixture);
28- console . log ( ' Is valid: ' , validation . isValid );
132+ ** Parameters: **
133+
134+ - ` fixturePath ` (string): Path to the fixture JSON file
29135
30- // Build a function
31- const payload = buildFunction ();
136+ ** Returns:** Promise<FixtureData > - Fixture object containing ` export ` , ` input ` , ` expectedOutput ` , and ` target `
32137
33- // Run a function implementation
138+ ** Example: **
34139
35- const result = runFunction (payload, mockFunction);
36- console . log ( ' Result status: ' , result . status );
140+ ``` javascript
141+ const fixture = await loadFixture ( " ./fixtures/my-test.json " );
37142```
38143
39- ## API Reference
144+ ---
40145
41- ### Functions
146+ #### ` loadSchema(schemaPath) `
42147
43- #### ` loadFixture(filename) `
44- Loads a fixture from the test_data directory.
148+ Loads a GraphQL schema from a file.
45149
46150** Parameters:**
47- - ` filename ` : Name of the fixture file
48151
49- ** Returns: ** Fixture object
152+ - ` schemaPath ` (string): Path to the schema.graphql file
50153
51- ** Throws :** Error if fixture file is not found
154+ ** Returns :** Promise< GraphQLSchema > - Parsed GraphQL schema
52155
53- #### ` validateFixture(fixture) `
54- Validates a fixture to ensure it has the correct structure.
156+ ** Example:**
157+
158+ ``` javascript
159+ const schema = await loadSchema (" ./schema.graphql" );
160+ ```
161+
162+ ---
163+
164+ #### ` loadInputQuery(queryPath) `
165+
166+ Loads and parses a GraphQL input query.
55167
56168** Parameters:**
57- - ` fixture ` : The fixture data to validate
58169
59- ** Returns:** ValidationResult object with ` isValid ` boolean and ` errors ` array
170+ - ` queryPath ` (string): Path to the GraphQL query file
171+
172+ ** Returns:** Promise<DocumentNode > - Parsed GraphQL query AST
173+
174+ ** Example:**
175+
176+ ``` javascript
177+ const inputQueryAST = await loadInputQuery (" ./src/run.graphql" );
178+ ```
179+
180+ ---
181+
182+ #### ` validateTestAssets(options) `
183+
184+ Validates test assets including input query, fixture input/output, and query-fixture match.
185+
186+ ** Parameters:**
187+
188+ - ` options ` (ValidateTestAssetsOptions):
189+ - ` schema ` (GraphQLSchema): The GraphQL schema
190+ - ` fixture ` (FixtureData): The fixture to validate
191+ - ` inputQueryAST ` (DocumentNode): The input query AST
192+ - ` mutationName ` (string, optional): The mutation name (auto-detected if not provided)
193+ - ` resultParameterName ` (string, optional): The result parameter name (auto-detected if not provided)
194+
195+ ** Returns:** Promise<CompleteValidationResult > - Validation results for all validation steps:
196+
197+ - ` inputQuery ` : { valid: boolean, errors: readonly GraphQLError[ ] }
198+ - ` inputFixture ` : { valid: boolean, errors: string[ ] , data: any }
199+ - ` inputQueryFixtureMatch ` : { valid: boolean, errors: string[ ] }
200+ - ` outputFixture ` : { valid: boolean, errors: { message: string }[ ] , mutationName: string | null, resultParameterType: string | null }
201+ - ` mutationName? ` : string - Auto-detected mutation name
202+ - ` resultParameterName? ` : string - Auto-detected result parameter name
203+ - ` error? ` : string - Top-level error if validation fails
204+
205+ ** Example:**
206+
207+ ``` javascript
208+ const validationResult = await validateTestAssets ({
209+ schema,
210+ fixture,
211+ inputQueryAST,
212+ });
213+
214+ // Log validation results
215+ console .log (` Input Query: ${ validationResult .inputQuery .valid ? ' ✅' : ' ❌' } ` );
216+ console .log (` Input Fixture: ${ validationResult .inputFixture .valid ? ' ✅' : ' ❌' } ` );
217+ console .log (` Input Query-Fixture Match: ${ validationResult .inputQueryFixtureMatch .valid ? ' ✅' : ' ❌' } ` );
218+ console .log (` Output Fixture: ${ validationResult .outputFixture .valid ? ' ✅' : ' ❌' } ` );
219+ ```
220+
221+ ---
60222
61223#### ` buildFunction(functionPath?) `
224+
62225Builds a Shopify function using the Shopify CLI.
63226
64227** Parameters:**
65- - ` functionPath ` (optional): Path to the function directory. If not provided, will auto-detect from current working directory.
66228
67- ** Returns:** Promise that resolves to build result object with ` success ` , ` output ` , and ` error ` properties.
229+ - ` functionPath ` (string, optional): Path to the function directory. If not provided, will auto-detect from current working directory.
230+
231+ ** Returns:** Promise<BuildFunctionResult > - Build result with ` success ` , ` output ` , and ` error ` properties
232+
233+ ** Example:**
234+
235+ ``` javascript
236+ const buildResult = await buildFunction (" /path/to/function" );
237+ if (! buildResult .success ) {
238+ console .error (" Build failed:" , buildResult .error );
239+ }
240+ ```
241+
242+ ---
68243
69244#### ` runFunction(exportName, input, functionPath?) `
245+
70246Runs a Shopify function using the Shopify CLI.
71247
72248** Parameters:**
73- - ` exportName ` : The export name of the function to run
74- - ` input ` : The input data to pass to the function
75- - ` functionPath ` (optional): Path to the function directory. If not provided, will auto-detect from current working directory.
76249
77- ** Returns:** Promise that resolves to result object with ` result ` and ` error ` properties.
250+ - ` exportName ` (string): The export name of the function to run
251+ - ` input ` (object): The input data to pass to the function
252+ - ` functionPath ` (string, optional): Path to the function directory. If not provided, will auto-detect from current working directory.
253+
254+ ** Returns:** Promise<RunFunctionResult > - Result object with:
255+ - ` result ` : { output: any } | null - The function execution result
256+ - ` error ` : string | null - Error message if execution failed
257+
258+ ** Example:**
259+
260+ ``` javascript
261+ const runResult = await runFunction (" run" , fixtureInput, " /path/to/function" );
262+ console .log (" Function output:" , runResult .result .output );
263+ ```
264+
265+ ** Note:** Both ` buildFunction ` and ` runFunction ` will automatically detect the function directory by looking for ` shopify.function.toml ` in common locations (current directory, src/, functions/, extensions/).
78266
79- ** Note: ** Both functions will automatically detect the function directory by looking for ` shopify.function.toml ` in common locations (current directory, src/, functions/, extensions/). You can also provide a specific path if needed.
267+ ---
80268
81269## Development
82270
@@ -91,6 +279,15 @@ npm run test:watch
91279
92280# Run tests with coverage
93281npm run test:coverage
282+
283+ # Run example integration tests
284+ npm run test:examples
285+ ```
286+
287+ ### Building
288+
289+ ``` bash
290+ npm run build
94291```
95292
96293### Linting
1153124 . Add tests for your changes
1163135 . Run the test suite
1173146 . Submit a pull request
118-
119- ## Related
120-
121- - [ Tech Design] ( https://docs.google.com/document/d/1nmJge_seHPgJlzYgux6S90NEVPcYgn9uqimx9AXP_m8/edit?tab=t.0#heading=h.9zotah988fq7 )
0 commit comments