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

View file

@ -1,11 +1,51 @@
"use strict";
var sinon = require('sinon');
var q = require('q');
import sinon from 'sinon';
import q from 'q';
import ReactTestUtils from 'react-addons-test-utils';
var peg = require('../src/MatrixClientPeg.js');
var jssdk = require('matrix-js-sdk');
var MatrixEvent = jssdk.MatrixEvent;
import peg from '../src/MatrixClientPeg.js';
import jssdk from 'matrix-js-sdk';
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