diff --git a/src/components/cart.js b/src/components/cart.js index bb5be0a9..4adc0a0d 100644 --- a/src/components/cart.js +++ b/src/components/cart.js @@ -116,6 +116,7 @@ export default class Cart extends Component { data.classes = this.classes; data.text = this.config.lineItem.text; data.lineItemImage = this.imageForLineItem(data); + data.lineItemImageAltText = this.imageAltTextForLineItem(data); data.variantTitle = data.variant.title === 'Default Title' ? '' : data.variant.title; return acc + this.childTemplate.render({data}, (output) => `
  • ${output}
  • `); }, ''); @@ -215,6 +216,14 @@ export default class Cart extends Component { } } + imageAltTextForLineItem(lineItem) { + if (lineItem.variant.image) { + return lineItem.variant.image.altText || lineItem.title; + } else { + return null; + } + } + /** * sets model to null and removes checkout from localStorage * @return {Promise} promise resolving to the cart model diff --git a/src/templates/line-item.js b/src/templates/line-item.js index b66f341d..0dfb2966 100644 --- a/src/templates/line-item.js +++ b/src/templates/line-item.js @@ -1,5 +1,5 @@ const lineItemTemplates = { - image: '
    ', + image: '', variantTitle: '
    {{data.variantTitle}}
    ', title: '{{data.title}}', diff --git a/test/unit/cart/cart.js b/test/unit/cart/cart.js index 3774909f..d02af3a1 100644 --- a/test/unit/cart/cart.js +++ b/test/unit/cart/cart.js @@ -130,13 +130,17 @@ describe('Cart class', () => { describe('get lineItemsHtml', () => { const variantAmount = '5.00'; let formatMoneySpy; + let renderSpy; + beforeEach(() => { formatMoneySpy = sinon.spy(formatMoney, 'default'); + renderSpy = sinon.spy(cart.childTemplate, 'render'); }); afterEach(() => { formatMoneySpy.restore(); + renderSpy.restore(); }); it('calls render and returns an html
  • string', () => { @@ -157,7 +161,6 @@ describe('Cart class', () => { discountAllocations: [], }]; - const renderSpy = sinon.spy(cart.childTemplate, 'render'); const cartLineItemsHtml = cart.lineItemsHtml; assert.include(cartLineItemsHtml, 'data-line-item-id="123"'); assert.match(cartLineItemsHtml, /[\s\S]*<\/li>/); @@ -188,6 +191,69 @@ describe('Cart class', () => { assert.include(cartLineItemsHtml, `${quantityIncrementAccessibilityLabel}`); }); + describe('Line item image', () => { + beforeEach(() => { + cart.lineItemCache = [{ + id: 123, + title: 'test', + variantTitle: 'test2', + quantity: 1, + variant: { + image: { + src: 'cdn.shopify.com/image.jpg', + }, + priceV2: { + amount: '5.00', + currencyCode: 'CAD', + }, + }, + discountAllocations: [], + }]; + }); + + it('renders the child template with a line item image', () => { + const mockLineItemImage = 'mock-image-src.com'; + const imageForLineItemStub = sinon.stub(cart, 'imageForLineItem').returns(mockLineItemImage); + + const cartLineItemsHtml = cart.lineItemsHtml; + const renderData = renderSpy.getCall(0).args[0].data; + + assert.calledOnce(imageForLineItemStub); + assert.equal(renderData.lineItemImage, mockLineItemImage); + assert.include(cartLineItemsHtml, `style="background-image: url(${mockLineItemImage})"`); + + imageForLineItemStub.restore(); + }); + + it('renders the child template line item image with a role and aria-label if alt text is not null', () => { + const mockLineItemImageAltText = 'alt text'; + const imageAltTextForLineItemStub = sinon.stub(cart, 'imageAltTextForLineItem').returns(mockLineItemImageAltText); + + const cartLineItemsHtml = cart.lineItemsHtml; + const renderData = renderSpy.getCall(0).args[0].data; + + assert.calledOnce(imageAltTextForLineItemStub); + assert.equal(renderData.lineItemImageAltText, mockLineItemImageAltText); + assert.include(cartLineItemsHtml, `role="img" aria-label="${mockLineItemImageAltText}"`); + + imageAltTextForLineItemStub.restore(); + }); + + it('renders the child template line item image without a role or aria-label if alt text is null', () => { + const mockLineItemImageAltText = null; + const imageAltTextForLineItemStub = sinon.stub(cart, 'imageAltTextForLineItem').returns(mockLineItemImageAltText); + + const cartLineItemsHtml = cart.lineItemsHtml; + const renderData = renderSpy.getCall(0).args[0].data; + + assert.calledOnce(imageAltTextForLineItemStub); + assert.equal(renderData.lineItemImageAltText, mockLineItemImageAltText); + assert.notInclude(cartLineItemsHtml, 'role="img" aria-label'); + + imageAltTextForLineItemStub.restore(); + }); + }); + describe('price without discounts', () => { beforeEach(() => { cart.childTemplate.contents.price = true; @@ -501,6 +567,49 @@ describe('Cart class', () => { }); }); + describe('imageAltTextForLineItem', () => { + it('returns null if the line item variant image does not exist', () => { + const lineItem = { + variant: { + id: 123, + }, + }; + const altText = cart.imageAltTextForLineItem(lineItem); + + assert.equal(altText, null); + }); + + it('returns the line item variant image alt text if it exists', () => { + const lineItem = { + title: 'title', + variant: { + id: 123, + image: { + altText: 'image alt text', + }, + }, + }; + const altText = cart.imageAltTextForLineItem(lineItem); + + assert.equal(altText, lineItem.variant.image.altText); + }); + + it('returns the line item title if the variant image alt text does not exist', () => { + const lineItem = { + title: 'title', + variant: { + id: 123, + image: { + src: 'cdn.shopify.com/variant_image.jpg', + }, + }, + }; + const altText = cart.imageAltTextForLineItem(lineItem); + + assert.equal(altText, lineItem.title); + }); + }); + describe('fetchData()', () => { it('resolves to null if key does not exist in localStorage', () => { localStorage.removeItem(cart.localStorageCheckoutKey);