← back to Dw Gemini Skip TK11321
test/live-product-fields.test.js
56 lines
'use strict';
const test = require('node:test');
const assert = require('node:assert/strict');
const { widthFromLive, canonicalProduct, completeLiveProduct } = require('../lib/live-product-fields');
const node = (fields, vendor = 'Carnegie') => ({ vendor, metafields: { nodes: fields } });
test('verified Carnegie width is recognized with provenance', () => {
assert.deepEqual(widthFromLive(node([{ namespace: 'dwc', key: 'width', value: '54" (137 cm)' }])),
{ value: '54" (137 cm)', source: 'dwc.width' });
});
test('canonical namespace order stays stable and blanks fall through', () => {
assert.deepEqual(widthFromLive(node([
{ namespace: 'dwc', key: 'width', value: '54' },
{ namespace: 'global', key: 'width', value: ' ' },
{ namespace: 'custom', key: 'width', value: ' 52 cm ' },
])), { value: '52 cm', source: 'custom.width' });
});
test('package dimensions, other vendors, and descriptions cannot invent width', () => {
const p = node([{ namespace: 'custom', key: 'package_width', value: '4 in' },
{ namespace: 'untrusted', key: 'width', value: '54' },
{ namespace: 'carnegie', key: 'width', value: '54' }], 'Other');
p.descriptionHtml = '<p>Width: 54 Inches</p>';
assert.deepEqual(widthFromLive(p), { value: '', source: null });
});
test('canonical adapter preserves sample title and required fields', () => {
const p = { ...node([{ namespace: 'specs', key: 'width', value: '54 inches' }]),
images: { nodes: [{ url: 'https://example.test/swatch.jpg' }] },
variants: { nodes: [{ sku: 'X', title: 'Sample' }] } };
const converted = canonicalProduct(p, 'DW-X', 'Carnegie');
assert.equal(converted.specs.width, '54 inches');
assert.equal(converted.variants[0].title, 'Sample');
assert.equal(converted.dwSku, 'DW-X');
});
test('sample and width beyond the first pages are fetched before validation', async () => {
const p = { id: 'gid://shopify/Product/1', vendor: 'Carnegie',
variants: { nodes: [{ sku: 'DW-1', price: '10' }], pageInfo: { hasNextPage: true, endCursor: 'v1' } },
metafields: { nodes: [], pageInfo: { hasNextPage: true, endCursor: 'm1' } } };
const calls = [];
const fetched = await completeLiveProduct(p, async (query, variables) => {
calls.push(variables.cursor);
const connection = query.includes('variants(') ? 'variants' : 'metafields';
return { status: 200, json: { data: { product: { id: p.id,
[connection]: { nodes: connection === 'variants' ? [{ sku: 'DW-1-Sample', price: '4.25' }]
: [{ namespace: 'dwc', key: 'width', value: '54 inches' }], pageInfo: { hasNextPage: false } },
} } } };
});
assert.deepEqual(calls, ['v1', 'm1']);
assert.equal(fetched.variants.nodes.length, 2);
assert.equal(widthFromLive(fetched).value, '54 inches');
assert.equal(p.variants.nodes.length, 1);
});
test('pagination errors and repeated cursors fail closed', async () => {
const p = { id: '1', variants: { nodes: [], pageInfo: { hasNextPage: true, endCursor: 'v1' } } };
await assert.rejects(completeLiveProduct(p, async () => ({ status: 429 })), /Incomplete Shopify/);
await assert.rejects(completeLiveProduct(p, async () => ({ status: 200, json: { data: { product: p } } })), /Cannot safely paginate/);
});