From 5e188751f77bd0ed8e521c9b2eca2b0b32534f5f Mon Sep 17 00:00:00 2001 From: Dylan Depass Date: Fri, 22 Nov 2024 14:40:45 -0500 Subject: [PATCH 1/3] fix: allow products with no price --- src/content/queries/cs-product.js | 6 +----- src/content/queries/cs-variants.js | 6 +----- src/templates/html/HTMLTemplate.js | 12 ++++++------ 3 files changed, 8 insertions(+), 16 deletions(-) diff --git a/src/content/queries/cs-product.js b/src/content/queries/cs-product.js index 78ae8d0..335880a 100644 --- a/src/content/queries/cs-product.js +++ b/src/content/queries/cs-product.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import { errorWithResponse, forceImagesHTTPS } from '../../utils/http.js'; +import { forceImagesHTTPS } from '../../utils/http.js'; import { gql, parseRating, parseSpecialToDate } from '../../utils/product.js'; /** @@ -91,10 +91,6 @@ export const adapter = (config, productData) => { } : null, }; - if (!minPrice && !maxPrice) { - throw errorWithResponse(400, 'no product price range found'); - } - if (config.attributeOverrides?.product) { Object.entries(config.attributeOverrides.product).forEach(([key, value]) => { product.attributeMap[key] = product.attributeMap[value] ?? product[key]; diff --git a/src/content/queries/cs-variants.js b/src/content/queries/cs-variants.js index 778d0ae..a380dce 100644 --- a/src/content/queries/cs-variants.js +++ b/src/content/queries/cs-variants.js @@ -10,7 +10,7 @@ * governing permissions and limitations under the License. */ -import { errorWithResponse, forceImagesHTTPS } from '../../utils/http.js'; +import { forceImagesHTTPS } from '../../utils/http.js'; import { gql, parseRating, parseSpecialToDate } from '../../utils/product.js'; /** @@ -53,10 +53,6 @@ export const adapter = (config, variants) => variants.map(({ selections, product selections: (selections ?? []).sort(), }; - if (!minPrice && !maxPrice) { - throw errorWithResponse(400, 'no variant price range found'); - } - if (config.attributeOverrides?.variant) { Object.entries(config.attributeOverrides.variant).forEach(([key, value]) => { variant.attributeMap[key] = variant.attributeMap[value] ?? variant[key]; diff --git a/src/templates/html/HTMLTemplate.js b/src/templates/html/HTMLTemplate.js index d90537e..22e75d0 100644 --- a/src/templates/html/HTMLTemplate.js +++ b/src/templates/html/HTMLTemplate.js @@ -111,7 +111,7 @@ ${HTMLTemplate.metaName('twitter:title', product.name)} ${HTMLTemplate.metaName('twitter:image', image?.url)} ${HTMLTemplate.metaName('twitter:description', product.metaDescription)} ${HTMLTemplate.metaName('twitter:label1', 'Price')} -${HTMLTemplate.metaName('twitter:data1', product.prices.final.amount)} +${HTMLTemplate.metaName('twitter:data1', product.prices?.final?.amount)} ${HTMLTemplate.metaName('twitter:label2', 'Availability')} ${HTMLTemplate.metaName('twitter:data2', product.inStock ? 'In stock' : 'Out of stock')}`; } @@ -129,8 +129,8 @@ ${HTMLTemplate.metaName('externalId', product.externalId)} ${HTMLTemplate.metaName('addToCartAllowed', product.addToCartAllowed)} ${HTMLTemplate.metaName('inStock', product.inStock ? 'true' : 'false')} ${HTMLTemplate.metaProperty('product:availability', product.inStock ? 'In stock' : 'Out of stock')} -${HTMLTemplate.metaProperty('product:price.amount', product.prices.final.amount)} -${HTMLTemplate.metaProperty('product:price.currency', product.prices.final.currency)}`; +${HTMLTemplate.metaProperty('product:price.amount', product.prices?.final?.amount)} +${HTMLTemplate.metaProperty('product:price.currency', product.prices?.final?.currency)}`; } /** @@ -271,8 +271,8 @@ ${HTMLTemplate.indent(this.renderProductItems(opt.items), 2)}`).join('\n')} */ renderVariantPrices(prices) { return /* html */ `\ -
Regular: ${prices.regular.amount} ${prices.regular.currency}${HTMLTemplate.priceRange(prices.regular.minimumAmount, prices.regular.maximumAmount)}
-
Final: ${prices.final.amount} ${prices.final.currency}${HTMLTemplate.priceRange(prices.final.minimumAmount, prices.final.maximumAmount)}
`; +
Regular: ${prices.regular?.amount} ${prices.regular?.currency}${HTMLTemplate.priceRange(prices.regular?.minimumAmount, prices.regular?.maximumAmount)}
+
Final: ${prices.final?.amount} ${prices.final?.currency}${HTMLTemplate.priceRange(prices.final?.minimumAmount, prices.final?.maximumAmount)}
`; } /** @@ -292,7 +292,7 @@ ${this.variants.map((v) => /* html */`\
${v.name}
${v.description}
${v.inStock ? 'inStock' : ''}
-${HTMLTemplate.indent(this.renderVariantPrices(v.prices), 4)} +${v.prices ? HTMLTemplate.indent(this.renderVariantPrices(v.prices), 4) : ''}
${HTMLTemplate.indent(this.renderVariantImages(v.images), 6)}
From 2c91dec1aa0c48ee94e67142ae0524a564a0208d Mon Sep 17 00:00:00 2001 From: Dylan Depass Date: Fri, 22 Nov 2024 14:56:16 -0500 Subject: [PATCH 2/3] fix: tests --- src/templates/json/JSONTemplate.js | 8 +++++--- test/templates/html/index.test.js | 30 ++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/src/templates/json/JSONTemplate.js b/src/templates/json/JSONTemplate.js index 9247a5a..1285aee 100644 --- a/src/templates/json/JSONTemplate.js +++ b/src/templates/json/JSONTemplate.js @@ -140,14 +140,16 @@ export class JSONTemplate { image: v.images?.[0]?.url ?? image, availability: v.inStock ? 'InStock' : 'OutOfStock', price: finalPrice, - priceCurrency: variantPrices.final?.currency, + priceCurrency: variantPrices?.final?.currency, gtin: v.attributeMap.gtin, priceValidUntil: v.specialToDate, aggregateRating: this.renderRating(v), }; - if (finalPrice < regularPrice) { - offer.priceSpecification = this.renderOffersPriceSpecification(v); + if (variantPrices) { + if (finalPrice < regularPrice) { + offer.priceSpecification = this.renderOffersPriceSpecification(v); + } } return pruneUndefined(offer); diff --git a/test/templates/html/index.test.js b/test/templates/html/index.test.js index 10e96a5..56d38c0 100644 --- a/test/templates/html/index.test.js +++ b/test/templates/html/index.test.js @@ -233,6 +233,36 @@ describe('Render Product HTML', () => { }); }); + it('JSON-LD should allow for missing prices', () => { + config.confMap = { + '/us/p/{{urlkey}}/{{sku}}': {}, + }; + + product.prices = undefined; + variations.forEach((variant) => { + variant.prices = undefined; + }); + + const html = htmlTemplateFromContext(DEFAULT_CONTEXT({ config }), product, variations).render(); + dom = new JSDOM(html); + document = dom.window.document; + + const metaPriceAmount = document.querySelector('meta[property="product:price.amount"]'); + assert.strictEqual(metaPriceAmount.getAttribute('content'), 'undefined', 'meta[property="product:price:amount"] should be undefined'); + + const metaPriceCurrency = document.querySelector('meta[property="product:price.currency"]'); + assert.strictEqual(metaPriceCurrency.getAttribute('content'), 'undefined', 'meta[property="product:price.currency"] should be undefined'); + + const jsonLdScript = document.querySelector('script[type="application/ld+json"]'); + const jsonLd = JSON.parse(jsonLdScript.textContent); + + jsonLd.offers.forEach((offer) => { + assert.strictEqual(offer.price, undefined, 'price should be undefined'); + assert.strictEqual(offer.priceCurrency, undefined, 'priceCurrency should be undefined'); + assert.strictEqual(offer.priceSpecification, undefined, 'priceSpecification should be undefined'); + }); + }); + it('should display the correct product name in

', () => { const h1 = document.querySelector('h1'); assert.strictEqual(h1.textContent, product.name, '

content does not match product name'); From e71c805ac1c5f33d7ea87345d33b71adb352df37 Mon Sep 17 00:00:00 2001 From: Dylan Depass Date: Fri, 22 Nov 2024 14:59:04 -0500 Subject: [PATCH 3/3] fix: test name --- test/templates/html/index.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/templates/html/index.test.js b/test/templates/html/index.test.js index 56d38c0..0fff73f 100644 --- a/test/templates/html/index.test.js +++ b/test/templates/html/index.test.js @@ -233,7 +233,7 @@ describe('Render Product HTML', () => { }); }); - it('JSON-LD should allow for missing prices', () => { + it('template should allow for missing prices', () => { config.confMap = { '/us/p/{{urlkey}}/{{sku}}': {}, };