Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorLuke Bennett <lbennett@gitlab.com>2018-11-26 11:57:21 +0300
committerFatih Acet <acetfatih@gmail.com>2018-11-26 11:57:21 +0300
commit1877eb49c0bfe855eca74209441f954c4550ffef (patch)
tree7bc47b4d007f48f8504ee1d6a4c2329d2324adf5 /spec
parentceae9f5211a77333810dfd704823381730eb1791 (diff)
Attempt to fix lazy loader spec transient failure
Diffstat (limited to 'spec')
-rw-r--r--spec/javascripts/helpers/scroll_into_view_promise.js28
-rw-r--r--spec/javascripts/helpers/wait_for_attribute_change.js16
-rw-r--r--spec/javascripts/lazy_loader_spec.js174
3 files changed, 146 insertions, 72 deletions
diff --git a/spec/javascripts/helpers/scroll_into_view_promise.js b/spec/javascripts/helpers/scroll_into_view_promise.js
new file mode 100644
index 00000000000..0edea2103da
--- /dev/null
+++ b/spec/javascripts/helpers/scroll_into_view_promise.js
@@ -0,0 +1,28 @@
+export default function scrollIntoViewPromise(intersectionTarget, timeout = 100, maxTries = 5) {
+ return new Promise((resolve, reject) => {
+ let intersectionObserver;
+ let retry = 0;
+
+ const intervalId = setInterval(() => {
+ if (retry >= maxTries) {
+ intersectionObserver.disconnect();
+ clearInterval(intervalId);
+ reject(new Error(`Could not scroll target into viewPort within ${timeout * maxTries} ms`));
+ }
+ retry += 1;
+ intersectionTarget.scrollIntoView();
+ }, timeout);
+
+ intersectionObserver = new IntersectionObserver(entries => {
+ if (entries[0].isIntersecting) {
+ intersectionObserver.disconnect();
+ clearInterval(intervalId);
+ resolve();
+ }
+ });
+
+ intersectionObserver.observe(intersectionTarget);
+
+ intersectionTarget.scrollIntoView();
+ });
+}
diff --git a/spec/javascripts/helpers/wait_for_attribute_change.js b/spec/javascripts/helpers/wait_for_attribute_change.js
new file mode 100644
index 00000000000..8f22d569222
--- /dev/null
+++ b/spec/javascripts/helpers/wait_for_attribute_change.js
@@ -0,0 +1,16 @@
+export default (domElement, attributes, timeout = 1500) =>
+ new Promise((resolve, reject) => {
+ let observer;
+ const timeoutId = setTimeout(() => {
+ observer.disconnect();
+ reject(new Error(`Could not see an attribute update within ${timeout} ms`));
+ }, timeout);
+
+ observer = new MutationObserver(() => {
+ clearTimeout(timeoutId);
+ observer.disconnect();
+ resolve();
+ });
+
+ observer.observe(domElement, { attributes: true, attributeFilter: attributes });
+ });
diff --git a/spec/javascripts/lazy_loader_spec.js b/spec/javascripts/lazy_loader_spec.js
index eac4756e8a9..cbdc1644430 100644
--- a/spec/javascripts/lazy_loader_spec.js
+++ b/spec/javascripts/lazy_loader_spec.js
@@ -1,16 +1,19 @@
import LazyLoader from '~/lazy_loader';
import { TEST_HOST } from './test_constants';
-
-let lazyLoader = null;
+import scrollIntoViewPromise from './helpers/scroll_into_view_promise';
+import waitForPromises from './helpers/wait_for_promises';
+import waitForAttributeChange from './helpers/wait_for_attribute_change';
const execImmediately = callback => {
callback();
};
describe('LazyLoader', function() {
+ let lazyLoader = null;
+
preloadFixtures('issues/issue_with_comment.html.raw');
- describe('with IntersectionObserver disabled', () => {
+ describe('without IntersectionObserver', () => {
beforeEach(function() {
loadFixtures('issues/issue_with_comment.html.raw');
@@ -36,14 +39,15 @@ describe('LazyLoader', function() {
it('should copy value from data-src to src for img 1', function(done) {
const img = document.querySelectorAll('img[data-src]')[0];
const originalDataSrc = img.getAttribute('data-src');
- img.scrollIntoView();
-
- setTimeout(() => {
- expect(LazyLoader.loadImage).toHaveBeenCalled();
- expect(img.getAttribute('src')).toBe(originalDataSrc);
- expect(img).toHaveClass('js-lazy-loaded');
- done();
- }, 50);
+
+ Promise.all([scrollIntoViewPromise(img), waitForAttributeChange(img, ['data-src', 'src'])])
+ .then(() => {
+ expect(LazyLoader.loadImage).toHaveBeenCalled();
+ expect(img.getAttribute('src')).toBe(originalDataSrc);
+ expect(img).toHaveClass('js-lazy-loaded');
+ done();
+ })
+ .catch(done.fail);
});
it('should lazy load dynamically added data-src images', function(done) {
@@ -52,14 +56,18 @@ describe('LazyLoader', function() {
newImg.className = 'lazy';
newImg.setAttribute('data-src', testPath);
document.body.appendChild(newImg);
- newImg.scrollIntoView();
-
- setTimeout(() => {
- expect(LazyLoader.loadImage).toHaveBeenCalled();
- expect(newImg.getAttribute('src')).toBe(testPath);
- expect(newImg).toHaveClass('js-lazy-loaded');
- done();
- }, 50);
+
+ Promise.all([
+ scrollIntoViewPromise(newImg),
+ waitForAttributeChange(newImg, ['data-src', 'src']),
+ ])
+ .then(() => {
+ expect(LazyLoader.loadImage).toHaveBeenCalled();
+ expect(newImg.getAttribute('src')).toBe(testPath);
+ expect(newImg).toHaveClass('js-lazy-loaded');
+ done();
+ })
+ .catch(done.fail);
});
it('should not alter normal images', function(done) {
@@ -67,13 +75,15 @@ describe('LazyLoader', function() {
const testPath = `${TEST_HOST}/img/testimg.png`;
newImg.setAttribute('src', testPath);
document.body.appendChild(newImg);
- newImg.scrollIntoView();
- setTimeout(() => {
- expect(LazyLoader.loadImage).not.toHaveBeenCalled();
- expect(newImg).not.toHaveClass('js-lazy-loaded');
- done();
- }, 50);
+ scrollIntoViewPromise(newImg)
+ .then(waitForPromises)
+ .then(() => {
+ expect(LazyLoader.loadImage).not.toHaveBeenCalled();
+ expect(newImg).not.toHaveClass('js-lazy-loaded');
+ done();
+ })
+ .catch(done.fail);
});
it('should not load dynamically added pictures if content observer is turned off', done => {
@@ -84,13 +94,15 @@ describe('LazyLoader', function() {
newImg.className = 'lazy';
newImg.setAttribute('data-src', testPath);
document.body.appendChild(newImg);
- newImg.scrollIntoView();
- setTimeout(() => {
- expect(LazyLoader.loadImage).not.toHaveBeenCalled();
- expect(newImg).not.toHaveClass('js-lazy-loaded');
- done();
- }, 50);
+ scrollIntoViewPromise(newImg)
+ .then(waitForPromises)
+ .then(() => {
+ expect(LazyLoader.loadImage).not.toHaveBeenCalled();
+ expect(newImg).not.toHaveClass('js-lazy-loaded');
+ done();
+ })
+ .catch(done.fail);
});
it('should load dynamically added pictures if content observer is turned off and on again', done => {
@@ -102,17 +114,22 @@ describe('LazyLoader', function() {
newImg.className = 'lazy';
newImg.setAttribute('data-src', testPath);
document.body.appendChild(newImg);
- newImg.scrollIntoView();
- setTimeout(() => {
- expect(LazyLoader.loadImage).toHaveBeenCalled();
- expect(newImg).toHaveClass('js-lazy-loaded');
- done();
- }, 50);
+ Promise.all([
+ scrollIntoViewPromise(newImg),
+ waitForAttributeChange(newImg, ['data-src', 'src']),
+ ])
+ .then(waitForPromises)
+ .then(() => {
+ expect(LazyLoader.loadImage).toHaveBeenCalled();
+ expect(newImg).toHaveClass('js-lazy-loaded');
+ done();
+ })
+ .catch(done.fail);
});
});
- describe('with IntersectionObserver enabled', () => {
+ describe('with IntersectionObserver', () => {
beforeEach(function() {
loadFixtures('issues/issue_with_comment.html.raw');
@@ -136,14 +153,15 @@ describe('LazyLoader', function() {
it('should copy value from data-src to src for img 1', function(done) {
const img = document.querySelectorAll('img[data-src]')[0];
const originalDataSrc = img.getAttribute('data-src');
- img.scrollIntoView();
-
- setTimeout(() => {
- expect(LazyLoader.loadImage).toHaveBeenCalled();
- expect(img.getAttribute('src')).toBe(originalDataSrc);
- expect(img).toHaveClass('js-lazy-loaded');
- done();
- }, 50);
+
+ Promise.all([scrollIntoViewPromise(img), waitForAttributeChange(img, ['data-src', 'src'])])
+ .then(() => {
+ expect(LazyLoader.loadImage).toHaveBeenCalled();
+ expect(img.getAttribute('src')).toBe(originalDataSrc);
+ expect(img).toHaveClass('js-lazy-loaded');
+ done();
+ })
+ .catch(done.fail);
});
it('should lazy load dynamically added data-src images', function(done) {
@@ -152,14 +170,18 @@ describe('LazyLoader', function() {
newImg.className = 'lazy';
newImg.setAttribute('data-src', testPath);
document.body.appendChild(newImg);
- newImg.scrollIntoView();
-
- setTimeout(() => {
- expect(LazyLoader.loadImage).toHaveBeenCalled();
- expect(newImg.getAttribute('src')).toBe(testPath);
- expect(newImg).toHaveClass('js-lazy-loaded');
- done();
- }, 50);
+
+ Promise.all([
+ scrollIntoViewPromise(newImg),
+ waitForAttributeChange(newImg, ['data-src', 'src']),
+ ])
+ .then(() => {
+ expect(LazyLoader.loadImage).toHaveBeenCalled();
+ expect(newImg.getAttribute('src')).toBe(testPath);
+ expect(newImg).toHaveClass('js-lazy-loaded');
+ done();
+ })
+ .catch(done.fail);
});
it('should not alter normal images', function(done) {
@@ -167,13 +189,15 @@ describe('LazyLoader', function() {
const testPath = `${TEST_HOST}/img/testimg.png`;
newImg.setAttribute('src', testPath);
document.body.appendChild(newImg);
- newImg.scrollIntoView();
- setTimeout(() => {
- expect(LazyLoader.loadImage).not.toHaveBeenCalled();
- expect(newImg).not.toHaveClass('js-lazy-loaded');
- done();
- }, 50);
+ scrollIntoViewPromise(newImg)
+ .then(waitForPromises)
+ .then(() => {
+ expect(LazyLoader.loadImage).not.toHaveBeenCalled();
+ expect(newImg).not.toHaveClass('js-lazy-loaded');
+ done();
+ })
+ .catch(done.fail);
});
it('should not load dynamically added pictures if content observer is turned off', done => {
@@ -184,13 +208,15 @@ describe('LazyLoader', function() {
newImg.className = 'lazy';
newImg.setAttribute('data-src', testPath);
document.body.appendChild(newImg);
- newImg.scrollIntoView();
- setTimeout(() => {
- expect(LazyLoader.loadImage).not.toHaveBeenCalled();
- expect(newImg).not.toHaveClass('js-lazy-loaded');
- done();
- }, 50);
+ scrollIntoViewPromise(newImg)
+ .then(waitForPromises)
+ .then(() => {
+ expect(LazyLoader.loadImage).not.toHaveBeenCalled();
+ expect(newImg).not.toHaveClass('js-lazy-loaded');
+ done();
+ })
+ .catch(done.fail);
});
it('should load dynamically added pictures if content observer is turned off and on again', done => {
@@ -202,13 +228,17 @@ describe('LazyLoader', function() {
newImg.className = 'lazy';
newImg.setAttribute('data-src', testPath);
document.body.appendChild(newImg);
- newImg.scrollIntoView();
- setTimeout(() => {
- expect(LazyLoader.loadImage).toHaveBeenCalled();
- expect(newImg).toHaveClass('js-lazy-loaded');
- done();
- }, 50);
+ Promise.all([
+ scrollIntoViewPromise(newImg),
+ waitForAttributeChange(newImg, ['data-src', 'src']),
+ ])
+ .then(() => {
+ expect(LazyLoader.loadImage).toHaveBeenCalled();
+ expect(newImg).toHaveClass('js-lazy-loaded');
+ done();
+ })
+ .catch(done.fail);
});
});
});