1
0
mirror of https://github.com/matrix-org/matrix-js-sdk.git synced 2025-09-01 21:21:58 +03:00

Fix MatrixClient unit tests

This commit is contained in:
Kegan Dougal
2015-12-11 11:07:31 +00:00
parent d6ba39f292
commit 26d9fed537
3 changed files with 102 additions and 71 deletions

View File

@@ -2502,7 +2502,7 @@ module.exports.CRYPTO_ENABLED = CRYPTO_ENABLED;
* a state of SYNCING. <i>This is the equivalent of "syncComplete" in the * a state of SYNCING. <i>This is the equivalent of "syncComplete" in the
* previous API.</i></li> * previous API.</i></li>
* <li>SYNCING : The client is currently polling for new events from the server. * <li>SYNCING : The client is currently polling for new events from the server.
* The client may fire this before or after processing latest events from a sync.</li> * This will be called <i>after</i> processing latest events from a sync.</li>
* <li>ERROR : The client has had a problem syncing with the server. If this is * <li>ERROR : The client has had a problem syncing with the server. If this is
* called <i>before</i> PREPARED then there was a problem performing the initial * called <i>before</i> PREPARED then there was a problem performing the initial
* sync. If this is called <i>after</i> PREPARED then there was a problem polling * sync. If this is called <i>after</i> PREPARED then there was a problem polling
@@ -2523,7 +2523,7 @@ module.exports.CRYPTO_ENABLED = CRYPTO_ENABLED;
* Transitions: * Transitions:
* <ul> * <ul>
* <li><code>null -> PREPARED</code> : Occurs when the initial sync is completed * <li><code>null -> PREPARED</code> : Occurs when the initial sync is completed
* first time. * first time. This involves setting up filters and obtaining push rules.
* <li><code>null -> ERROR</code> : Occurs when the initial sync failed first time. * <li><code>null -> ERROR</code> : Occurs when the initial sync failed first time.
* <li><code>ERROR -> PREPARED</code> : Occurs when the initial sync succeeds * <li><code>ERROR -> PREPARED</code> : Occurs when the initial sync succeeds
* after previously failing. * after previously failing.
@@ -2535,6 +2535,8 @@ module.exports.CRYPTO_ENABLED = CRYPTO_ENABLED;
* live update after having previously failed. * live update after having previously failed.
* <li><code>ERROR -> ERROR</code> : Occurs when the client has failed to sync * <li><code>ERROR -> ERROR</code> : Occurs when the client has failed to sync
* for a second time or more.</li> * for a second time or more.</li>
* <li><code>SYNCING -> SYNCING</code> : Occurs when the client has performed a live
* update. This is called <i>after</i> processing.</li>
* </ul> * </ul>
* *
* @event module:client~MatrixClient#"sync" * @event module:client~MatrixClient#"sync"

View File

@@ -161,7 +161,7 @@ SyncApi.prototype._sync = function(syncOptions, attempt) {
} }
if (client._guestRooms && client._isGuest) { if (client._guestRooms && client._isGuest) {
qps.room_id = JSON.stringify(client._guestRooms); qps.room_id = client._guestRooms;
} }
// Set up local timer and error handler for retries. // Set up local timer and error handler for retries.

View File

