tests: Factor out USER_CHANGES/ACCEPT_COMMIT helpers
This will make it possible for other tests to reuse the code.pull/5331/head
parent
674a0ccedc
commit
02d1b90d30
|
@ -1,6 +1,8 @@
|
|||
'use strict';
|
||||
|
||||
const AttributePool = require('../../static/js/AttributePool');
|
||||
const apiHandler = require('../../node/handler/APIHandler');
|
||||
const assert = require('assert').strict;
|
||||
const io = require('socket.io-client');
|
||||
const log4js = require('log4js');
|
||||
const process = require('process');
|
||||
|
@ -185,6 +187,58 @@ exports.handshake = async (socket, padId) => {
|
|||
return msg;
|
||||
};
|
||||
|
||||
/**
|
||||
* Convenience wrapper around `socket.send()` that waits for acknowledgement.
|
||||
*/
|
||||
exports.sendMessage = async (socket, message) => await new Promise((resolve, reject) => {
|
||||
socket.send(message, (errInfo) => {
|
||||
if (errInfo != null) {
|
||||
const {name, message} = errInfo;
|
||||
const err = new Error(message);
|
||||
err.name = name;
|
||||
reject(err);
|
||||
return;
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Convenience function to send a USER_CHANGES message. Waits for acknowledgement.
|
||||
*/
|
||||
exports.sendUserChanges = async (socket, data) => await exports.sendMessage(socket, {
|
||||
type: 'COLLABROOM',
|
||||
component: 'pad',
|
||||
data: {
|
||||
type: 'USER_CHANGES',
|
||||
apool: new AttributePool(),
|
||||
...data,
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Convenience function that waits for an ACCEPT_COMMIT message. Asserts that the new revision
|
||||
* matches the expected revision.
|
||||
*
|
||||
* Note: To avoid a race condition, this should be called before the USER_CHANGES message is sent.
|
||||
* For example:
|
||||
*
|
||||
* await Promise.all([
|
||||
* common.waitForAcceptCommit(socket, rev + 1),
|
||||
* common.sendUserChanges(socket, {baseRev: rev, changeset}),
|
||||
* ]);
|
||||
*/
|
||||
exports.waitForAcceptCommit = async (socket, wantRev) => {
|
||||
const msg = await exports.waitForSocketEvent(socket, 'message');
|
||||
assert.deepEqual(msg, {
|
||||
type: 'COLLABROOM',
|
||||
data: {
|
||||
type: 'ACCEPT_COMMIT',
|
||||
newRev: wantRev,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const alphabet = 'abcdefghijklmnopqrstuvwxyz';
|
||||
|
||||
/**
|
||||
|
|
|
@ -36,27 +36,10 @@ describe(__filename, function () {
|
|||
});
|
||||
|
||||
describe('USER_CHANGES', function () {
|
||||
const sendUserChanges = (changeset, apool = new AttributePool()) => {
|
||||
socket.json.send({
|
||||
type: 'COLLABROOM',
|
||||
component: 'pad',
|
||||
data: {
|
||||
type: 'USER_CHANGES',
|
||||
baseRev: rev,
|
||||
changeset,
|
||||
apool: new AttributePool(),
|
||||
},
|
||||
});
|
||||
};
|
||||
const sendUserChanges =
|
||||
async (changeset) => await common.sendUserChanges(socket, {baseRev: rev, changeset});
|
||||
const assertAccepted = async (wantRev) => {
|
||||
const msg = await common.waitForSocketEvent(socket, 'message');
|
||||
assert.deepEqual(msg, {
|
||||
type: 'COLLABROOM',
|
||||
data: {
|
||||
type: 'ACCEPT_COMMIT',
|
||||
newRev: wantRev,
|
||||
},
|
||||
});
|
||||
await common.waitForAcceptCommit(socket, wantRev);
|
||||
rev = wantRev;
|
||||
};
|
||||
const assertRejected = async () => {
|
||||
|
@ -65,38 +48,55 @@ describe(__filename, function () {
|
|||
};
|
||||
|
||||
it('changes are applied', async function () {
|
||||
sendUserChanges('Z:1>5+5$hello');
|
||||
await assertAccepted(rev + 1);
|
||||
await Promise.all([
|
||||
assertAccepted(rev + 1),
|
||||
sendUserChanges('Z:1>5+5$hello'),
|
||||
]);
|
||||
assert.equal(pad.text(), 'hello\n');
|
||||
});
|
||||
|
||||
it('bad changeset is rejected', async function () {
|
||||
sendUserChanges('this is not a valid changeset');
|
||||
await assertRejected();
|
||||
await Promise.all([
|
||||
assertRejected(),
|
||||
sendUserChanges('this is not a valid changeset'),
|
||||
]);
|
||||
});
|
||||
|
||||
it('retransmission is accepted, has no effect', async function () {
|
||||
sendUserChanges('Z:1>5+5$hello');
|
||||
await assertAccepted(rev + 1);
|
||||
const cs = 'Z:1>5+5$hello';
|
||||
await Promise.all([
|
||||
assertAccepted(rev + 1),
|
||||
sendUserChanges(cs),
|
||||
]);
|
||||
--rev;
|
||||
sendUserChanges('Z:1>5+5$hello');
|
||||
await assertAccepted(rev + 1);
|
||||
await Promise.all([
|
||||
assertAccepted(rev + 1),
|
||||
sendUserChanges(cs),
|
||||
]);
|
||||
assert.equal(pad.text(), 'hello\n');
|
||||
});
|
||||
|
||||
it('identity changeset is accepted, has no effect', async function () {
|
||||
sendUserChanges('Z:1>5+5$hello');
|
||||
await assertAccepted(rev + 1);
|
||||
sendUserChanges('Z:6>0$');
|
||||
await assertAccepted(rev);
|
||||
await Promise.all([
|
||||
assertAccepted(rev + 1),
|
||||
sendUserChanges('Z:1>5+5$hello'),
|
||||
]);
|
||||
await Promise.all([
|
||||
assertAccepted(rev),
|
||||
sendUserChanges('Z:6>0$'),
|
||||
]);
|
||||
assert.equal(pad.text(), 'hello\n');
|
||||
});
|
||||
|
||||
it('non-identity changeset with no net change is accepted, has no effect', async function () {
|
||||
sendUserChanges('Z:1>5+5$hello');
|
||||
await assertAccepted(rev + 1);
|
||||
sendUserChanges('Z:6>0-5+5$hello');
|
||||
await assertAccepted(rev);
|
||||
await Promise.all([
|
||||
assertAccepted(rev + 1),
|
||||
sendUserChanges('Z:1>5+5$hello'),
|
||||
]);
|
||||
await Promise.all([
|
||||
assertAccepted(rev),
|
||||
sendUserChanges('Z:6>0-5+5$hello'),
|
||||
]);
|
||||
assert.equal(pad.text(), 'hello\n');
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue