14
14
15
15
import assert from 'node:assert' ;
16
16
import { JSDOM } from 'jsdom' ;
17
- // import { constructProductUrl } from '../../../src/utils/product .js';
17
+ import { JSONTemplate } from '../../../src/templates/json/JSONTemplate .js' ;
18
18
import { DEFAULT_CONTEXT } from '../../fixtures/context.js' ;
19
19
import { createDefaultVariations , createProductVariationFixture } from '../../fixtures/variant.js' ;
20
20
import { createProductFixture } from '../../fixtures/product.js' ;
@@ -81,26 +81,30 @@ describe('Render Product HTML', () => {
81
81
const jsonLdScript = document . querySelector ( 'script[type="application/ld+json"]' ) ;
82
82
assert . ok ( jsonLdScript , 'JSON-LD script tag should exist' ) ;
83
83
84
+ // @ts -ignore
85
+ const productTemplate = new JSONTemplate ( DEFAULT_CONTEXT ( { config } ) , product , variations ) ;
86
+
84
87
const jsonLd = JSON . parse ( jsonLdScript . textContent ) ;
85
88
assert . strictEqual ( jsonLd [ '@type' ] , 'Product' , 'JSON-LD @type should be Product' ) ;
86
- // assert.strictEqual(jsonLd['@id'], constructProductUrl(config, product ), 'JSON-LD @id does not match product URL');
89
+ assert . strictEqual ( jsonLd [ '@id' ] , productTemplate . constructProductURL ( ) , 'JSON-LD @id does not match product URL' ) ;
87
90
assert . strictEqual ( jsonLd . name , product . name , 'JSON-LD name does not match product name' ) ;
88
91
assert . strictEqual ( jsonLd . sku , product . sku , 'JSON-LD SKU does not match product SKU' ) ;
89
92
assert . strictEqual ( jsonLd . description , product . metaDescription , 'JSON-LD description does not match product description' ) ;
90
93
assert . strictEqual ( jsonLd . image , product . images [ 0 ] ?. url || '' , 'JSON-LD image does not match product image' ) ;
91
94
assert . strictEqual ( jsonLd . productID , product . sku , 'JSON-LD productID does not match product SKU' ) ;
92
95
assert . ok ( Array . isArray ( jsonLd . offers ) , 'JSON-LD offers should be an array' ) ;
93
- assert . strictEqual ( jsonLd . offers . length , variations . length + 1 , 'JSON-LD offers length does not match number of variants' ) ;
96
+ assert . strictEqual ( jsonLd . offers . length , variations . length , 'JSON-LD offers length does not match number of variants' ) ;
94
97
95
98
jsonLd . offers . forEach ( ( offer , index ) => {
96
- const variant = index === 0 ? product : variations [ index - 1 ] ;
99
+ const variant = variations [ index ] ;
97
100
assert . strictEqual ( offer [ '@type' ] , 'Offer' , `Offer type for variant ${ variant . sku } should be Offer` ) ;
98
101
assert . strictEqual ( offer . sku , variant . sku , `Offer SKU for variant ${ variant . sku } does not match` ) ;
99
- // assert.strictEqual(offer.url, constructProductUrl(config, product, index === 0 ? undefined : variant), 'JSON-LD offer URL does not match');
102
+ assert . strictEqual ( offer . url , productTemplate . constructProductURL ( variant ) , 'JSON-LD offer URL does not match' ) ;
100
103
assert . strictEqual ( offer . price , variant . prices . final . amount , `Offer price for variant ${ variant . sku } does not match` ) ;
101
104
assert . strictEqual ( offer . priceCurrency , variant . prices . final . currency , `Offer priceCurrency for variant ${ variant . sku } does not match` ) ;
102
105
assert . strictEqual ( offer . availability , variant . inStock ? 'InStock' : 'OutOfStock' , `Offer availability for variant ${ variant . sku } does not match` ) ;
103
106
assert . strictEqual ( offer . image , variant . images [ 0 ] . url || '' , `Offer image for variant ${ variant . sku } does not match` ) ;
107
+ assert . strictEqual ( offer . priceSpecification , undefined , 'Offer contains priceSpecification for variant when it should not' ) ;
104
108
} ) ;
105
109
} ) ;
106
110
@@ -117,7 +121,7 @@ describe('Render Product HTML', () => {
117
121
const jsonLd = JSON . parse ( jsonLdScript . textContent ) ;
118
122
119
123
jsonLd . offers . forEach ( ( offer , index ) => {
120
- const variant = index === 0 ? product : variations [ index - 1 ] ;
124
+ const variant = variations [ index ] ;
121
125
assert . strictEqual ( offer . gtin , variant . gtin , `Offer gtin for variant ${ variant . sku } does not match` ) ;
122
126
} ) ;
123
127
} ) ;
@@ -135,10 +139,63 @@ describe('Render Product HTML', () => {
135
139
const jsonLdScript = document . querySelector ( 'script[type="application/ld+json"]' ) ;
136
140
const jsonLd = JSON . parse ( jsonLdScript . textContent ) ;
137
141
138
- assert . strictEqual ( jsonLd . offers [ 0 ] . url , 'https://example.com/us/p/test-product-url-key/test-sku' , 'JSON-LD offer URL does not match' ) ;
139
- assert . strictEqual ( jsonLd . offers [ 1 ] . url , 'https://example.com/us/p/test-product-url-key?selected_product=test-sku-1' , 'JSON-LD offer URL does not match' ) ;
140
- assert . strictEqual ( jsonLd . offers [ 2 ] . url , 'https://example.com/us/p/test-product-url-key?selected_product=test-sku-2' , 'JSON-LD offer URL does not match' ) ;
141
- assert . strictEqual ( jsonLd . offers [ 3 ] . url , 'https://example.com/us/p/test-product-url-key?selected_product=test-sku-3' , 'JSON-LD offer URL does not match' ) ;
142
+ assert . strictEqual ( jsonLd . offers [ 0 ] . url , 'https://example.com/us/p/test-product-url-key?selected_product=test-sku-1' , 'JSON-LD offer URL does not match' ) ;
143
+ assert . strictEqual ( jsonLd . offers [ 1 ] . url , 'https://example.com/us/p/test-product-url-key?selected_product=test-sku-2' , 'JSON-LD offer URL does not match' ) ;
144
+ assert . strictEqual ( jsonLd . offers [ 2 ] . url , 'https://example.com/us/p/test-product-url-key?selected_product=test-sku-3' , 'JSON-LD offer URL does not match' ) ;
145
+ } ) ;
146
+
147
+ it ( 'should have the correct JSON-LD schema with specialToDate' , ( ) => {
148
+ config . confMap = {
149
+ '/us/p/{{urlkey}}/{{sku}}' : { } ,
150
+ } ;
151
+ variations . forEach ( ( variant ) => {
152
+ variant . specialToDate = '2024-12-31' ;
153
+ } ) ;
154
+ const html = htmlTemplateFromContext ( DEFAULT_CONTEXT ( { config } ) , product , variations ) . render ( ) ;
155
+ dom = new JSDOM ( html ) ;
156
+ document = dom . window . document ;
157
+
158
+ const jsonLdScript = document . querySelector ( 'script[type="application/ld+json"]' ) ;
159
+ const jsonLd = JSON . parse ( jsonLdScript . textContent ) ;
160
+
161
+ jsonLd . offers . forEach ( ( offer ) => {
162
+ assert . strictEqual ( offer . priceValidUntil , '2024-12-31' , 'Invalid priceValidUntil for variant' ) ;
163
+ } ) ;
164
+ } ) ;
165
+
166
+ it ( 'JSON-LD should contain priceSpecification if variant is on sale' , ( ) => {
167
+ config . confMap = {
168
+ '/us/p/{{urlkey}}/{{sku}}' : { } ,
169
+ } ;
170
+ variations . forEach ( ( variant ) => {
171
+ variant . prices = {
172
+ regular : {
173
+ amount : 29.99 ,
174
+ currency : 'USD' ,
175
+ maximumAmount : 29.99 ,
176
+ minimumAmount : 29.99 ,
177
+ } ,
178
+ final : {
179
+ amount : 14.99 ,
180
+ currency : 'USD' ,
181
+ maximumAmount : 14.99 ,
182
+ minimumAmount : 14.99 ,
183
+ } ,
184
+ } ;
185
+ } ) ;
186
+ const html = htmlTemplateFromContext ( DEFAULT_CONTEXT ( { config } ) , product , variations ) . render ( ) ;
187
+ dom = new JSDOM ( html ) ;
188
+ document = dom . window . document ;
189
+
190
+ const jsonLdScript = document . querySelector ( 'script[type="application/ld+json"]' ) ;
191
+ const jsonLd = JSON . parse ( jsonLdScript . textContent ) ;
192
+
193
+ jsonLd . offers . forEach ( ( offer ) => {
194
+ assert . strictEqual ( offer . priceSpecification [ '@type' ] , 'UnitPriceSpecification' , 'Invalid ListPrice @type for variant' ) ;
195
+ assert . strictEqual ( offer . priceSpecification . priceType , 'https://schema.org/ListPrice' , 'Invalid ListPrice priceType for variant' ) ;
196
+ assert . strictEqual ( offer . priceSpecification . price , 29.99 , 'Invalid ListPrice price for variant' ) ;
197
+ assert . strictEqual ( offer . priceSpecification . priceCurrency , 'USD' , 'Invalid ListPrice priceCurrency for variant' ) ;
198
+ } ) ;
142
199
} ) ;
143
200
144
201
it ( 'should display the correct product name in <h1>' , ( ) => {
0 commit comments