Skip to content

Commit

Permalink
Make tests more reliable
Browse files Browse the repository at this point in the history
  • Loading branch information
islemaster committed Mar 23, 2017
1 parent 7ae0637 commit 9c340a1
Showing 1 changed file with 82 additions and 41 deletions.
123 changes: 82 additions & 41 deletions apps/test/unit/lib/kits/maker/ui/SetupChecklistTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,17 @@ import SetupChecklist from '@cdo/apps/lib/kits/maker/ui/SetupChecklist';
import SetupChecker from '@cdo/apps/lib/kits/maker/util/SetupChecker';

describe('SetupChecklist', () => {
const STEP_DELAY = 15;
let checker;

// Speed up the tests by reducing the artificial delay between steps
const STEP_DELAY_MS = 1;

// Helpful selectors
const REDETECT_BUTTON = 'input[value="re-detect"]';
const WAITING_ICON = '.fa-clock-o';
const SUCCESS_ICON = '.fa-check-circle';
const FAILURE_ICON = '.fa-times-circle';

beforeEach(() => {
sinon.stub(window.console, 'error');
sinon.stub(window.location, 'reload');
Expand All @@ -21,78 +29,111 @@ describe('SetupChecklist', () => {
window.console.error.restore();
});

it('renders success', done => {
it('renders success', () => {
const wrapper = mount(
<SetupChecklist
setupChecker={checker}
stepDelay={STEP_DELAY}
stepDelay={STEP_DELAY_MS}
/>
);
expect(wrapper.find('.fa-clock-o')).to.have.length(5);
setTimeout(() => {
expect(wrapper.find('.fa-check-circle')).to.have.length(5);
expect(window.console.error).not.to.have.been.called;
done();
}, STEP_DELAY * 10);
expect(wrapper.find(REDETECT_BUTTON)).to.be.disabled;
expect(wrapper.find(WAITING_ICON)).to.have.length(5);
return yieldUntilDoneDetecting(wrapper)
.then(() => {
expect(wrapper.find(REDETECT_BUTTON)).not.to.be.disabled;
expect(wrapper.find(SUCCESS_ICON)).to.have.length(5);
expect(window.console.error).not.to.have.been.called;
});
});

it('fails if chrome version is wrong', done => {
it('fails if chrome version is wrong', () => {
const error = new Error('test error');
checker.detectChromeVersion.rejects(error);
const wrapper = mount(
<SetupChecklist
setupChecker={checker}
stepDelay={STEP_DELAY}
stepDelay={STEP_DELAY_MS}
/>
);
expect(wrapper.find('.fa-clock-o')).to.have.length(5);
setTimeout(() => {
expect(wrapper.find('.fa-times-circle')).to.have.length(1);
expect(wrapper.find('.fa-clock-o')).to.have.length(4);
expect(wrapper.text()).to.include('Your current browser is not supported at this time.');
expect(window.console.error).to.have.been.calledWith(error);
done();
}, STEP_DELAY * 10);
expect(wrapper.find(WAITING_ICON)).to.have.length(5);
return yieldUntilDoneDetecting(wrapper)
.then(() => {
expect(wrapper.find(FAILURE_ICON)).to.have.length(1);
expect(wrapper.find(WAITING_ICON)).to.have.length(4);
expect(wrapper.text()).to.include('Your current browser is not supported at this time.');
expect(window.console.error).to.have.been.calledWith(error);
});
});

it('does not reload the page on re-detect if successful', done => {
it('does not reload the page on re-detect if successful', () => {
const wrapper = mount(
<SetupChecklist
setupChecker={checker}
stepDelay={STEP_DELAY}
stepDelay={STEP_DELAY_MS}
/>
);
setTimeout(() => {
expect(wrapper.find('.fa-check-circle')).to.have.length(5);
wrapper.find('input[value="re-detect"]').simulate('click');
expect(wrapper.find('.fa-clock-o')).to.have.length(5);
setTimeout(() => {
expect(wrapper.find('.fa-check-circle')).to.have.length(5);
expect(window.location.reload).not.to.have.been.called;
done();
}, STEP_DELAY * 10);
}, STEP_DELAY * 10);
return yieldUntilDoneDetecting(wrapper)
.then(() => {
expect(wrapper.find(SUCCESS_ICON)).to.have.length(5);
wrapper.find(REDETECT_BUTTON).simulate('click');
expect(wrapper.find(WAITING_ICON)).to.have.length(5);
})
.then(() => yieldUntilDoneDetecting(wrapper))
.then(() => {
expect(wrapper.find(SUCCESS_ICON)).to.have.length(5);
expect(window.location.reload).not.to.have.been.called;
});
});

it('reloads the page on re-detect if plugin not installed', done => {
it('reloads the page on re-detect if plugin not installed', () => {
checker.detectChromeAppInstalled.rejects(new Error('not installed'));
const wrapper = mount(
<SetupChecklist
setupChecker={checker}
stepDelay={STEP_DELAY}
stepDelay={STEP_DELAY_MS}
/>
);
setTimeout(() => {
expect(wrapper.find('.fa-check-circle')).to.have.length(1);
expect(wrapper.find('.fa-times-circle')).to.have.length(1);
expect(wrapper.find('.fa-clock-o')).to.have.length(3);
wrapper.find('input[value="re-detect"]').simulate('click');
expect(window.location.reload).to.have.been.called;
done();
}, STEP_DELAY * 10);
return yieldUntilDoneDetecting(wrapper)
.then(() => {
expect(wrapper.find(SUCCESS_ICON)).to.have.length(1);
expect(wrapper.find(FAILURE_ICON)).to.have.length(1);
expect(wrapper.find(WAITING_ICON)).to.have.length(3);
wrapper.find(REDETECT_BUTTON).simulate('click');
expect(window.location.reload).to.have.been.called;
});
});

function yieldUntilDoneDetecting(wrapper) {
return yieldUntil(() => !wrapper.find(REDETECT_BUTTON).prop('disabled'));
}
});

/**
* Returns a promise that resolves when a condition becomes true, or rejects
* when a timeout is reached.
* @param {function():boolean} predicate
* @param {number} timeoutMs - maximum time to wait
* @param {number} intervalMs - time to wait between steps
* @return {Promise}
*/
function yieldUntil(predicate, timeoutMs = 2000, intervalMs = 5) {
return new Promise((resolve, reject) => {
let elapsedTime = 0;
const key = setInterval(() => {
if (predicate()) {
clearInterval(key);
resolve();
} else {
elapsedTime += intervalMs;
if (elapsedTime > timeoutMs) {
clearInterval(key);
reject(new Error(`yieldUntil exceeded timeout of ${timeoutMs}ms`));
}
}
}, intervalMs);
});
}

/**
* SetupChecker with all methods stubbed and by default everything succeeds.
* Since methods are sinon stubs, individual tests can modify stub behavior
Expand Down

0 comments on commit 9c340a1

Please sign in to comment.