Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions src/components/cart.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) => `<li id="${lineItem.id}" class=${this.classes.lineItem.lineItem}>${output}</li>`);
}, '');
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/templates/line-item.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

111 changes: 110 additions & 1 deletion test/unit/cart/cart.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 <li /> string', () => {
Expand All @@ -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, /<li\b.*>[\s\S]*<\/li>/);
Expand Down Expand Up @@ -188,6 +191,69 @@ describe('Cart class', () => {
assert.include(cartLineItemsHtml, `<span class="visuallyhidden">${quantityIncrementAccessibilityLabel}</span>`);
});

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;
Expand Down Expand Up @@ -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);
Expand Down