Merge pull request #1077 from vincentbavitz/integration-test-vince

Message & Settings Tests
pull/1113/head
Vince 5 years ago committed by GitHub
commit cdc88f3cd1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,7 +1,8 @@
/* eslint-disable func-names */
/* eslint-disable import/no-extraneous-dependencies */
const common = require('./common');
const { afterEach, beforeEach, describe, it } = require('mocha');
const common = require('./common');
const ConversationPage = require('./page-objects/conversation.page');
describe('Add friends', function() {

@ -1,7 +1,8 @@
/* eslint-disable func-names */
/* eslint-disable import/no-extraneous-dependencies */
const common = require('./common');
const { afterEach, beforeEach, describe, it } = require('mocha');
const common = require('./common');
const ConversationPage = require('./page-objects/conversation.page');
describe('Closed groups', function() {
@ -27,80 +28,8 @@ describe('Closed groups', function() {
await app.client.element(ConversationPage.globeButtonSection).click();
await app.client.element(ConversationPage.createClosedGroupButton).click();
// fill the groupname
await common.setValueWrapper(
app,
ConversationPage.closedGroupNameTextarea,
common.VALID_CLOSED_GROUP_NAME1
);
await app.client
.element(ConversationPage.closedGroupNameTextarea)
.getValue()
.should.eventually.equal(common.VALID_CLOSED_GROUP_NAME1);
await app.client
.element(ConversationPage.createClosedGroupMemberItem)
.isVisible();
// select the first friend as a member of the groups being created
await app.client
.element(ConversationPage.createClosedGroupMemberItem)
.click();
await app.client
.element(ConversationPage.createClosedGroupMemberItemSelected)
.isVisible();
// trigger the creation of the group
await app.client
.element(ConversationPage.validateCreationClosedGroupButton)
.click();
await app.client.waitForExist(
ConversationPage.sessionToastGroupCreatedSuccess,
1000
);
await app.client.isExisting(
ConversationPage.headerTitleGroupName(common.VALID_CLOSED_GROUP_NAME1)
).should.eventually.be.true;
await app.client
.element(ConversationPage.headerTitleMembers(2))
.isVisible();
// validate overlay is closed
await app.client.isExisting(ConversationPage.leftPaneOverlay).should
.eventually.be.false;
// move back to the conversation section
await app.client
.element(ConversationPage.conversationButtonSection)
.click();
// validate open chat has been added
await app.client.isExisting(
ConversationPage.rowOpenGroupConversationName(
common.VALID_CLOSED_GROUP_NAME1
)
).should.eventually.be.true;
// next check app2 has been invited and has the group in its conversations
await app2.client.waitForExist(
ConversationPage.rowOpenGroupConversationName(
common.VALID_CLOSED_GROUP_NAME1
),
6000
);
// open the closed group conversation on app2
await app2.client
.element(ConversationPage.conversationButtonSection)
.click();
await common.timeout(500);
await app2.client
.element(
ConversationPage.rowOpenGroupConversationName(
common.VALID_CLOSED_GROUP_NAME1
)
)
.click();
// create group and add new friend
await common.addFriendToNewClosedGroup(app, app2);
// send a message from app and validate it is received on app2
const textMessage = common.generateSendMessageText();

@ -4,15 +4,17 @@
const { Application } = require('spectron');
const path = require('path');
const url = require('url');
const http = require('http');
const fse = require('fs-extra');
const { exec } = require('child_process');
const chai = require('chai');
const chaiAsPromised = require('chai-as-promised');
const CommonPage = require('./page-objects/common.page');
const RegistrationPage = require('./page-objects/registration.page');
const ConversationPage = require('./page-objects/conversation.page');
const { exec } = require('child_process');
const url = require('url');
const http = require('http');
const fse = require('fs-extra');
const SettingsPage = require('./page-objects/settings.page');
chai.should();
chai.use(chaiAsPromised);
@ -35,6 +37,12 @@ module.exports = {
'054e1ca8681082dbd9aad1cf6fc89a32254e15cba50c75b5a73ac10a0b96bcbd2a',
TEST_DISPLAY_NAME2: 'integration_tester_2',
TEST_MNEMONIC3:
'alpine lukewarm oncoming blender kiwi fuel lobster upkeep vogue simplest gasp fully simplest',
TEST_PUBKEY3:
'05f8662b6e83da5a31007cc3ded44c601f191e07999acb6db2314a896048d9036c',
TEST_DISPLAY_NAME3: 'integration_tester_3',
/* ************** OPEN GROUPS ****************** */
VALID_GROUP_URL: 'https://chat.getsession.org',
VALID_GROUP_URL2: 'https://chat-dev.lokinet.org',
@ -50,36 +58,43 @@ module.exports = {
return new Promise(resolve => setTimeout(resolve, ms));
},
async closeToast(app) {
app.client.element(CommonPage.toastCloseButton).click();
},
// 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,
if (process.platform === 'darwin') {
await app.client.execute(
(slctr, val) => {
// 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();
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();
} else {
// Linux & Windows don't require wrapper
await app.client.element(selector).setValue(value);
}
},
async startApp(environment = 'test-integration-session') {
@ -135,12 +150,8 @@ module.exports = {
? 'taskkill /im electron.exe /t /f'
: 'pkill -f "node_modules/electron/dist/electron" | pkill -f "node_modules/.bin/electron"';
return new Promise(resolve => {
exec(killStr, (err, stdout, stderr) => {
if (err) {
resolve({ stdout, stderr });
} else {
resolve({ stdout, stderr });
}
exec(killStr, (_err, stdout, stderr) => {
resolve({ stdout, stderr });
});
});
},
@ -197,13 +208,14 @@ module.exports = {
return app;
},
async startAndStub2(props) {
const app2 = await this.startAndStub({
env: 'test-integration-session-2',
async startAndStubN(props, n) {
// Make app with stub as number n
const appN = await this.startAndStub({
env: `test-integration-session-${n}`,
...props,
});
return app2;
return appN;
},
async restoreFromMnemonic(app, mnemonic, displayName) {
@ -221,7 +233,9 @@ module.exports = {
displayName
);
await app.client.element(RegistrationPage.continueSessionButton).click();
// await app.client.element(RegistrationPage.continueSessionButton).click();
await app.client.keys('Enter');
await app.client.waitForExist(
RegistrationPage.conversationListContainer,
4000
@ -243,7 +257,7 @@ module.exports = {
const [app1, app2] = await Promise.all([
this.startAndStub(app1Props),
this.startAndStub2(app2Props),
this.startAndStubN(app2Props, 2),
]);
/** add each other as friends */
@ -307,11 +321,89 @@ module.exports = {
return [app1, app2];
},
async addFriendToNewClosedGroup(app, app2) {
await this.setValueWrapper(
app,
ConversationPage.closedGroupNameTextarea,
this.VALID_CLOSED_GROUP_NAME1
);
await app.client
.element(ConversationPage.closedGroupNameTextarea)
.getValue()
.should.eventually.equal(this.VALID_CLOSED_GROUP_NAME1);
await app.client
.element(ConversationPage.createClosedGroupMemberItem)
.isVisible().should.eventually.be.true;
// select the first friend as a member of the groups being created
await app.client
.element(ConversationPage.createClosedGroupMemberItem)
.click();
await app.client
.element(ConversationPage.createClosedGroupMemberItemSelected)
.isVisible().should.eventually.be.true;
// trigger the creation of the group
await app.client
.element(ConversationPage.validateCreationClosedGroupButton)
.click();
await app.client.waitForExist(
ConversationPage.sessionToastGroupCreatedSuccess,
1000
);
await app.client.isExisting(
ConversationPage.headerTitleGroupName(this.VALID_CLOSED_GROUP_NAME1)
).should.eventually.be.true;
await app.client.element(ConversationPage.headerTitleMembers(2)).isVisible()
.should.eventually.be.true;
// validate overlay is closed
await app.client
.isExisting(ConversationPage.leftPaneOverlay)
.should.eventually.be.equal(false);
// move back to the conversation section
await app.client
.element(ConversationPage.conversationButtonSection)
.click();
// validate open chat has been added
await app.client.isExisting(
ConversationPage.rowOpenGroupConversationName(
this.VALID_CLOSED_GROUP_NAME1
)
).should.eventually.be.true;
// next check app2 has been invited and has the group in its conversations
await app2.client.waitForExist(
ConversationPage.rowOpenGroupConversationName(
this.VALID_CLOSED_GROUP_NAME1
),
6000
);
// open the closed group conversation on app2
await app2.client
.element(ConversationPage.conversationButtonSection)
.click();
await this.timeout(500);
await app2.client
.element(
ConversationPage.rowOpenGroupConversationName(
this.VALID_CLOSED_GROUP_NAME1
)
)
.click();
},
async linkApp2ToApp(app1, app2) {
// app needs to be logged in as user1 and app2 needs to be logged out
// start the pairing dialog for the first app
await app1.client.element(ConversationPage.settingsButtonSection).click();
await app1.client.element(ConversationPage.deviceSettingsRow).click();
await app1.client.element(SettingsPage.settingsButtonSection).click();
await app1.client
.element(SettingsPage.settingsRowWithText('Devices'))
.click();
await app1.client.isVisible(ConversationPage.noPairedDeviceMessage);
// we should not find the linkDeviceButtonDisabled button (as DISABLED)
@ -375,7 +467,9 @@ module.exports = {
.should.eventually.be.true;
await app1.client.element(ConversationPage.settingsButtonSection).click();
await app1.client.element(ConversationPage.deviceSettingsRow).click();
await app1.client
.element(ConversationPage.settingsRowWithText('Devices'))
.click();
await app1.client.isExisting(ConversationPage.linkDeviceButtonDisabled)
.should.eventually.be.true;
// click the unlink button
@ -411,6 +505,31 @@ module.exports = {
}
},
async sendMessage(app, messageText, fileLocation = undefined) {
await this.setValueWrapper(
app,
ConversationPage.sendMessageTextarea,
messageText
);
await app.client
.element(ConversationPage.sendMessageTextarea)
.getValue()
.should.eventually.equal(messageText);
// attach a file
if (fileLocation) {
await this.setValueWrapper(
app,
ConversationPage.attachmentInput,
fileLocation
);
}
// send message
await app.client.element(ConversationPage.sendMessageTextarea).click();
await app.client.keys('Enter');
},
generateSendMessageText: () =>
`Test message from integration tests ${Date.now()}`,

@ -11,6 +11,8 @@ require('./open_group_test');
require('./add_friends_test');
require('./link_device_test');
require('./closed_group_test');
require('./message_functions_test');
require('./settings_test');
before(async () => {
// start the app once before all tests to get the platform-dependent

@ -2,8 +2,8 @@
/* eslint-disable more/no-then */
/* eslint-disable func-names */
/* eslint-disable import/no-extraneous-dependencies */
const common = require('./common');
const { afterEach, beforeEach, describe, it } = require('mocha');
const common = require('./common');
describe('Link Device', function() {
let app;
@ -27,7 +27,7 @@ describe('Link Device', function() {
[app, app2] = await Promise.all([
common.startAndStub(app1Props),
common.startAndStub2(app2Props),
common.startAndStubN(app2Props, 2),
]);
});

@ -0,0 +1,86 @@
/* eslint-disable prefer-destructuring */
/* eslint-disable more/no-then */
/* eslint-disable func-names */
/* eslint-disable import/no-extraneous-dependencies */
const path = require('path');
const { after, before, describe, it } = require('mocha');
const common = require('./common');
const ConversationPage = require('./page-objects/conversation.page');
describe('Message Functions', function() {
let app;
let app2;
this.timeout(60000);
this.slow(15000);
before(async () => {
await common.killallElectron();
await common.stopStubSnodeServer();
[app, app2] = await common.startAppsAsFriends();
});
after(async () => {
await common.stopApp(app);
await common.killallElectron();
await common.stopStubSnodeServer();
});
it('can send attachment', async () => {
await app.client.element(ConversationPage.globeButtonSection).click();
await app.client.element(ConversationPage.createClosedGroupButton).click();
// create group and add new friend
await common.addFriendToNewClosedGroup(app, app2);
// send attachment from app1 to closed group
const fileLocation = path.join(__dirname, 'test_attachment');
const messageText = 'test_attachment';
await common.sendMessage(app, messageText, fileLocation);
// validate attachment sent
await app.client.waitForExist(
ConversationPage.existingSendMessageText(messageText),
3000
);
// validate attachment recieved
await app2.client.waitForExist(
ConversationPage.existingReceivedMessageText(messageText),
5000
);
});
it('can delete message', async () => {
const messageText = 'delete_me';
await common.sendMessage(app, messageText);
await app.client.waitForExist(
ConversationPage.existingSendMessageText(messageText),
6000
);
await app2.client.waitForExist(
ConversationPage.existingReceivedMessageText(messageText),
7000
);
// delete message in context menu
await app.client
.element(ConversationPage.messageCtxMenu(messageText))
.click();
await app.client.element(ConversationPage.deleteMessageCtxButton).click();
// delete messaage from modal
await app.client.waitForExist(
ConversationPage.deleteMessageModalButton,
5000
);
await app.client.element(ConversationPage.deleteMessageModalButton).click();
// verify the message is actually deleted
await app.client.isExisting(
ConversationPage.existingSendMessageText(messageText)
).should.eventually.be.false;
});
});

@ -0,0 +1,49 @@
/* eslint-disable func-names */
/* eslint-disable import/no-extraneous-dependencies */
const { afterEach, beforeEach, describe, it } = require('mocha');
const common = require('./common');
describe('Message Syncing', function() {
let app;
let app2;
this.timeout(60000);
this.slow(15000);
beforeEach(async () => {
await common.killallElectron();
await common.stopStubSnodeServer();
const app1Props = {
mnemonic: common.TEST_MNEMONIC1,
displayName: common.TEST_DISPLAY_NAME1,
stubSnode: true,
};
const app2Props = {
mnemonic: common.TEST_MNEMONIC2,
displayName: common.TEST_DISPLAY_NAME2,
stubSnode: true,
};
[app, app2] = await Promise.all([
common.startAndStub(app1Props),
common.startAndStubN(app2Props, 2),
]);
});
afterEach(async () => {
await common.killallElectron();
await common.stopStubSnodeServer();
});
it('message syncing between linked devices', async () => {
await common.linkApp2ToApp(app, app2);
});
it('unlink two devices', async () => {
await common.linkApp2ToApp(app, app2);
await common.timeout(1000);
await common.triggerUnlinkApp2FromApp(app, app2);
});
});

@ -1,7 +1,8 @@
/* eslint-disable func-names */
/* eslint-disable import/no-extraneous-dependencies */
const common = require('./common');
const { afterEach, beforeEach, describe, it } = require('mocha');
const common = require('./common');
const ConversationPage = require('./page-objects/conversation.page');
describe('Open groups', function() {
@ -49,10 +50,9 @@ describe('Open groups', function() {
.eventually.be.false;
// validate open chat has been added
await app.client.waitForExist(
ConversationPage.rowOpenGroupConversationName(name),
4000
);
await app.client.isExisting(
ConversationPage.rowOpenGroupConversationName(name)
).should.eventually.be.true;
}
it('openGroup: works with valid open group url', async () => {

@ -11,6 +11,7 @@ module.exports = {
`${module.exports.divRoleButtonWithText(text)}[contains(@class, "danger")]`,
inputWithPlaceholder: placeholder =>
`//input[contains(@placeholder, "${placeholder}")]`,
inputWithId: id => `//input[contains(@id, '${id}')]`,
textAreaWithPlaceholder: placeholder =>
`//textarea[contains(@placeholder, "${placeholder}")]`,
byId: id => `//*[@id="${id}"]`,
@ -21,4 +22,6 @@ module.exports = {
module.exports.objWithClassAndText('span', classname, text),
toastWithText: text =>
module.exports.divWithClassAndText('session-toast-wrapper', text),
toastCloseButton:
'//div[contains(@class, "session-toast-wrapper")]//div[contains(@class, "toast-close")]/div',
};

@ -9,11 +9,11 @@ module.exports = {
'Send your first message'
),
existingSendMessageText: textMessage =>
`//*[contains(@class, "module-message__text--outgoing")and .//span[contains(@class, "text-selectable")][contains(string(), '${textMessage}')]]`,
`//*[contains(@class, "module-message__text--outgoing") and .//span[contains(@class, "text-selectable")][contains(string(), '${textMessage}')]]`,
existingFriendRequestText: textMessage =>
`//*[contains(@class, "module-message-friend-request__container")and .//span[contains(@class, "text-selectable")][contains(string(), '${textMessage}')]]`,
`//*[contains(@class, "module-message-friend-request__container") and .//span[contains(@class, "text-selectable")][contains(string(), '${textMessage}')]]`,
existingReceivedMessageText: textMessage =>
`//*[contains(@class, "module-message__text--incoming")and .//span[contains(@class, "text-selectable")][contains(string(), '${textMessage}')]]`,
`//*[contains(@class, "module-message__text--incoming") and .//span[contains(@class, "text-selectable")][contains(string(), '${textMessage}')]]`,
// conversations
conversationButtonSection:
@ -28,6 +28,17 @@ module.exports = {
`${number} members`
),
attachmentInput: '//*[contains(@class, "choose-file")]/input[@type="file"]',
attachmentButton: '//*[contains(@class, "choose-file")]/button',
messageCtxMenu: message =>
`//div[contains(@class, 'message-wrapper')]//span[contains(string(), '${message}')]/parent::div/parent::div/parent::div/parent::div//div[contains(@class, 'module-message__buttons__menu')]`,
deleteMessageCtxButton:
'//*[contains(@class, "react-contextmenu--visible")]/div[contains(string(), "Delete")]',
deleteMessageModalButton:
'//*[contains(@class, "session-modal")]//div[contains(string(), "Delete") and contains(@class, "session-button")]',
// channels
globeButtonSection:
'//*[contains(@class,"session-icon-button") and .//*[contains(@class, "globe")]]',
@ -87,12 +98,6 @@ module.exports = {
acceptedFriendRequestMessage:
'//*[contains(@class, "module-friend-request__title")][contains(string(), "Friend request accepted")]',
// settings
settingsButtonSection:
'//*[contains(@class,"session-icon-button") and .//*[contains(@class, "gear")]]',
deviceSettingsRow:
'//*[contains(@class, "left-pane-setting-category-list-item")][contains(string(), "Devices")]',
descriptionDeleteAccount: commonPage.spanWithClassAndText(
'session-confirm-main-message',
'Are you sure you want to delete your account?'

@ -0,0 +1,20 @@
module.exports = {
// settings view
settingsButtonSection:
'//*[contains(@class,"session-icon-button") and .//*[contains(@class, "gear")]]',
settingsRowWithText: text =>
`//*[contains(@class, "left-pane-setting-category-list-item")][contains(string(), '${text}')]`,
leftPaneSettingsButton: `//*[contains(@class,"session-icon-button") and .//*[contains(@class, "gear")]]`,
settingToggleWithText: text =>
`//div[contains(@class, 'session-settings-item') and contains(string(), '${text}')]//*[contains(@class, 'session-toggle')]`,
settingButtonWithText: text =>
`//div[contains(@class, 'session-settings-item')]//*[contains(@class, 'session-button') and contains(string(), '${text}')]`,
settingCategoryWithText: text =>
`//div[contains(@class, 'left-pane-setting-category-list-item') and contains(string(), '${text}')]`,
// Confirm is a boolean. Selects confirmation input
passwordSetModalInput: _confirm =>
`//input[@id = 'password-modal-input${_confirm ? '-confirm' : ''}']`,
};

@ -2,8 +2,9 @@
/* eslint-disable func-names */
/* eslint-disable import/no-extraneous-dependencies */
const common = require('./common');
const { afterEach, beforeEach, describe, it } = require('mocha');
const common = require('./common');
const RegistrationPage = require('./page-objects/registration.page');
const ConversationPage = require('./page-objects/conversation.page');

@ -0,0 +1,120 @@
/* eslint-disable prefer-destructuring */
/* eslint-disable more/no-then */
/* eslint-disable func-names */
/* eslint-disable import/no-extraneous-dependencies */
const { after, before, describe, it } = require('mocha');
const common = require('./common');
const SettingsPage = require('./page-objects/settings.page');
const CommonPage = require('./page-objects/common.page');
// Generate random password
const password = Math.random()
.toString(36)
.substr(2, 8);
const passwordInputID = 'password-modal-input';
describe('Settings', function() {
let app;
this.timeout(60000);
this.slow(15000);
before(async () => {
await common.killallElectron();
await common.stopStubSnodeServer();
const appProps = {
mnemonic: common.TEST_MNEMONIC1,
displayName: common.TEST_DISPLAY_NAME1,
stubSnode: true,
};
app = await common.startAndStub(appProps);
});
after(async () => {
await common.stopApp(app);
await common.killallElectron();
await common.stopStubSnodeServer();
});
it('can toggle menubar', async () => {
const menuBarVisible = await app.browserWindow.isMenuBarVisible();
await app.client.element(SettingsPage.settingsButtonSection).click();
await app.client
.element(SettingsPage.settingToggleWithText('Hide Menu Bar'))
.click();
// Confirm that toggling works
const menuBarToggled = await app.browserWindow.isMenuBarVisible();
menuBarToggled.should.equal(!menuBarVisible);
});
it('can set password', async () => {
await app.client
.element(SettingsPage.settingsRowWithText('Privacy'))
.click();
await app.client
.element(SettingsPage.settingButtonWithText('Set Password'))
.click();
await common.setValueWrapper(
app,
CommonPage.inputWithId(passwordInputID),
password
);
await common.setValueWrapper(
app,
CommonPage.inputWithId(`${passwordInputID}-confirm`),
password
);
await app.client.keys('Enter');
// Verify password set
await app.client.waitForExist(
CommonPage.toastWithText('Set Password'),
2000
);
await common.closeToast(app);
});
it('can remove password', async () => {
// Enter password to unlock settings
await common.setValueWrapper(
app,
CommonPage.inputWithId('password-lock-input'),
password
);
await app.client.keys('Enter');
// Remove password
await app.client
.element(SettingsPage.settingButtonWithText('Remove Password'))
.click();
await common.setValueWrapper(
app,
CommonPage.inputWithId(passwordInputID),
password
);
await app.client.keys('Enter');
// Verify password removed with toast
await app.client.waitForExist(
CommonPage.toastWithText('Removed Password'),
2000
);
// Verify password actully removed
await app.client.isExisting(
CommonPage.divWithClass('session-settings__password-lock')
).should.eventually.be.false;
});
});

Binary file not shown.

@ -140,15 +140,15 @@ a {
}
input[type='file'] {
display: none;
// Must be displayed in order to programmatically
// insert file paths)
position: absolute;
width: 100%;
height: 100%;
opacity: 0;
top: 0;
left: 0;
cursor: pointer;
z-index: 1;
z-index: -100;
}
}

@ -139,18 +139,28 @@ export class SessionPasswordModal extends React.Component<Props, State> {
);
}
private async setPassword(onSuccess: any) {
if (!this.passwordInput.current || !this.passwordInputConfirm.current) {
private async setPassword(onSuccess?: any) {
// Only initial input required for PasswordAction.Remove
if (
!this.passwordInput.current ||
(!this.passwordInputConfirm.current &&
this.props.action !== PasswordAction.Remove)
) {
return;
}
// Trim leading / trailing whitespace for UX
const enteredPassword = String(this.passwordInput.current.value).trim();
const enteredPasswordConfirm = String(
this.passwordInputConfirm.current.value
).trim();
const enteredPasswordConfirm =
(this.passwordInputConfirm.current &&
String(this.passwordInputConfirm.current.value).trim()) ||
'';
if (enteredPassword.length === 0 || enteredPasswordConfirm.length === 0) {
if (
enteredPassword.length === 0 ||
(enteredPasswordConfirm.length === 0 &&
this.props.action !== PasswordAction.Remove)
) {
return;
}
@ -178,7 +188,7 @@ export class SessionPasswordModal extends React.Component<Props, State> {
// Check if password match, when setting, changing or removing
const valid =
this.props.action !== PasswordAction.Set
? !!await this.validatePasswordHash(oldPassword)
? Boolean(await this.validatePasswordHash(oldPassword))
: enteredPassword === enteredPasswordConfirm;
if (!valid) {

Loading…
Cancel
Save