From 597705716b30e0efa9cca8e5ac744bda36bf503e Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Tue, 24 Jan 2017 11:26:09 +0000 Subject: [PATCH] Hopefully, fix intermittent test failure This seeks to fix the intermittent failure of the "MatrixClient rehydrated from stored credentials" tests. The problem appears to be that the 'load_completed' is sometimes taking a while to come through from the dispatcher - or rather, it is taking a long time to get *sent* to the dispatcher: the chain of `q().then().catch().done()` in componentDidMount can take a while to happen. As a workaround, give the test a few goes when waiting for us to start syncing. It's not ideal to be poking into the internal state of MatrixChat like this, but it'll do for now. --- test/app-tests/loading.js | 69 +++++++++++++++++++++++---------------- 1 file changed, 40 insertions(+), 29 deletions(-) diff --git a/test/app-tests/loading.js b/test/app-tests/loading.js index 03a4d11e..2fe82e51 100644 --- a/test/app-tests/loading.js +++ b/test/app-tests/loading.js @@ -94,13 +94,13 @@ describe('loading:', function () { loadCompletePromise = loadCompleteDefer.promise; function onNewScreen(screen) { - console.log("newscreen "+screen); + console.log(Date.now() + " newscreen "+screen); if (!appLoaded) { lastLoadedScreen = screen; } else { var hash = '#/' + screen; windowLocation.hash = hash; - console.log("browser URI now "+ windowLocation); + console.log(Date.now() + " browser URI now "+ windowLocation); } } @@ -122,22 +122,22 @@ describe('loading:', function () { ); function routeUrl(location, matrixChat) { - console.log("Routing URL "+location); + console.log(Date.now() + " Routing URL "+location); var fragparts = parseQsFromFragment(location); matrixChat.showScreen(fragparts.location.substring(1), fragparts.params); } // pause for a cycle, then simulate the window.onload handler - q.delay(0).then(() => { - console.log("simulating window.onload"); + window.setTimeout(() => { + console.log(Date.now() + " simulating window.onload"); routeUrl(windowLocation, matrixChat); appLoaded = true; if (lastLoadedScreen) { onNewScreen(lastLoadedScreen); lastLoadedScreen = null; } - }).done(); + }, 0); } describe("Clean load with no stored credentials:", function() { @@ -243,10 +243,8 @@ describe('loading:', function () { loadApp(); - q.delay(1).then(() => { - // we expect a spinner - assertAtSyncingSpinner(matrixChat); - + return awaitSyncingSpinner(matrixChat).then(() => { + // we got a sync spinner - let the sync complete return httpBackend.flush(); }).then(() => { // once the sync completes, we should have a directory @@ -266,10 +264,8 @@ describe('loading:', function () { uriFragment: "#/room/!room:id", }); - q.delay(1).then(() => { - // we expect a spinner - assertAtSyncingSpinner(matrixChat); - + return awaitSyncingSpinner(matrixChat).then(() => { + // we got a sync spinner - let the sync complete return httpBackend.flush(); }).then(() => { // once the sync completes, we should have a room view @@ -300,12 +296,9 @@ describe('loading:', function () { return httpBackend.flush(); }).then(() => { - // Wait for another trip around the event loop for the UI to update - return q.delay(1); + return awaitSyncingSpinner(matrixChat); }).then(() => { - // now we should have a spinner with a logout link - assertAtSyncingSpinner(matrixChat); - + // we got a sync spinner - let the sync complete httpBackend.when('GET', '/sync').respond(200, {}); return httpBackend.flush(); }).then(() => { @@ -338,12 +331,8 @@ describe('loading:', function () { return httpBackend.flush(); }).then(() => { - // Wait for another trip around the event loop for the UI to update - return q.delay(1); + return awaitSyncingSpinner(matrixChat); }).then(() => { - // now we should have a spinner with a logout link - assertAtSyncingSpinner(matrixChat); - httpBackend.when('GET', '/sync').check(function(req) { expect(req.path).toMatch(new RegExp("^https://homeserver/")); }).respond(200, {}); @@ -377,12 +366,8 @@ describe('loading:', function () { return httpBackend.flush(); }).then(() => { - // Wait for another trip around the event loop for the UI to update - return q.delay(1); + return awaitSyncingSpinner(matrixChat); }).then(() => { - // now we should have a spinner with a logout link - assertAtSyncingSpinner(matrixChat); - httpBackend.when('GET', '/sync').respond(200, {}); return httpBackend.flush(); }).then(() => { @@ -448,6 +433,32 @@ function assertAtLoadingSpinner(matrixChat) { // we've got login creds, and are waiting for the sync to finish. // the page includes a logout link. +function awaitSyncingSpinner(matrixChat, retryLimit, retryCount) { + if (retryLimit === undefined) { + retryLimit = 5; + } + if (retryCount === undefined) { + retryCount = 0; + } + + if (matrixChat.state.loading) { + console.log(Date.now() + " Awaiting sync spinner: still loading."); + if (retryCount >= retryLimit) { + throw new Error("MatrixChat still not loaded after " + + retryCount + " tries"); + } + return q.delay(0).then(() => { + return awaitSyncingSpinner(matrixChat, retryLimit, retryCount + 1); + }); + } + + console.log(Date.now() + " Awaiting sync spinner: load complete."); + + // state looks good, check the rendered output + assertAtSyncingSpinner(matrixChat); + return q(); +} + function assertAtSyncingSpinner(matrixChat) { var domComponent = ReactDOM.findDOMNode(matrixChat); expect(domComponent.className).toEqual("mx_MatrixChat_splash");