diff --git a/__tests__/App.test.jsx b/__tests__/App.test.jsx
index 29f0f21fa0..663cf231a8 100644
--- a/__tests__/App.test.jsx
+++ b/__tests__/App.test.jsx
@@ -1,6 +1,6 @@
import React from 'react';
-import { mountWithContexts } from './enzymeHelpers';
+import { mountWithContexts, waitForElement } from './enzymeHelpers';
import { asyncFlush } from '../jest.setup';
@@ -66,11 +66,9 @@ describe('', () => {
expect(wrapper.find(aboutModalContent)).toHaveLength(0);
wrapper.find(aboutDropdown).simulate('click');
wrapper.find(aboutButton).simulate('click');
- wrapper.update();
// check about modal content
- const content = wrapper.find(aboutModalContent);
- expect(content).toHaveLength(1);
+ const content = await waitForElement(wrapper, aboutModalContent);
expect(content.find('dd').text()).toContain(ansible_version);
expect(content.find('pre').text()).toContain(`< Tower ${version} >`);
diff --git a/__tests__/enzymeHelpers.jsx b/__tests__/enzymeHelpers.jsx
index aa04ca5c26..d8a5de7e4e 100644
--- a/__tests__/enzymeHelpers.jsx
+++ b/__tests__/enzymeHelpers.jsx
@@ -158,3 +158,26 @@ export function mountWithContexts (node, options = {}) {
};
return mount(wrapContexts(node, context), { context, childContextTypes });
}
+
+/**
+ * Wait for element to exist.
+ *
+ * @param[wrapper] - A ReactWrapper instance
+ * @param[selector] - The selector of the element to wait for.
+ */
+export function waitForElement (wrapper, selector) {
+ const interval = 100;
+ return new Promise((resolve, reject) => {
+ let attempts = 30;
+ (function pollElement () {
+ wrapper.update();
+ if (wrapper.exists(selector)) {
+ return resolve(wrapper.find(selector));
+ }
+ if (--attempts <= 0) {
+ return reject(new Error(`Element not found using ${selector}`));
+ }
+ return setTimeout(pollElement, interval);
+ }());
+ });
+}
diff --git a/__tests__/enzymeHelpers.test.jsx b/__tests__/enzymeHelpers.test.jsx
index 5ee423800a..8a92fe0ab9 100644
--- a/__tests__/enzymeHelpers.test.jsx
+++ b/__tests__/enzymeHelpers.test.jsx
@@ -1,8 +1,8 @@
-import React from 'react';
+import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import { withI18n } from '@lingui/react';
import { t } from '@lingui/macro';
-import { mountWithContexts } from './enzymeHelpers';
+import { mountWithContexts, waitForElement } from './enzymeHelpers';
import { Config } from '../src/contexts/Config';
import { withNetwork } from '../src/contexts/Network';
import { withRootDialog } from '../src/contexts/RootDialog';
@@ -185,12 +185,12 @@ describe('mountWithContexts', () => {
});
it('should set props on wrapped component', () => {
- function Component ({ text }) {
+ function TestComponent ({ text }) {
return (
{text}
);
}
const wrapper = mountWithContexts(
-
+
);
expect(wrapper.find('div').text()).toEqual('foo');
wrapper.setProps({
@@ -199,3 +199,56 @@ describe('mountWithContexts', () => {
expect(wrapper.find('div').text()).toEqual('bar');
});
});
+
+/**
+ * This is a fixture for testing async components. It renders a div
+ * after a short amount of time.
+ */
+class TestAsyncComponent extends Component {
+ constructor (props) {
+ super(props);
+ this.state = { displayElement: false };
+ }
+
+ componentDidMount () {
+ setTimeout(() => {
+ this.setState({ displayElement: true });
+ }, 1000);
+ }
+
+ render () {
+ const { displayElement } = this.state;
+ if (displayElement) {
+ return ();
+ }
+ return null;
+ }
+}
+
+describe('waitForElement', () => {
+ it('waits for the element and returns it', async (done) => {
+ const selector = '#test-async-component';
+ const wrapper = mountWithContexts();
+ expect(wrapper.exists(selector)).toEqual(false);
+
+ const elem = await waitForElement(wrapper, selector);
+ expect(elem.props().id).toEqual('test-async-component');
+ expect(wrapper.exists(selector)).toEqual(true);
+ done();
+ });
+
+ it('eventually throws an error for elements that don\'t exist', async (done) => {
+ const selector = '#does-not-exist';
+ const wrapper = mountWithContexts();
+
+ let error;
+ try {
+ await waitForElement(wrapper, selector);
+ } catch (err) {
+ error = err;
+ } finally {
+ expect(error).toEqual(new Error(`Element not found using ${selector}`));
+ done();
+ }
+ });
+});