mirror of
https://github.com/oxen-io/session-desktop.git
synced 2023-12-14 02:12:57 +01:00
More integration tests for medium groups
This commit is contained in:
parent
2a0130ff04
commit
fcadcd780e
|
@ -21,8 +21,8 @@ chai.use(chaiAsPromised);
|
|||
chai.config.includeStack = true;
|
||||
|
||||
// From https://github.com/chaijs/chai/issues/200
|
||||
chai.use(function (_chai, _) {
|
||||
_chai.Assertion.addMethod('withMessage', function (msg) {
|
||||
chai.use((_chai, _) => {
|
||||
_chai.Assertion.addMethod('withMessage', msg => {
|
||||
_.flag(this, 'message', msg);
|
||||
});
|
||||
});
|
||||
|
@ -250,7 +250,6 @@ module.exports = {
|
|||
},
|
||||
|
||||
async makeFriends(app1, client2) {
|
||||
|
||||
const [app2, pubkey2] = client2;
|
||||
|
||||
/** add each other as friends */
|
||||
|
@ -259,11 +258,7 @@ module.exports = {
|
|||
await app1.client.element(ConversationPage.contactsButtonSection).click();
|
||||
await app1.client.element(ConversationPage.addContactButton).click();
|
||||
|
||||
await this.setValueWrapper(
|
||||
app1,
|
||||
ConversationPage.sessionIDInput,
|
||||
pubkey2
|
||||
);
|
||||
await this.setValueWrapper(app1, ConversationPage.sessionIDInput, pubkey2);
|
||||
await app1.client.element(ConversationPage.nextButton).click();
|
||||
await app1.client.waitForExist(
|
||||
ConversationPage.sendFriendRequestTextarea,
|
||||
|
@ -310,10 +305,6 @@ module.exports = {
|
|||
ConversationPage.acceptedFriendRequestMessage,
|
||||
5000
|
||||
);
|
||||
|
||||
// click away to close the current pane and make further FR possible
|
||||
await app1.client.element(ConversationPage.globeButtonSection).click();
|
||||
|
||||
},
|
||||
|
||||
async startAppsAsFriends() {
|
||||
|
@ -340,7 +331,6 @@ module.exports = {
|
|||
},
|
||||
|
||||
async addFriendToNewClosedGroup(members, useSenderKeys) {
|
||||
|
||||
const [app, ...others] = members;
|
||||
|
||||
await this.setValueWrapper(
|
||||
|
@ -348,28 +338,35 @@ module.exports = {
|
|||
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;
|
||||
// This assumes that app does not have any other friends
|
||||
|
||||
for (let i = 0; i < others.length; i += 1) {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
await app.client
|
||||
.element(ConversationPage.createClosedGroupMemberItem(i))
|
||||
.isVisible().should.eventually.be.true;
|
||||
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
await app.client
|
||||
.element(ConversationPage.createClosedGroupMemberItem(i))
|
||||
.click();
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
if (useSenderKeys) {
|
||||
// Select Sender Keys
|
||||
// Select Sender Keys
|
||||
await app.client
|
||||
.element(ConversationPage.createClosedGroupSealedSenderToggle)
|
||||
.click();
|
||||
.element(ConversationPage.createClosedGroupSealedSenderToggle)
|
||||
.click();
|
||||
}
|
||||
|
||||
// trigger the creation of the group
|
||||
|
@ -384,8 +381,9 @@ module.exports = {
|
|||
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;
|
||||
await app.client
|
||||
.element(ConversationPage.headerTitleMembers(members.length))
|
||||
.isVisible().should.eventually.be.true;
|
||||
|
||||
// validate overlay is closed
|
||||
await app.client
|
||||
|
@ -575,6 +573,10 @@ module.exports = {
|
|||
app1.webContents.executeJavaScript(
|
||||
'window.LokiMessageAPI = window.StubMessageAPI;'
|
||||
);
|
||||
|
||||
app1.webContents.executeJavaScript(
|
||||
'window.LokiSnodeAPI = window.StubLokiSnodeAPI;'
|
||||
);
|
||||
},
|
||||
|
||||
logsContainsString: async (app1, str) => {
|
||||
|
@ -589,35 +591,45 @@ module.exports = {
|
|||
const { query } = url.parse(request.url, true);
|
||||
const { pubkey, data, timestamp } = query;
|
||||
|
||||
if (pubkey) {
|
||||
if (request.method === 'POST') {
|
||||
if (ENABLE_LOG) {
|
||||
console.warn('POST', [data, timestamp]);
|
||||
}
|
||||
|
||||
let ori = this.messages[pubkey];
|
||||
if (!this.messages[pubkey]) {
|
||||
ori = [];
|
||||
}
|
||||
|
||||
this.messages[pubkey] = [...ori, { data, timestamp }];
|
||||
|
||||
response.writeHead(200, { 'Content-Type': 'text/html' });
|
||||
response.end();
|
||||
} else {
|
||||
const retrievedMessages = { messages: this.messages[pubkey] };
|
||||
if (ENABLE_LOG) {
|
||||
console.warn('GET', pubkey, retrievedMessages);
|
||||
}
|
||||
if (this.messages[pubkey]) {
|
||||
response.writeHead(200, { 'Content-Type': 'application/json' });
|
||||
response.write(JSON.stringify(retrievedMessages));
|
||||
this.messages[pubkey] = [];
|
||||
}
|
||||
response.end();
|
||||
}
|
||||
if (!pubkey) {
|
||||
console.warn('NO PUBKEY');
|
||||
response.writeHead(400, { 'Content-Type': 'text/html' });
|
||||
response.end();
|
||||
}
|
||||
|
||||
if (request.method === 'POST') {
|
||||
if (ENABLE_LOG) {
|
||||
console.warn(
|
||||
'POST',
|
||||
pubkey.substr(2, 3),
|
||||
data.substr(4, 10),
|
||||
timestamp
|
||||
);
|
||||
}
|
||||
|
||||
let ori = this.messages[pubkey];
|
||||
|
||||
if (!this.messages[pubkey]) {
|
||||
ori = [];
|
||||
}
|
||||
|
||||
this.messages[pubkey] = [...ori, { data, timestamp }];
|
||||
|
||||
response.writeHead(200, { 'Content-Type': 'text/html' });
|
||||
response.end();
|
||||
} else {
|
||||
const retrievedMessages = { messages: this.messages[pubkey] || [] };
|
||||
|
||||
if (ENABLE_LOG) {
|
||||
const messages = retrievedMessages.messages.map(m =>
|
||||
m.data.substr(4, 10)
|
||||
);
|
||||
console.warn('GET', pubkey.substr(2, 3), messages);
|
||||
}
|
||||
response.writeHead(200, { 'Content-Type': 'application/json' });
|
||||
response.write(JSON.stringify(retrievedMessages));
|
||||
response.end();
|
||||
}
|
||||
response.end();
|
||||
});
|
||||
this.stubSnode.listen(STUB_SNODE_SERVER_PORT);
|
||||
} else {
|
||||
|
|
|
@ -63,7 +63,8 @@ module.exports = {
|
|||
closedGroupNameTextarea: commonPage.textAreaWithPlaceholder(
|
||||
'Enter a group name'
|
||||
),
|
||||
createClosedGroupMemberItem: commonPage.divWithClass('session-member-item'),
|
||||
createClosedGroupMemberItem: idx =>
|
||||
commonPage.divWithClass(`session-member-item-${idx}`),
|
||||
createClosedGroupSealedSenderToggle: commonPage.divWithClass(
|
||||
'session-toggle'
|
||||
),
|
||||
|
|
|
@ -6,41 +6,145 @@ const common = require('./common');
|
|||
const ConversationPage = require('./page-objects/conversation.page');
|
||||
|
||||
async function generateAndSendMessage(app) {
|
||||
|
||||
// send a message from app and validate it is received on app2
|
||||
const textMessage = common.generateSendMessageText();
|
||||
await app.client
|
||||
// send a message from app and validate it is received on app2
|
||||
const textMessage = common.generateSendMessageText();
|
||||
await app.client
|
||||
.element(ConversationPage.sendMessageTextarea)
|
||||
.setValue(textMessage);
|
||||
|
||||
await app.client
|
||||
await app.client
|
||||
.element(ConversationPage.sendMessageTextarea)
|
||||
.getValue()
|
||||
.should.eventually.equal(textMessage);
|
||||
// send the message
|
||||
await app.client.keys('Enter');
|
||||
// send the message
|
||||
await app.client.keys('Enter');
|
||||
|
||||
// validate that the message has been added to the message list view
|
||||
await app.client.waitForExist(
|
||||
ConversationPage.existingSendMessageText(textMessage),
|
||||
2000
|
||||
);
|
||||
// validate that the message has been added to the message list view
|
||||
await app.client.waitForExist(
|
||||
ConversationPage.existingSendMessageText(textMessage),
|
||||
2000
|
||||
);
|
||||
|
||||
return textMessage;
|
||||
return textMessage;
|
||||
}
|
||||
|
||||
async function makeFriendsPlusMessage(app, [app2, pubkey]) {
|
||||
await common.makeFriends(app, [app2, pubkey]);
|
||||
|
||||
// Send something back so that `app` can see our name
|
||||
const text = await generateAndSendMessage(app2);
|
||||
await app.client.waitForExist(
|
||||
ConversationPage.existingReceivedMessageText(text),
|
||||
8000
|
||||
);
|
||||
|
||||
// Click away so we can call this function again
|
||||
await app.client.element(ConversationPage.globeButtonSection).click();
|
||||
}
|
||||
|
||||
async function testTwoMembers() {
|
||||
const [app, app2] = await common.startAppsAsFriends();
|
||||
|
||||
await app.client.element(ConversationPage.globeButtonSection).click();
|
||||
await app.client.element(ConversationPage.createClosedGroupButton).click();
|
||||
|
||||
const useSenderKeys = true;
|
||||
|
||||
// create group and add new friend
|
||||
await common.addFriendToNewClosedGroup([app, app2], useSenderKeys);
|
||||
|
||||
const text1 = await generateAndSendMessage(app);
|
||||
|
||||
// validate that the message has been added to the message list view
|
||||
await app2.client.waitForExist(
|
||||
ConversationPage.existingReceivedMessageText(text1),
|
||||
5000
|
||||
);
|
||||
|
||||
// Send a message back:
|
||||
const text2 = await generateAndSendMessage(app2);
|
||||
|
||||
// TODO: fix this. We can send messages back manually, not sure
|
||||
// why this test fails
|
||||
await app.client.waitForExist(
|
||||
ConversationPage.existingReceivedMessageText(text2),
|
||||
10000
|
||||
);
|
||||
}
|
||||
|
||||
async function testThreeMembers() {
|
||||
// 1. Make three clients A, B, C
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
const app3Props = {
|
||||
mnemonic: common.TEST_MNEMONIC3,
|
||||
displayName: common.TEST_DISPLAY_NAME3,
|
||||
stubSnode: true,
|
||||
};
|
||||
|
||||
const [app1, app2, app3] = await Promise.all([
|
||||
common.startAndStub(app1Props),
|
||||
common.startAndStubN(app2Props, 2),
|
||||
common.startAndStubN(app3Props, 3),
|
||||
]);
|
||||
|
||||
// 2. Make A friends with B and C (B and C are not friends)
|
||||
|
||||
await makeFriendsPlusMessage(app1, [app2, common.TEST_PUBKEY2]);
|
||||
await makeFriendsPlusMessage(app1, [app3, common.TEST_PUBKEY3]);
|
||||
|
||||
const useSenderKeys = true;
|
||||
|
||||
await app1.client.element(ConversationPage.globeButtonSection).click();
|
||||
await app1.client.element(ConversationPage.createClosedGroupButton).click();
|
||||
|
||||
// 3. Add all three to the group
|
||||
|
||||
await common.addFriendToNewClosedGroup([app1, app2, app3], useSenderKeys);
|
||||
|
||||
// 4. Test that all members can see the message from app1
|
||||
const text1 = await generateAndSendMessage(app1);
|
||||
|
||||
await app2.client.waitForExist(
|
||||
ConversationPage.existingReceivedMessageText(text1),
|
||||
5000
|
||||
);
|
||||
|
||||
await app3.client.waitForExist(
|
||||
ConversationPage.existingReceivedMessageText(text1),
|
||||
5000
|
||||
);
|
||||
|
||||
// TODO: test that B and C can send messages to the group
|
||||
|
||||
// const text2 = await generateAndSendMessage(app3);
|
||||
|
||||
// await app2.client.waitForExist(
|
||||
// ConversationPage.existingReceivedMessageText(text2),
|
||||
// 5000
|
||||
// );
|
||||
}
|
||||
|
||||
describe('senderkeys', function() {
|
||||
let app;
|
||||
let app2;
|
||||
|
||||
this.timeout(60000);
|
||||
this.slow(30000);
|
||||
this.timeout(600000);
|
||||
this.slow(40000);
|
||||
|
||||
beforeEach(async () => {
|
||||
await common.killallElectron();
|
||||
await common.stopStubSnodeServer();
|
||||
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
|
@ -49,89 +153,7 @@ describe('senderkeys', function() {
|
|||
await common.stopStubSnodeServer();
|
||||
});
|
||||
|
||||
it('Two member group', async function() {
|
||||
|
||||
[app, app2] = await common.startAppsAsFriends();
|
||||
|
||||
await app.client.element(ConversationPage.globeButtonSection).click();
|
||||
await app.client.element(ConversationPage.createClosedGroupButton).click();
|
||||
|
||||
const useSenderKeys = true;
|
||||
|
||||
// create group and add new friend
|
||||
await common.addFriendToNewClosedGroup([app, app2], useSenderKeys);
|
||||
|
||||
const text1 = await generateAndSendMessage(app);
|
||||
|
||||
// validate that the message has been added to the message list view
|
||||
await app2.client.waitForExist(
|
||||
ConversationPage.existingReceivedMessageText(text1),
|
||||
5000
|
||||
);
|
||||
|
||||
// Send a message back:
|
||||
const text2 = await generateAndSendMessage(app2);
|
||||
|
||||
// TODO: fix this. We can send messages back manually, not sure
|
||||
// why this test fails
|
||||
// await app.client.waitForExist(
|
||||
// ConversationPage.existingReceivedMessageText(text2),
|
||||
// 10000
|
||||
// );
|
||||
|
||||
});
|
||||
|
||||
it('Three member group: test session requests', async function() {
|
||||
|
||||
// 1. Make three clients A, B, C
|
||||
|
||||
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,
|
||||
};
|
||||
|
||||
const app3Props = {
|
||||
mnemonic: common.TEST_MNEMONIC3,
|
||||
displayName: common.TEST_DISPLAY_NAME3,
|
||||
stubSnode: true,
|
||||
};
|
||||
|
||||
const [app1, app2, app3] = await Promise.all([
|
||||
common.startAndStub(app1Props),
|
||||
common.startAndStubN(app2Props, 2),
|
||||
common.startAndStubN(app3Props, 3)
|
||||
]);
|
||||
|
||||
// 2. Make A friends with B and C (B and C are not friends)
|
||||
|
||||
await common.makeFriends(app1, [app2, common.TEST_PUBKEY2]);
|
||||
|
||||
await common.makeFriends(app1, [app3, common.TEST_PUBKEY3]);
|
||||
|
||||
// const text1 = await generateAndSendMessage(app1);
|
||||
|
||||
// // validate that the message has been added to the message list view
|
||||
// await app2.client.waitForExist(
|
||||
// ConversationPage.existingReceivedMessageText(text1),
|
||||
// 5000
|
||||
// );
|
||||
|
||||
// // validate that the message has been added to the message list view
|
||||
// await app3.client.waitForExist(
|
||||
// ConversationPage.existingReceivedMessageText(text1),
|
||||
// 5000
|
||||
// );
|
||||
|
||||
// TODO: test that B and C can send messages to the group
|
||||
|
||||
|
||||
});
|
||||
it('Two member group', testTwoMembers);
|
||||
|
||||
it('Three member group: test session requests', testThreeMembers);
|
||||
});
|
||||
|
|
10
integration_test/stubs/stub_loki_snode_api.js
Normal file
10
integration_test/stubs/stub_loki_snode_api.js
Normal file
|
@ -0,0 +1,10 @@
|
|||
/* global log */
|
||||
|
||||
class StubLokiSnodeAPI {
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
async refreshSwarmNodesForPubKey(pubKey) {
|
||||
log.info('refreshSwarmNodesForPubkey: ', pubKey);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = StubLokiSnodeAPI;
|
|
@ -1,4 +1,4 @@
|
|||
/* global clearTimeout, dcodeIO, Buffer, TextDecoder, process */
|
||||
/* global clearTimeout, dcodeIO, Buffer, TextDecoder, process, log */
|
||||
const nodeFetch = require('node-fetch');
|
||||
|
||||
class StubMessageAPI {
|
||||
|
@ -26,6 +26,35 @@ class StubMessageAPI {
|
|||
);
|
||||
}
|
||||
|
||||
async pollForGroupId(groupId, onMessages) {
|
||||
const get = {
|
||||
method: 'GET',
|
||||
};
|
||||
const res = await nodeFetch(
|
||||
`${this.baseUrl}/messages?pubkey=${groupId}`,
|
||||
get
|
||||
);
|
||||
|
||||
try {
|
||||
const json = await res.json();
|
||||
|
||||
const modifiedMessages = json.messages.map(m => {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
m.conversationId = groupId;
|
||||
return m;
|
||||
});
|
||||
|
||||
onMessages(modifiedMessages || []);
|
||||
} catch (e) {
|
||||
log.error('invalid json for GROUP', e);
|
||||
onMessages([]);
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
this.pollForGroupId(groupId, onMessages);
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
async startLongPolling(numConnections, stopPolling, callback) {
|
||||
const ourPubkey = this.ourKey;
|
||||
|
||||
|
@ -36,10 +65,15 @@ class StubMessageAPI {
|
|||
`${this.baseUrl}/messages?pubkey=${ourPubkey}`,
|
||||
get
|
||||
);
|
||||
const json = await res.json();
|
||||
// console.warn('STUBBED polling messages ', json.messages);
|
||||
|
||||
callback(json.messages || []);
|
||||
try {
|
||||
const json = await res.json();
|
||||
callback(json.messages || []);
|
||||
} catch (e) {
|
||||
log.error('invalid json: ', e);
|
||||
callback([]);
|
||||
}
|
||||
// console.warn('STUBBED polling messages ', json.messages);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
"test-electron": "yarn grunt test",
|
||||
"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-medium-groups": "ELECTRON_DISABLE_SANDBOX=1 mocha --exit --timeout 10000 integration_test/integration_test.js --grep 'senderkeys'",
|
||||
"test-node": "mocha --recursive --exit test/app test/modules ts/test libloki/test/node",
|
||||
"eslint": "eslint --cache .",
|
||||
"eslint-fix": "eslint --fix .",
|
||||
|
|
|
@ -342,6 +342,7 @@ window.LokiMessageAPI = require('./js/modules/loki_message_api');
|
|||
if (process.env.USE_STUBBED_NETWORK) {
|
||||
window.StubMessageAPI = require('./integration_test/stubs/stub_message_api');
|
||||
window.StubAppDotNetApi = require('./integration_test/stubs/stub_app_dot_net_api');
|
||||
window.StubLokiSnodeAPI = require('./integration_test/stubs/stub_loki_snode_api');
|
||||
}
|
||||
window.LokiPublicChatAPI = require('./js/modules/loki_public_chat_api');
|
||||
|
||||
|
@ -456,7 +457,7 @@ if (
|
|||
};
|
||||
/* eslint-enable global-require, import/no-extraneous-dependencies */
|
||||
window.lokiFeatureFlags = {};
|
||||
window.lokiSnodeAPI = {}; // no need stub out each function here
|
||||
window.lokiSnodeAPI = new window.StubLokiSnodeAPI(); // no need stub out each function here
|
||||
}
|
||||
if (config.environment.includes('test-integration')) {
|
||||
window.lokiFeatureFlags = {
|
||||
|
|
|
@ -108,9 +108,10 @@ export class InviteFriendsDialog extends React.Component<Props, State> {
|
|||
private renderMemberList() {
|
||||
const members = this.state.friendList;
|
||||
|
||||
return members.map((member: ContactType) => (
|
||||
return members.map((member: ContactType, index: number) => (
|
||||
<SessionMemberListItem
|
||||
member={member}
|
||||
index={index}
|
||||
isSelected={false}
|
||||
onSelect={(selectedMember: ContactType) => {
|
||||
this.onMemberClicked(selectedMember);
|
||||
|
|
|
@ -147,9 +147,10 @@ export class UpdateGroupMembersDialog extends React.Component<Props, State> {
|
|||
private renderMemberList() {
|
||||
const members = this.state.friendList;
|
||||
|
||||
return members.map((member: ContactType) => (
|
||||
return members.map((member: ContactType, index: number) => (
|
||||
<SessionMemberListItem
|
||||
member={member}
|
||||
index={index}
|
||||
isSelected={!member.checkmarked}
|
||||
onSelect={this.onMemberClicked}
|
||||
onUnselect={this.onMemberClicked}
|
||||
|
|
|
@ -123,6 +123,7 @@ export class LeftPaneSectionHeader extends React.Component<Props, State> {
|
|||
count={notificationCount}
|
||||
size={NotificationCountSize.ON_HEADER}
|
||||
onClick={this.props.buttonClicked}
|
||||
key="notificationCount"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -282,9 +282,10 @@ export class SessionClosableOverlay extends React.Component<Props, State> {
|
|||
}
|
||||
|
||||
private renderMemberList(members: any) {
|
||||
return members.map((member: ContactType) => (
|
||||
return members.map((member: ContactType, index: number) => (
|
||||
<SessionMemberListItem
|
||||
member={member}
|
||||
index={index}
|
||||
isSelected={false}
|
||||
key={member.id}
|
||||
onSelect={(selectedMember: ContactType) => {
|
||||
|
|
|
@ -18,6 +18,7 @@ export interface ContactType {
|
|||
|
||||
interface Props {
|
||||
member: ContactType;
|
||||
index: number; // index in the list
|
||||
isSelected: boolean;
|
||||
onSelect?: any;
|
||||
onUnselect?: any;
|
||||
|
@ -54,7 +55,11 @@ export class SessionMemberListItem extends React.Component<Props, State> {
|
|||
|
||||
return (
|
||||
<div
|
||||
className={classNames('session-member-item', isSelected && 'selected')}
|
||||
className={classNames(
|
||||
`session-member-item-${this.props.index}`,
|
||||
'session-member-item',
|
||||
isSelected && 'selected'
|
||||
)}
|
||||
onClick={this.handleSelectionAction}
|
||||
role="button"
|
||||
>
|
||||
|
|
Loading…
Reference in a new issue