@@ -9,20 +9,30 @@ describe("MatrixClient", function() {
var identityServerUrl = "https://identity.server"; var identityServerUrl = "https://identity.server";
var client, store, scheduler; var client, store, scheduler;
var initialSyncData = {
end: "s_5_3",
presence: [],
rooms: []
};
var eventData = {
start: "s_START",
end: "s_END",
chunk: []
};
var PUSH_RULES_RESPONSE = { var PUSH_RULES_RESPONSE = {
method: "GET", path: "/pushrules/", data: {} method: "GET",
path: "/pushrules/",
data: {}
};
var FILTER_PATH = "/user/" + encodeURIComponent(userId) + "/filter";
var FILTER_RESPONSE = {
method: "POST",
path: FILTER_PATH,
data: { filter_id: "f1lt3r" }
};
var SYNC_DATA = {
next_batch: "s_5_3",
presence: { events: [] },
rooms: {}
};
var SYNC_RESPONSE = {
method: "GET",
path: "/sync",
data: SYNC_DATA
}; };
var httpLookups = [ var httpLookups = [
@@ -107,7 +117,8 @@ describe("MatrixClient", function() {
]); ]);
store = jasmine.createSpyObj("store", [ store = jasmine.createSpyObj("store", [
"getRoom", "getRooms", "getUser", "getSyncToken", "scrollback", "getRoom", "getRooms", "getUser", "getSyncToken", "scrollback",
"setSyncToken", "storeEvents", "storeRoom", "storeUser" "setSyncToken", "storeEvents", "storeRoom", "storeUser",
"getFilterIdByName", "setFilterIdByName", "getFilter", "storeFilter"
]); ]);
client = new MatrixClient({ client = new MatrixClient({
baseUrl: "https://my.home.server", baseUrl: "https://my.home.server",
@@ -130,9 +141,8 @@ describe("MatrixClient", function() {
pendingLookup = null; pendingLookup = null;
httpLookups = []; httpLookups = [];
httpLookups.push(PUSH_RULES_RESPONSE); httpLookups.push(PUSH_RULES_RESPONSE);
httpLookups.push({ httpLookups.push(FILTER_RESPONSE);
method: "GET", path: "/initialSync", data: initialSyncData httpLookups.push(SYNC_RESPONSE);
});
}); });
afterEach(function() { afterEach(function() {
@@ -156,9 +166,10 @@ describe("MatrixClient", function() {
}); });
it("should return the same sync state as emitted sync events", function(done) { it("should return the same sync state as emitted sync events", function(done) {
client.on("sync", function(state) { client.on("sync", function syncListener(state) {
expect(state).toEqual(client.getSyncState()); expect(state).toEqual(client.getSyncState());
if (state === "SYNCING") { if (state === "SYNCING") {
client.removeListener("sync", syncListener);
done(); done();
} }
}); });
@@ -172,40 +183,46 @@ describe("MatrixClient", function() {
expect(client.retryImmediately()).toBe(false); expect(client.retryImmediately()).toBe(false);
}); });
it("should work on /initialSync", function(done) { it("should work on /filter", function(done) {
httpLookups = []; httpLookups = [];
httpLookups.push(PUSH_RULES_RESPONSE); httpLookups.push(PUSH_RULES_RESPONSE);
httpLookups.push({ httpLookups.push({
method: "GET", path: "/initialSync", error: { errcode: "NOPE_NOPE_NOPE" } method: "POST", path: FILTER_PATH, error: { errcode: "NOPE_NOPE_NOPE" }
}); });
httpLookups.push({ httpLookups.push({
method: "GET", path: "/initialSync", error: { errcode: "NOPE_NOPE_NOPE" } method: "POST", path: FILTER_PATH, error: { errcode: "NOPE_NOPE_NOPE" }
}); });
client.on("sync", function(state) { client.on("sync", function syncListener(state) {
if (state === "ERROR" && httpLookups.length > 0) { if (state === "ERROR" && httpLookups.length > 0) {
expect(httpLookups.length).toEqual(1); expect(httpLookups.length).toEqual(1);
expect(client.retryImmediately()).toBe(true); expect(client.retryImmediately()).toBe(true);
expect(httpLookups.length).toEqual(0); expect(httpLookups.length).toEqual(0);
client.removeListener("sync", syncListener);
done(); done();
} }
}); });
client.startClient(); client.startClient();
}); });
it("should work on /events", function(done) { it("should work on /sync", function(done) {
httpLookups.push({ httpLookups.push({
method: "GET", path: "/events", error: { errcode: "NOPE_NOPE_NOPE" } method: "GET", path: "/sync", error: { errcode: "NOPE_NOPE_NOPE" }
}); });
httpLookups.push({ httpLookups.push({
method: "GET", path: "/events", data: eventData method: "GET", path: "/sync", data: SYNC_DATA
}); });
client.on("sync", function(state) { client.on("sync", function syncListener(state) {
if (state === "ERROR" && httpLookups.length > 0) { if (state === "ERROR" && httpLookups.length > 0) {
expect(httpLookups.length).toEqual(1); expect(httpLookups.length).toEqual(1);
expect(client.retryImmediately()).toBe(true); expect(client.retryImmediately()).toBe(
expect(httpLookups.length).toEqual(0); true, "retryImmediately returned false"
);
expect(httpLookups.length).toEqual(
0, "more httpLookups remaining than expected"
);
client.removeListener("sync", syncListener);
done(); done();
} }
}); });
@@ -221,11 +238,12 @@ describe("MatrixClient", function() {
method: "GET", path: "/pushrules/", error: { errcode: "NOPE_NOPE_NOPE" } method: "GET", path: "/pushrules/", error: { errcode: "NOPE_NOPE_NOPE" }
}); });
client.on("sync", function(state) { client.on("sync", function syncListener(state) {
if (state === "ERROR" && httpLookups.length > 0) { if (state === "ERROR" && httpLookups.length > 0) {
expect(httpLookups.length).toEqual(1); expect(httpLookups.length).toEqual(1);
expect(client.retryImmediately()).toBe(true); expect(client.retryImmediately()).toBe(true);
expect(httpLookups.length).toEqual(0); expect(httpLookups.length).toEqual(0);
client.removeListener("sync", syncListener);
done(); done();
} }
}); });
@@ -234,10 +252,9 @@ describe("MatrixClient", function() {
}); });
describe("emitted sync events", function() { describe("emitted sync events", function() {
var expectedStates;
function syncChecker(done) { function syncChecker(expectedStates, done) {
return function(state, old) { return function syncListener(state, old) {
var expected = expectedStates.shift(); var expected = expectedStates.shift();
console.log( console.log(
"'sync' curr=%s old=%s EXPECT=%s", state, old, expected "'sync' curr=%s old=%s EXPECT=%s", state, old, expected
@@ -249,6 +266,7 @@ describe("MatrixClient", function() {
expect(state).toEqual(expected[0]); expect(state).toEqual(expected[0]);
expect(old).toEqual(expected[1]); expect(old).toEqual(expected[1]);
if (expectedStates.length === 0) { if (expectedStates.length === 0) {
client.removeListener("sync", syncListener);
done(); done();
} }
// standard retry time is 4s // standard retry time is 4s
@@ -256,94 +274,107 @@ describe("MatrixClient", function() {
}; };
} }
beforeEach(function() { it("should transition null -> PREPARED after the first /sync", function(done) {
expectedStates = [ var expectedStates = [];
// [current, old]
];
});
it("should transition null -> PREPARED after /initialSync", function(done) {
expectedStates.push(["PREPARED", null]); expectedStates.push(["PREPARED", null]);
client.on("sync", syncChecker(done)); client.on("sync", syncChecker(expectedStates, done));
client.startClient(); client.startClient();
}); });
it("should transition null -> ERROR after a failed /initialSync", function(done) { it("should transition null -> ERROR after a failed /filter", function(done) {
var expectedStates = [];
httpLookups = []; httpLookups = [];
httpLookups.push(PUSH_RULES_RESPONSE); httpLookups.push(PUSH_RULES_RESPONSE);
httpLookups.push({ httpLookups.push({
method: "GET", path: "/initialSync", error: { errcode: "NOPE_NOPE_NOPE" } method: "POST", path: FILTER_PATH, error: { errcode: "NOPE_NOPE_NOPE" }
}); });
expectedStates.push(["ERROR", null]); expectedStates.push(["ERROR", null]);
client.on("sync", syncChecker(done)); client.on("sync", syncChecker(expectedStates, done));
client.startClient(); client.startClient();
}); });
it("should transition ERROR -> PREPARED after /initialSync if prev failed", it("should transition ERROR -> PREPARED after /sync if prev failed",
function(done) { function(done) {
var expectedStates = [];
httpLookups = []; httpLookups = [];
httpLookups.push(PUSH_RULES_RESPONSE); httpLookups.push(PUSH_RULES_RESPONSE);
httpLookups.push(FILTER_RESPONSE);
httpLookups.push({ httpLookups.push({
method: "GET", path: "/initialSync", error: { errcode: "NOPE_NOPE_NOPE" } method: "GET", path: "/sync", error: { errcode: "NOPE_NOPE_NOPE" }
}); });
httpLookups.push({ httpLookups.push({
method: "GET", path: "/initialSync", data: initialSyncData method: "GET", path: "/sync", data: SYNC_DATA
}); });
expectedStates.push(["ERROR", null]); expectedStates.push(["ERROR", null]);
expectedStates.push(["PREPARED", "ERROR"]); expectedStates.push(["PREPARED", "ERROR"]);
client.on("sync", syncChecker(done)); client.on("sync", syncChecker(expectedStates, done));
client.startClient(); client.startClient();
}); });
it("should transition PREPARED -> SYNCING after /initialSync", function(done) { it("should transition PREPARED -> SYNCING after /sync", function(done) {
var expectedStates = [];
expectedStates.push(["PREPARED", null]); expectedStates.push(["PREPARED", null]);
expectedStates.push(["SYNCING", "PREPARED"]); expectedStates.push(["SYNCING", "PREPARED"]);
client.on("sync", syncChecker(done)); client.on("sync", syncChecker(expectedStates, done));
client.startClient(); client.startClient();
}); });
it("should transition SYNCING -> ERROR after a failed /events", function(done) { it("should transition SYNCING -> ERROR after a failed /sync", function(done) {
var expectedStates = [];
httpLookups.push({ httpLookups.push({
method: "GET", path: "/events", error: { errcode: "NONONONONO" } method: "GET", path: "/sync", error: { errcode: "NONONONONO" }
}); });
expectedStates.push(["PREPARED", null]); expectedStates.push(["PREPARED", null]);
expectedStates.push(["SYNCING", "PREPARED"]); expectedStates.push(["SYNCING", "PREPARED"]);
expectedStates.push(["ERROR", "SYNCING"]); expectedStates.push(["ERROR", "SYNCING"]);
client.on("sync", syncChecker(done)); client.on("sync", syncChecker(expectedStates, done));
client.startClient(); client.startClient();
}); });
it("should transition ERROR -> SYNCING after /events if prev failed", xit("should transition ERROR -> SYNCING after /sync if prev failed",
function(done) { function(done) {
var expectedStates = [];
httpLookups.push({ httpLookups.push({
method: "GET", path: "/events", error: { errcode: "NONONONONO" } method: "GET", path: "/sync", error: { errcode: "NONONONONO" }
});
httpLookups.push({
method: "GET", path: "/events", data: eventData
}); });
httpLookups.push(SYNC_RESPONSE);
expectedStates.push(["PREPARED", null]); expectedStates.push(["PREPARED", null]);
expectedStates.push(["SYNCING", "PREPARED"]); expectedStates.push(["SYNCING", "PREPARED"]);
expectedStates.push(["ERROR", "SYNCING"]); expectedStates.push(["ERROR", "SYNCING"]);
client.on("sync", syncChecker(done)); client.on("sync", syncChecker(expectedStates, done));
client.startClient(); client.startClient();
}); });
it("should transition ERROR -> ERROR if multiple /events fails", function(done) { it("should transition SYNCING -> SYNCING on subsequent /sync successes",
function(done) {
var expectedStates = [];
httpLookups.push(SYNC_RESPONSE);
httpLookups.push(SYNC_RESPONSE);
expectedStates.push(["PREPARED", null]);
expectedStates.push(["SYNCING", "PREPARED"]);
expectedStates.push(["SYNCING", "SYNCING"]);
client.on("sync", syncChecker(expectedStates, done));
client.startClient();
});
it("should transition ERROR -> ERROR if multiple /sync fails", function(done) {
var expectedStates = [];
httpLookups.push({ httpLookups.push({
method: "GET", path: "/events", error: { errcode: "NONONONONO" } method: "GET", path: "/sync", error: { errcode: "NONONONONO" }
}); });
httpLookups.push({ httpLookups.push({
method: "GET", path: "/events", error: { errcode: "NONONONONO" } method: "GET", path: "/sync", error: { errcode: "NONONONONO" }
}); });
expectedStates.push(["PREPARED", null]); expectedStates.push(["PREPARED", null]);
expectedStates.push(["SYNCING", "PREPARED"]); expectedStates.push(["SYNCING", "PREPARED"]);
expectedStates.push(["ERROR", "SYNCING"]); expectedStates.push(["ERROR", "SYNCING"]);
expectedStates.push(["ERROR", "ERROR"]); expectedStates.push(["ERROR", "ERROR"]);
client.on("sync", syncChecker(done)); client.on("sync", syncChecker(expectedStates, done));
client.startClient(); client.startClient();
}); });
}); });
@@ -373,15 +404,13 @@ describe("MatrixClient", function() {
"!foo:bar", "!baz:bar" "!foo:bar", "!baz:bar"
]; ];
it("should be set via setGuestRooms and used in /events calls", function(done) { it("should be set via setGuestRooms and used in /sync calls", function(done) {
httpLookups = []; // no /pushrules httpLookups = []; // no /pushrules
httpLookups.push({ httpLookups.push(FILTER_RESPONSE);
method: "GET", path: "/initialSync", data: initialSyncData
});
httpLookups.push({ httpLookups.push({
method: "GET", method: "GET",
path: "/events", path: "/sync",
data: eventData, data: SYNC_DATA,
expectQueryParams: { expectQueryParams: {
room_id: roomIds room_id: roomIds
}, },