Merge pull request #1044 from neuroscr/fix-int-tests

Integration tests: Support slower computers/network
This commit is contained in:
Ryan Tharp 2020-04-02 18:42:18 -07:00 committed by GitHub
commit 996d7c9844
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 138 additions and 81 deletions

View file

@ -38,7 +38,7 @@ describe('Add friends', function() {
await common.stopStubSnodeServer();
});
it('can add a friend by sessionID', async () => {
it('addFriends: can add a friend by sessionID', async () => {
const textMessage = common.generateSendMessageText();
await app.client.element(ConversationPage.contactsButtonSection).click();
@ -46,13 +46,16 @@ describe('Add friends', function() {
await app.client.isExisting(ConversationPage.leftPaneOverlay).should
.eventually.be.true;
await app.client
.element(ConversationPage.sessionIDInput)
.setValue(common.TEST_PUBKEY2);
await common.setValueWrapper(
app,
ConversationPage.sessionIDInput,
common.TEST_PUBKEY2
);
await app.client
.element(ConversationPage.sessionIDInput)
.getValue()
.should.eventually.equal(common.TEST_PUBKEY2);
await app.client.element(ConversationPage.nextButton).click();
await app.client.waitForExist(
ConversationPage.sendFriendRequestTextarea,
@ -68,6 +71,7 @@ describe('Add friends', function() {
ConversationPage.existingFriendRequestText(textMessage),
1000
);
// assure friend request message has been sent
await common.timeout(3000);
await app.client.isExisting(ConversationPage.retrySendButton).should

View file

@ -23,14 +23,16 @@ describe('Closed groups', function() {
await common.stopStubSnodeServer();
});
it('can create a closed group with a friend and send/receive a message', async () => {
it('closedGroup: can create a closed group with a friend and send/receive a message', async () => {
await app.client.element(ConversationPage.globeButtonSection).click();
await app.client.element(ConversationPage.createClosedGroupButton).click();
// fill the groupname
await app.client
.element(ConversationPage.closedGroupNameTextarea)
.setValue(common.VALID_CLOSED_GROUP_NAME1);
await common.setValueWrapper(
app,
ConversationPage.closedGroupNameTextarea,
common.VALID_CLOSED_GROUP_NAME1
);
await app.client
.element(ConversationPage.closedGroupNameTextarea)
.getValue()

View file

@ -50,6 +50,38 @@ module.exports = {
return new Promise(resolve => setTimeout(resolve, ms));
},
// a wrapper to work around electron/spectron bug
async setValueWrapper(app, selector, value) {
await app.client.element(selector).click();
// keys, setValue and addValue hang on certain platforms
// could put a branch here to use one of those
// if we know what platforms are good and which ones are broken
await app.client.execute(
(slctr, val) => {
// eslint-disable-next-line no-undef
const iter = document.evaluate(
slctr,
// eslint-disable-next-line no-undef
document,
null,
// eslint-disable-next-line no-undef
XPathResult.UNORDERED_NODE_ITERATOR_TYPE,
null
);
const elem = iter.iterateNext();
if (elem) {
elem.value = val;
} else {
console.error('Cant find', slctr, elem, iter);
}
},
selector,
value
);
// let session js detect the text change
await app.client.element(selector).click();
},
async startApp(environment = 'test-integration-session') {
const env = environment.startsWith('test-integration')
? 'test-integration'
@ -92,16 +124,16 @@ module.exports = {
async stopApp(app1) {
if (app1 && app1.isRunning()) {
await app1.stop();
return Promise.resolve();
}
return Promise.resolve();
},
async killallElectron() {
// rtharp - my 2nd client on MacOs needs: pkill -f "node_modules/.bin/electron"
// node_modules/electron/dist/electron is node_modules/electron/dist/Electron.app on MacOS
const killStr =
process.platform === 'win32'
? 'taskkill /im electron.exe /t /f'
: 'pkill -f "node_modules/electron/dist/electron"';
: 'pkill -f "node_modules/electron/dist/electron" | pkill -f "node_modules/.bin/electron"';
return new Promise(resolve => {
exec(killStr, (err, stdout, stderr) => {
if (err) {
@ -145,23 +177,24 @@ module.exports = {
stubOpenGroups = false,
env = 'test-integration-session',
}) {
const app1 = await this.startAndAssureCleanedApp(env);
const app = await this.startAndAssureCleanedApp(env);
if (stubSnode) {
await this.startStubSnodeServer();
this.stubSnodeCalls(app1);
this.stubSnodeCalls(app);
}
if (stubOpenGroups) {
this.stubOpenGroupsCalls(app1);
this.stubOpenGroupsCalls(app);
}
if (mnemonic && displayName) {
await this.restoreFromMnemonic(app1, mnemonic, displayName);
await this.restoreFromMnemonic(app, mnemonic, displayName);
// not sure we need this - rtharp.
await this.timeout(2000);
}
return app1;
return app;
},
async startAndStub2(props) {
@ -173,18 +206,23 @@ module.exports = {
return app2;
},
async restoreFromMnemonic(app1, mnemonic, displayName) {
await app1.client.element(RegistrationPage.registrationTabSignIn).click();
await app1.client.element(RegistrationPage.restoreFromSeedMode).click();
await app1.client
.element(RegistrationPage.recoveryPhraseInput)
.setValue(mnemonic);
await app1.client
.element(RegistrationPage.displayNameInput)
.setValue(displayName);
async restoreFromMnemonic(app, mnemonic, displayName) {
await app.client.element(RegistrationPage.registrationTabSignIn).click();
await app.client.element(RegistrationPage.restoreFromSeedMode).click();
await this.setValueWrapper(
app,
RegistrationPage.recoveryPhraseInput,
mnemonic
);
await app1.client.element(RegistrationPage.continueSessionButton).click();
await app1.client.waitForExist(
await this.setValueWrapper(
app,
RegistrationPage.displayNameInput,
displayName
);
await app.client.element(RegistrationPage.continueSessionButton).click();
await app.client.waitForExist(
RegistrationPage.conversationListContainer,
4000
);
@ -214,9 +252,11 @@ module.exports = {
await app1.client.element(ConversationPage.contactsButtonSection).click();
await app1.client.element(ConversationPage.addContactButton).click();
await app1.client
.element(ConversationPage.sessionIDInput)
.setValue(this.TEST_PUBKEY2);
await this.setValueWrapper(
app1,
ConversationPage.sessionIDInput,
this.TEST_PUBKEY2
);
await app1.client.element(ConversationPage.nextButton).click();
await app1.client.waitForExist(
ConversationPage.sendFriendRequestTextarea,
@ -224,9 +264,11 @@ module.exports = {
);
// send a text message to that user (will be a friend request)
await app1.client
.element(ConversationPage.sendFriendRequestTextarea)
.setValue(textMessage);
await this.setValueWrapper(
app1,
ConversationPage.sendFriendRequestTextarea,
textMessage
);
await app1.client.keys('Enter');
await app1.client.waitForExist(
ConversationPage.existingFriendRequestText(textMessage),
@ -284,9 +326,12 @@ module.exports = {
// next trigger the link request from the app2 with the app1 pubkey
await app2.client.element(RegistrationPage.registrationTabSignIn).click();
await app2.client.element(RegistrationPage.linkDeviceMode).click();
await app2.client
.element(RegistrationPage.textareaLinkDevicePubkey)
.setValue(this.TEST_PUBKEY1);
await this.setValueWrapper(
app2,
RegistrationPage.textareaLinkDevicePubkey,
this.TEST_PUBKEY1
);
await app2.client.element(RegistrationPage.linkDeviceTriggerButton).click();
await app1.client.waitForExist(RegistrationPage.toastWrapper, 7000);
let secretWordsapp1 = await app1.client

View file

@ -36,11 +36,11 @@ describe('Link Device', function() {
await common.stopStubSnodeServer();
});
it('link two desktop devices', async () => {
it('linkDevice: link two desktop devices', async () => {
await common.linkApp2ToApp(app, app2);
});
it('unlink two devices', async () => {
it('linkDevice: unlink two devices', async () => {
await common.linkApp2ToApp(app, app2);
await common.timeout(1000);
await common.triggerUnlinkApp2FromApp(app, app2);

View file

@ -23,25 +23,25 @@ describe('Open groups', function() {
await common.killallElectron();
});
it('works with valid group url', async () => {
// reduce code duplication to get the initial join
async function joinOpenGroup(url, name) {
await app.client.element(ConversationPage.globeButtonSection).click();
await app.client.element(ConversationPage.joinOpenGroupButton).click();
await app.client
.element(ConversationPage.openGroupInputUrl)
.setValue(common.VALID_GROUP_URL);
await common.setValueWrapper(app, ConversationPage.openGroupInputUrl, url);
await app.client
.element(ConversationPage.openGroupInputUrl)
.getValue()
.should.eventually.equal(common.VALID_GROUP_URL);
.should.eventually.equal(url);
await app.client.element(ConversationPage.joinOpenGroupButton).click();
// validate session loader is shown
await app.client.isExisting(ConversationPage.sessionLoader).should
.eventually.be.true;
// account for slow home internet connection delays...
await app.client.waitForExist(
ConversationPage.sessionToastJoinOpenGroupSuccess,
9000
60 * 1000
);
// validate overlay is closed
@ -50,35 +50,27 @@ describe('Open groups', function() {
// validate open chat has been added
await app.client.waitForExist(
ConversationPage.rowOpenGroupConversationName(common.VALID_GROUP_NAME),
ConversationPage.rowOpenGroupConversationName(name),
4000
);
}
await common.timeout(1000);
it('openGroup: works with valid open group url', async () => {
await joinOpenGroup(common.VALID_GROUP_URL, common.VALID_GROUP_NAME);
});
it('cannot join two times the same open group', async () => {
await app.client.element(ConversationPage.globeButtonSection).click();
await app.client.element(ConversationPage.joinOpenGroupButton).click();
await app.client
.element(ConversationPage.openGroupInputUrl)
.setValue(common.VALID_GROUP_URL2);
await app.client.element(ConversationPage.joinOpenGroupButton).click();
// first add is a success
await common.timeout(2000);
await app.client.waitForExist(
ConversationPage.rowOpenGroupConversationName(common.VALID_GROUP_NAME2),
8000
);
it('openGroup: cannot join two times the same open group', async () => {
await joinOpenGroup(common.VALID_GROUP_URL2, common.VALID_GROUP_NAME2);
// adding a second time the same open group
await app.client.element(ConversationPage.globeButtonSection).click();
await app.client.element(ConversationPage.joinOpenGroupButton).click();
await app.client
.element(ConversationPage.openGroupInputUrl)
.setValue(common.VALID_GROUP_URL2);
await common.setValueWrapper(
app,
ConversationPage.openGroupInputUrl,
common.VALID_GROUP_URL2
);
await app.client.element(ConversationPage.joinOpenGroupButton).click();
// validate session loader is not shown
await app.client.isExisting(ConversationPage.sessionLoader).should
@ -86,7 +78,7 @@ describe('Open groups', function() {
await app.client.waitForExist(
ConversationPage.sessionToastJoinOpenGroupAlreadyExist,
1000
1 * 1000
);
// validate overlay is still opened
@ -94,20 +86,28 @@ describe('Open groups', function() {
.eventually.be.true;
});
it('can send message to open group', async () => {
it('openGroup: can send message to open group', async () => {
// join dev-chat group
await app.client.element(ConversationPage.globeButtonSection).click();
await app.client.element(ConversationPage.joinOpenGroupButton).click();
await app.client
.element(ConversationPage.openGroupInputUrl)
.setValue(common.VALID_GROUP_URL2);
await common.setValueWrapper(
app,
ConversationPage.openGroupInputUrl,
common.VALID_GROUP_URL2
);
await app.client.element(ConversationPage.joinOpenGroupButton).click();
// first add is a success
await common.timeout(2000);
// wait for toast to appear
await app.client.waitForExist(
ConversationPage.sessionToastJoinOpenGroupSuccess,
30 * 1000
);
await common.timeout(5 * 1000); // wait for toast to clear
await app.client.waitForExist(
ConversationPage.rowOpenGroupConversationName(common.VALID_GROUP_NAME2),
8000
10 * 1000
);
// generate a message containing the current timestamp so we can find it in the list of messages
const textMessage = common.generateSendMessageText();
@ -118,14 +118,18 @@ describe('Open groups', function() {
await app.client.isExisting(
ConversationPage.rowOpenGroupConversationName(common.VALID_GROUP_NAME2)
);
await app.client
.element(
ConversationPage.rowOpenGroupConversationName(common.VALID_GROUP_NAME2)
)
.click();
await app.client
.element(ConversationPage.sendMessageTextarea)
.setValue(textMessage);
await common.setValueWrapper(
app,
ConversationPage.sendMessageTextarea,
textMessage
);
await app.client
.element(ConversationPage.sendMessageTextarea)
.getValue()
@ -139,7 +143,7 @@ describe('Open groups', function() {
// validate that the message has been added to the message list view
await app.client.waitForExist(
ConversationPage.existingSendMessageText(textMessage),
3000
3 * 1000
);
// we should validate that the message has been added effectively sent
// (checking the check icon on the metadata part of the message?)

View file

@ -13,6 +13,7 @@ module.exports = {
`//input[contains(@placeholder, "${placeholder}")]`,
textAreaWithPlaceholder: placeholder =>
`//textarea[contains(@placeholder, "${placeholder}")]`,
byId: id => `//*[@id="${id}"]`,
divWithClass: classname => `//div[contains(@class, "${classname}")]`,
divWithClassAndText: (classname, text) =>
module.exports.objWithClassAndText('div', classname, text),

View file

@ -21,12 +21,12 @@ describe('Window Test and Login', function() {
await common.killallElectron();
});
it('opens one window', async () => {
it('registration: opens one window', async () => {
app = await common.startAndAssureCleanedApp();
app.client.getWindowCount().should.eventually.be.equal(1);
});
it('window title is correct', async () => {
it('registration: window title is correct', async () => {
app = await common.startAndAssureCleanedApp();
app.client
@ -34,7 +34,7 @@ describe('Window Test and Login', function() {
.should.eventually.be.equal('Session - test-integration-session');
});
it('can restore from seed', async () => {
it('registration: can restore from seed', async () => {
app = await common.startAndAssureCleanedApp();
await app.client.element(RegistrationPage.registrationTabSignIn).click();
@ -70,7 +70,7 @@ describe('Window Test and Login', function() {
.should.eventually.be.equal(common.TEST_PUBKEY1);
});
it('can create new account', async () => {
it('registration: can create new account', async () => {
app = await common.startAndAssureCleanedApp();
await app.client.element(RegistrationPage.createSessionIDButton).click();
// wait for the animation of generated pubkey to finish
@ -98,7 +98,7 @@ describe('Window Test and Login', function() {
.should.eventually.be.equal(pubkeyGenerated);
});
it('can delete account when logged in', async () => {
it('registration: can delete account when logged in', async () => {
// login as user1
const login = {
mnemonic: common.TEST_MNEMONIC1,

View file

@ -35,7 +35,8 @@
"test-lib-view": "NODE_ENV=test-lib yarn run start",
"test-loki-view": "NODE_ENV=test-loki yarn run start",
"test-electron": "yarn grunt test",
"test-integration": "ELECTRON_DISABLE_SANDBOX=1 mocha --exit --timeout 5000 integration_test/integration_test.js",
"test-integration": "ELECTRON_DISABLE_SANDBOX=1 mocha --exit --timeout 10000 integration_test/integration_test.js",
"test-integration-parts": "ELECTRON_DISABLE_SANDBOX=1 mocha --exit --timeout 10000 integration_test/integration_test.js --grep 'registration' && ELECTRON_DISABLE_SANDBOX=1 mocha --exit --timeout 10000 integration_test/integration_test.js --grep 'openGroup' && ELECTRON_DISABLE_SANDBOX=1 mocha --exit --timeout 10000 integration_test/integration_test.js --grep 'addFriends' && ELECTRON_DISABLE_SANDBOX=1 mocha --exit --timeout 10000 integration_test/integration_test.js --grep 'linkDevice' && ELECTRON_DISABLE_SANDBOX=1 mocha --exit --timeout 10000 integration_test/integration_test.js --grep 'closedGroup'",
"test-node": "mocha --recursive --exit test/app test/modules ts/test libloki/test/node",
"eslint": "eslint --cache .",
"eslint-fix": "eslint --fix .",