Fix password UI auth test

By adding a way to wait a short time for a component to appear in
the DOM, so we don't get flakey failures like this when we change
something to returning a promise that needs to resolve before the
component actually appears.
This commit is contained in:
David Baker 2017-03-16 17:26:42 +00:00
parent c413de4452
commit 375ae8fb04
2 changed files with 83 additions and 42 deletions

View file

@ -68,50 +68,51 @@ describe('InteractiveAuthDialog', function () {
onFinished={onFinished} onFinished={onFinished}
/>, parentDiv); />, parentDiv);
// at this point there should be a password box and a submit button // wait for a password box and a submit button
const formNode = ReactTestUtils.findRenderedDOMComponentWithTag(dlg, "form"); test_utils.waitForRenderedDOMComponentWithTag(dlg, "form").then((formNode) => {
const inputNodes = ReactTestUtils.scryRenderedDOMComponentsWithTag( const inputNodes = ReactTestUtils.scryRenderedDOMComponentsWithTag(
dlg, "input" dlg, "input"
); );
let passwordNode; let passwordNode;
let submitNode; let submitNode;
for (const node of inputNodes) { for (const node of inputNodes) {
if (node.type == 'password') { if (node.type == 'password') {
passwordNode = node; passwordNode = node;
} else if (node.type == 'submit') { } else if (node.type == 'submit') {
submitNode = node; submitNode = node;
}
} }
} expect(passwordNode).toExist();
expect(passwordNode).toExist(); expect(submitNode).toExist();
expect(submitNode).toExist();
// submit should be disabled // submit should be disabled
expect(submitNode.disabled).toBe(true); expect(submitNode.disabled).toBe(true);
// put something in the password box, and hit enter; that should // put something in the password box, and hit enter; that should
// trigger a request // trigger a request
passwordNode.value = "s3kr3t"; passwordNode.value = "s3kr3t";
ReactTestUtils.Simulate.change(passwordNode); ReactTestUtils.Simulate.change(passwordNode);
expect(submitNode.disabled).toBe(false); expect(submitNode.disabled).toBe(false);
ReactTestUtils.Simulate.submit(formNode, {}); ReactTestUtils.Simulate.submit(formNode, {});
expect(doRequest.callCount).toEqual(1); expect(doRequest.callCount).toEqual(1);
expect(doRequest.calledWithExactly({ expect(doRequest.calledWithExactly({
session: "sess", session: "sess",
type: "m.login.password", type: "m.login.password",
password: "s3kr3t", password: "s3kr3t",
user: "@user:id", user: "@user:id",
})).toBe(true); })).toBe(true);
// there should now be a spinner // there should now be a spinner
ReactTestUtils.findRenderedComponentWithType( ReactTestUtils.findRenderedComponentWithType(
dlg, sdk.getComponent('elements.Spinner'), dlg, sdk.getComponent('elements.Spinner'),
); );
// let the request complete // let the request complete
q.delay(1).then(() => { return q.delay(1);
}).then(() => {
expect(onFinished.callCount).toEqual(1); expect(onFinished.callCount).toEqual(1);
expect(onFinished.calledWithExactly(true, {a:1})).toBe(true); expect(onFinished.calledWithExactly(true, {a:1})).toBe(true);
}).done(done, done); }).done(done);
}); });
}); });

View file

@ -1,11 +1,51 @@
"use strict"; "use strict";
var sinon = require('sinon'); import sinon from 'sinon';
var q = require('q'); import q from 'q';
import ReactTestUtils from 'react-addons-test-utils';
var peg = require('../src/MatrixClientPeg.js'); import peg from '../src/MatrixClientPeg.js';
var jssdk = require('matrix-js-sdk'); import jssdk from 'matrix-js-sdk';
var MatrixEvent = jssdk.MatrixEvent; const MatrixEvent = jssdk.MatrixEvent;
/**
* Wrapper around window.requestAnimationFrame that returns a promise
* @private
*/
function _waitForFrame() {
const def = q.defer();
window.requestAnimationFrame(() => {
def.resolve();
});
return def.promise;
}
/**
* Waits a small number of animation frames for a component to appear
* in the DOM. Like findRenderedDOMComponentWithTag(), but allows
* for the element to appear a short time later, eg. if a promise needs
* to resolve first.
* @return a promise that resolves once the component appears, or rejects
* if it doesn't appear after a nominal number of animation frames.
*/
export function waitForRenderedDOMComponentWithTag(tree, tag, attempts) {
if (attempts === undefined) {
// Let's start by assuming we'll only need to wait a single frame, and
// we can try increasing this if necessary.
attempts = 1;
} else if (attempts == 0) {
return q.reject("Gave up waiting for component with tag: " + tag);
}
return _waitForFrame().then(() => {
const result = ReactTestUtils.scryRenderedDOMComponentsWithTag(tree, tag);
if (result.length > 0) {
return result[0];
} else {
return waitForRenderedDOMComponentWithTag(tree, tag, attempts - 1);
}
});
}
/** /**
* Perform common actions before each test case, e.g. printing the test case * Perform common actions before each test case, e.g. printing the test case