diff --git a/.travis.yml b/.travis.yml index f904298..c32e2d3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,17 +3,14 @@ language: node_js node_js: # we recommend testing addons with the same minimum supported node version as Ember CLI # so that your addon works for all apps - - "6" + - "12" sudo: false -dist: trusty addons: chrome: stable -cache: - directories: - - $HOME/.npm +cache: npm env: global: @@ -47,7 +44,6 @@ jobs: before_install: - npm config set spin false - - npm install -g npm@4 - npm --version script: diff --git a/README.md b/README.md index c353103..6508bea 100644 --- a/README.md +++ b/README.md @@ -20,3 +20,25 @@ Extracted from [smoke-and-mirrors](https://github.com/runspired/smoke-and-mirror title=attrs.imageTitle }} ``` + +### Test Helper + +Sometimes you want to wait for all async images on a page to load during tests. `waitUntilAllAsyncImagesAreLoaded` can be use to wait for all image to finish loading during a test. For instance you use visual regression testing and need to ensure all async images are loaded before taking a snapshot. + +```js +import { visit } from '@ember/test-helpers'; +import { setupApplicationTest } from 'ember-qunit'; +import { module, test } from 'qunit'; +import { takeVisualRegressionSnapshot } from 'my-great-visual-regression-testing-lib'; +import { waitUntilAllAsyncImagesAreLoaded } from 'ember-async-image/test-support'; + +module('Acceptance | dashboard', function (hooks) { + setupApplicationTest(hooks); + + test('no visual regressions', async function(assert) { + visit('/page-with-async-images'); + await waitUntilAllAsyncImagesAreLoaded(); + await takeVisualRegressionSnapshot(); + }); +}); +``` diff --git a/addon-test-support/index.js b/addon-test-support/index.js new file mode 100644 index 0000000..eeeec77 --- /dev/null +++ b/addon-test-support/index.js @@ -0,0 +1,3 @@ +import waitUntilAllAsyncImagesAreLoaded from './wait-until-all-async-images-are-loaded'; + +export { waitUntilAllAsyncImagesAreLoaded }; diff --git a/addon-test-support/wait-until-all-async-images-are-loaded.js b/addon-test-support/wait-until-all-async-images-are-loaded.js new file mode 100644 index 0000000..7faaabd --- /dev/null +++ b/addon-test-support/wait-until-all-async-images-are-loaded.js @@ -0,0 +1,13 @@ +import { findAll, waitUntil } from '@ember/test-helpers'; + +export default function waitUntilAllAsyncImagesAreLoaded({ emptyAllowed = false, failureAllowed = false } = {}) { + return waitUntil(function allAsyncImagesLoaded() { + return findAll('.async-image').every(function isLoaded(element) { + return ( + element.classList.contains('is-loaded') || + (failureAllowed && element.classList.contains('is-failed')) || + (emptyAllowed && element.classList.contains('is-empty')) + ); + }); + }); +} diff --git a/tests/dummy/public/small.png b/tests/dummy/public/small.png new file mode 100644 index 0000000..91a99b9 Binary files /dev/null and b/tests/dummy/public/small.png differ diff --git a/tests/integration/components/async-image-test.js b/tests/integration/components/async-image-test.js index 3b52839..757b375 100644 --- a/tests/integration/components/async-image-test.js +++ b/tests/integration/components/async-image-test.js @@ -2,6 +2,7 @@ import { module, test } from 'qunit'; import { setupRenderingTest } from 'ember-qunit'; import { render, findAll } from '@ember/test-helpers'; import hbs from 'htmlbars-inline-precompile'; +import { waitUntilAllAsyncImagesAreLoaded } from 'ember-async-image/test-support'; module('Integration | Component | async image', function(hooks) { setupRenderingTest(hooks); @@ -15,4 +16,29 @@ module('Integration | Component | async image', function(hooks) { assert.equal(findAll('*')[0].firstElementChild.tagName, 'IMG'); }); + + test('waitUntilAllAsyncImagesAreLoaded', async function(assert) { + await render(hbs`{{async-image src="/small.png"}}`); + let element = findAll('*')[0].firstElementChild; + + assert.ok(element.classList.contains('is-loading'), `classes: ${element.classList.toString()}`); + await waitUntilAllAsyncImagesAreLoaded(); + assert.ok(element.classList.contains('is-loaded'), `classes: ${element.classList.toString()}`); + }); + + test('waitUntilAllAsyncImagesAreLoaded - empty', async function(assert) { + await render(hbs`{{async-image src=""}}`); + let element = findAll('*')[0].firstElementChild; + + await waitUntilAllAsyncImagesAreLoaded({ emptyAllowed: true }); + assert.ok(element.classList.contains('is-empty'), `classes: ${element.classList.toString()}`); + }); + + test('waitUntilAllAsyncImagesAreLoaded - failed', async function(assert) { + await render(hbs`{{async-image src="/nonexistent.png"}}`); + let element = findAll('*')[0].firstElementChild; + + await waitUntilAllAsyncImagesAreLoaded({ failureAllowed: true }); + assert.ok(element.classList.contains('is-failed'), `classes: ${element.classList.toString()}`); + }); });