open-nomad/ui/tests/integration/components/image-file-test.js
Buck Doyle 29de8f4f76
Add component accessibility auditing and fixes (#8679)
This continues #8455 by adding accessibility audits to component integration
tests and fixing associated errors. It adds audits to existing tests rather than
adding separate ones to facilitate auditing the various permutations a
component’s rendering can go through.

It also adds linting to ensure audits happen in component tests. This
necessitated consolidating test files that were scattered.
2020-08-25 10:56:02 -05:00

110 lines
3.2 KiB
JavaScript

import { find, settled } from '@ember/test-helpers';
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';
import { componentA11yAudit } from 'nomad-ui/tests/helpers/a11y-audit';
import sinon from 'sinon';
import RSVP from 'rsvp';
import { formatBytes } from 'nomad-ui/helpers/format-bytes';
module('Integration | Component | image file', function(hooks) {
setupRenderingTest(hooks);
const commonTemplate = hbs`
<ImageFile @src={{src}} @alt={{alt}} @size={{size}} />
`;
const commonProperties = {
src: 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7',
alt: 'This is the alt text',
size: 123456,
};
test('component displays the image', async function(assert) {
this.setProperties(commonProperties);
await this.render(commonTemplate);
assert.ok(find('img'), 'Image is in the DOM');
assert.equal(
find('img').getAttribute('src'),
commonProperties.src,
`src is ${commonProperties.src}`
);
await componentA11yAudit(this.element, assert);
});
test('the image is wrapped in an anchor that links directly to the image', async function(assert) {
this.setProperties(commonProperties);
await this.render(commonTemplate);
assert.ok(find('a'), 'Anchor');
assert.ok(find('a > img'), 'Image in anchor');
assert.equal(
find('a').getAttribute('href'),
commonProperties.src,
`href is ${commonProperties.src}`
);
assert.equal(find('a').getAttribute('target'), '_blank', 'Anchor opens to a new tab');
assert.equal(
find('a').getAttribute('rel'),
'noopener noreferrer',
'Anchor rel correctly bars openers and referrers'
);
});
test('component updates image meta when the image loads', async function(assert) {
const { spy, wrapper, notifier } = notifyingSpy();
this.setProperties(commonProperties);
this.set('spy', wrapper);
this.render(hbs`
<ImageFile @src={{src}} @alt={{alt}} @size={{size}} @updateImageMeta={{spy}} />
`);
await notifier;
assert.ok(spy.calledOnce);
});
test('component shows the width, height, and size of the image', async function(assert) {
this.setProperties(commonProperties);
await this.render(commonTemplate);
await settled();
const statsEl = find('[data-test-file-stats]');
assert.ok(
/\d+px \u00d7 \d+px/.test(statsEl.textContent),
'Width and height are formatted correctly'
);
assert.ok(
statsEl.textContent.trim().endsWith(formatBytes([commonProperties.size]) + ')'),
'Human-formatted size is included'
);
});
});
function notifyingSpy() {
// The notifier must resolve when the spy wrapper is called
let dispatch;
const notifier = new RSVP.Promise(resolve => {
dispatch = resolve;
});
const spy = sinon.spy();
// The spy wrapper must call the spy, passing all arguments through, and it must
// call dispatch in order to resolve the promise.
const wrapper = (...args) => {
spy(...args);
dispatch();
};
// All three pieces are required to wire up a component, pause test execution, and
// write assertions.
return { spy, wrapper, notifier };
}