← back to Dw Daily Catchup 20260909

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/);
});