Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 98 additions & 0 deletions tests/fixtures/wix/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# Wix Product Option Fixture

## Scope

This fixture provides synthetic Wix Stores product options and variants for
future product synchronization work.

It does not make live Wix API calls and does not implement a Wix connector.

## Official Wix documentation

The fixture is based on the Wix Stores Catalog V3 product model.

- Wix Stores introduction:
https://dev.wix.com/docs/api-reference/business-solutions/stores/introduction

- Product options and variants:
https://dev.wix.com/docs/api-reference/business-solutions/stores/catalog-v3/about-product-options-and-variants

- Products V3:
https://dev.wix.com/docs/api-reference/business-solutions/stores/catalog-v3/products-v3/introduction

- Query Products:
https://dev.wix.com/docs/api-reference/business-solutions/stores/catalog-v3/products-v3/query-products

## Synthetic product

The fixture contains one synthetic product:

- Product: `Classic T-Shirt`
- Option 1: `Size`
- `Small`
- `Large`
- Option 2: `Color`
- `Red`
- `Blue`

The four option combinations are represented as separate synthetic variants.

## Expected Posnic mapping

The repository already uses the following item fields in its import fixtures:

- `SKU` -> `itemid`
- `Barcode` -> `barcode_id`

The existing variant-linking script also uses:

- `variant_group_id`
- `variant_axis`
- `variant_value`
- `variant_parent_name`

For this fixture, the expected future mapping is:

| Wix data | Expected Posnic mapping |
|---|---|
| Product name | `variant_parent_name` |
| Option combination | `variant_value` |
| Variant family | `variant_axis` |
| Variant SKU | `itemid` |
| Variant barcode | `barcode_id` |

For example:

`Small + Red` becomes the synthetic variant value `Small - Red`
under the parent product `Classic T-Shirt`.

This fixture documents an expected mapping for future connector work. It does
not claim that a Wix connector implementing this mapping already exists.

## Missing SKU and barcode behavior

A missing SKU must not result in an invented identifier.

- Missing SKU -> `itemid` remains unset and the variant is marked for review.
- Missing barcode -> `barcode_id` remains unset.
- Missing SKU and barcode -> both remain unset and the variant is marked for review.

The synthetic variant ID remains available for fixture-level identification.

## Unsupported areas

This fixture does not establish or implement:

- live Wix API calls;
- Wix authentication or installation;
- a production Wix connector;
- automatic product synchronization;
- SKU generation;
- barcode generation;
- Posnic Cloud-only functionality;
- platform certification.

All identifiers in this fixture are synthetic and intended only for local
development, testing, and documentation.

It contains no live credentials, merchant data, or customer data.
94 changes: 94 additions & 0 deletions tests/fixtures/wix/product-options.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
{
"provider": "wix",
"catalog_version": "v3",
"product": {
"id": "SYNTH-WIX-PROD-1001",
"name": "Classic T-Shirt",
"options": [
{
"name": "Size",
"choices": [
"Small",
"Large"
]
},
{
"name": "Color",
"choices": [
"Red",
"Blue"
]
}
],
"variants": [
{
"id": "SYNTH-WIX-VAR-1001",
"choices": {
"Size": "Small",
"Color": "Red"
},
"sku": "SYNTH-SKU-1001",
"barcode": "SYNTH-BC-1001",
"expected_posnic": {
"variant_parent_name": "Classic T-Shirt",
"variant_axis": "Variant",
"variant_value": "Small - Red",
"itemid": "SYNTH-SKU-1001",
"barcode_id": "SYNTH-BC-1001",
"review": false
}
},
{
"id": "SYNTH-WIX-VAR-1002",
"choices": {
"Size": "Small",
"Color": "Blue"
},
"sku": "SYNTH-SKU-1002",
"barcode": null,
"expected_posnic": {
"variant_parent_name": "Classic T-Shirt",
"variant_axis": "Variant",
"variant_value": "Small - Blue",
"itemid": "SYNTH-SKU-1002",
"barcode_id": null,
"review": false
}
},
{
"id": "SYNTH-WIX-VAR-1003",
"choices": {
"Size": "Large",
"Color": "Red"
},
"sku": null,
"barcode": "SYNTH-BC-1003",
"expected_posnic": {
"variant_parent_name": "Classic T-Shirt",
"variant_axis": "Variant",
"variant_value": "Large - Red",
"itemid": null,
"barcode_id": "SYNTH-BC-1003",
"review": true
}
},
{
"id": "SYNTH-WIX-VAR-1004",
"choices": {
"Size": "Large",
"Color": "Blue"
},
"sku": null,
"barcode": null,
"expected_posnic": {
"variant_parent_name": "Classic T-Shirt",
"variant_axis": "Variant",
"variant_value": "Large - Blue",
"itemid": null,
"barcode_id": null,
"review": true
}
}
]
}
}
149 changes: 149 additions & 0 deletions tests/wix-product-option-fixture.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
'use strict';

const test = require('node:test');
const assert = require('node:assert');
const fs = require('fs');
const path = require('path');

const FIXTURE_PATH = path.join(
__dirname,
'fixtures',
'wix',
'product-options.json',
);

function readFixture() {
return JSON.parse(fs.readFileSync(FIXTURE_PATH, 'utf8'));
}

test('Wix fixture contains size and color product options', () => {
const fixture = readFixture();
const options = fixture.product.options;

assert.strictEqual(fixture.provider, 'wix');
assert.strictEqual(fixture.catalog_version, 'v3');
assert.strictEqual(fixture.product.name, 'Classic T-Shirt');

assert.deepStrictEqual(options[0], {
name: 'Size',
choices: ['Small', 'Large'],
});

assert.deepStrictEqual(options[1], {
name: 'Color',
choices: ['Red', 'Blue'],
});
});

test('Wix fixture contains every size and color combination', () => {
const fixture = readFixture();
const variants = fixture.product.variants;

assert.strictEqual(variants.length, 4);

const combinations = variants.map(
(variant) =>
`${variant.choices.Size} - ${variant.choices.Color}`,
);

assert.deepStrictEqual(combinations.sort(), [
'Large - Blue',
'Large - Red',
'Small - Blue',
'Small - Red',
]);
});

test('Wix fixture maps SKU and barcode to Posnic identifiers', () => {
const fixture = readFixture();

for (const variant of fixture.product.variants) {
assert.strictEqual(
variant.expected_posnic.itemid,
variant.sku,
);

assert.strictEqual(
variant.expected_posnic.barcode_id,
variant.barcode,
);
}
});
test('Wix variants map option choices to the Posnic variant fields', () => {
const fixture = readFixture();

for (const variant of fixture.product.variants) {
const expectedValue =
`${variant.choices.Size} - ${variant.choices.Color}`;

assert.strictEqual(
variant.expected_posnic.variant_parent_name,
fixture.product.name,
);

assert.strictEqual(
variant.expected_posnic.variant_axis,
'Variant',
);

assert.strictEqual(
variant.expected_posnic.variant_value,
expectedValue,
);
}
});

test('Wix fixture covers missing SKU and barcode behavior', () => {
const fixture = readFixture();

const missingSku = fixture.product.variants.filter(
(variant) => variant.sku === null,
);

const missingBarcode = fixture.product.variants.filter(
(variant) => variant.barcode === null,
);

assert.strictEqual(missingSku.length, 2);
assert.strictEqual(missingBarcode.length, 2);

for (const variant of fixture.product.variants) {
assert.strictEqual(
variant.expected_posnic.review,
variant.sku === null,
);
}
});

test('Wix fixture contains only synthetic identifiers', () => {
const fixture = readFixture();

assert.match(fixture.product.id, /^SYNTH-WIX-PROD-\d+$/);

for (const variant of fixture.product.variants) {
assert.match(variant.id, /^SYNTH-WIX-VAR-\d+$/);

if (variant.sku !== null) {
assert.match(variant.sku, /^SYNTH-SKU-\d+$/);
}

if (variant.barcode !== null) {
assert.match(variant.barcode, /^SYNTH-BC-\d+$/);
}
}
});

test('Wix fixture documentation describes the integration boundary', () => {
const documentation = fs.readFileSync(
path.join(__dirname, 'fixtures', 'wix', 'README.md'),
'utf8',
);

assert.match(documentation, /Official Wix documentation/i);
assert.match(documentation, /Product options and variants/i);
assert.match(documentation, /Expected Posnic mapping/i);
assert.match(documentation, /Missing SKU and barcode behavior/i);
assert.match(documentation, /Unsupported areas/i);
assert.match(documentation, /live Wix API calls/i);
assert.match(documentation, /synthetic/i);
});
Loading