(resolve => setTimeout(() => resolve(), 2000))
}
+ this.isOpened = false
+ console.log('App closed', this.buildSetup.dataDir)
}
get saveStateButton() {
@@ -59,12 +68,6 @@ export class StartingLoadingPanel {
get element() {
return this.driver.wait(until.elementLocated(By.xpath('//div[@data-testid="startingPanelComponent"]')))
}
- // get element() {
- // return this.driver.wait(until.elementLocated(By.xpath(`//span[text()="${this.text}"]`)))
- // }
- // get title() {
- // return this.driver.findElement(By.xpath(`//span[text()="${this.text}"]`))
- // }
}
export class WarningModal {
@@ -227,6 +230,19 @@ export class Channel {
return await messagesGroup.findElement(By.xpath('//p[@data-testid="/messagesGroupContent-/"]'))
}
+ async waitForUserMessage(username: string, messageContent: string) {
+ console.log(`Waiting for user "${username}" message "${messageContent}"`)
+ return this.driver.wait(async () => {
+ const messages = await this.getUserMessages(username)
+ const hasMessage = messages.find(async msg => {
+ const messageText = await msg.getText()
+ console.log(`got message "${messageText}"`)
+ return messageText.includes(messageContent)
+ })
+ return hasMessage
+ })
+ }
+
get getAllMessages() {
return this.driver.wait(until.elementsLocated(By.xpath('//*[contains(@data-testid, "userMessages-")]')))
}
@@ -256,6 +272,26 @@ export class Channel {
)
}
+ async waitForLabel(username: string, label: string) {
+ console.log(`Waiting for user's "${username}" label "${label}" label`)
+ await this.driver.wait(async () => {
+ const labels = await this.driver.findElements(By.xpath(`//*[contains(@data-testid, "userLabel-${username}")]`))
+ const properLabels = labels.filter(async labelElement => {
+ const labelText = await labelElement.getText()
+ return labelText === label
+ })
+ return properLabels.length > 0
+ })
+ }
+
+ async waitForLabelsNotPresent(username: string) {
+ console.log(`Waiting for user's "${username}" label to not be present`)
+ await this.driver.wait(async () => {
+ const labels = await this.driver.findElements(By.xpath(`//*[contains(@data-testid, "userLabel-${username}")]`))
+ return labels.length === 0
+ })
+ }
+
async getMessage(text: string) {
return await this.driver.wait(until.elementLocated(By.xpath(`//span[contains(text(),"${text}")]`)))
}
@@ -375,18 +411,27 @@ export class DebugModeModal {
}
get element() {
- return this.driver.wait(until.elementLocated(By.xpath("//h3[text()='App is running in debug mode']")))
+ return this.driver.wait(until.elementLocated(By.xpath("//h3[text()='App is running in debug mode']")), 5000)
}
get button() {
- return this.driver.wait(until.elementLocated(By.xpath("//button[text()='Understand']")))
+ return this.driver.wait(until.elementLocated(By.xpath("//button[text()='Understand']")), 5000)
}
async close() {
- console.log('Closing debug modal')
- await this.element.isDisplayed()
- const button = await this.button
- console.log('Debug modal title is displayed')
+ if (!process.env.TEST_MODE) return
+ let button
+ try {
+ console.log('Closing debug modal')
+ await this.element.isDisplayed()
+ console.log('Debug modal title is displayed')
+ button = await this.button
+ console.log('Debug modal button is displayed')
+ } catch (e) {
+ console.log('Debug modal might have been covered by "join community" modal', e.message)
+ return
+ }
+
await button.isDisplayed()
console.log('Button is displayed')
await button.click()
diff --git a/packages/e2e-tests/src/tests/invitationLink.test.ts b/packages/e2e-tests/src/tests/invitationLink.test.ts
index 0b4e917019..e43f845071 100644
--- a/packages/e2e-tests/src/tests/invitationLink.test.ts
+++ b/packages/e2e-tests/src/tests/invitationLink.test.ts
@@ -44,14 +44,6 @@ describe('New user joins using invitation link while having app opened', () => {
await ownerApp.open()
})
- if (process.env.TEST_MODE) {
- it('Owner closes debug modal', async () => {
- console.log('Invitation Link', 2)
- const debugModal = new DebugModeModal(ownerApp.driver)
- await debugModal.close()
- })
- }
-
it('JoinCommunityModal - owner switches to create community', async () => {
console.log('Invitation Link', 4)
const joinModal = new JoinCommunityModal(ownerApp.driver)
@@ -121,13 +113,6 @@ describe('New user joins using invitation link while having app opened', () => {
console.log('Guest opens app')
await guestApp.open()
})
- if (process.env.TEST_MODE) {
- it('Close debug modal', async () => {
- console.log('Invitation Link', 12)
- const debugModal = new DebugModeModal(guestApp.driver)
- await debugModal.close()
- })
- }
it.skip('Guest clicks invitation link with invalid invitation code', async () => {
// Fix when modals ordering is fixed (joining modal hiddes warning modal)
diff --git a/packages/e2e-tests/src/tests/multipleClients.test.ts b/packages/e2e-tests/src/tests/multipleClients.test.ts
new file mode 100644
index 0000000000..9adf41a272
--- /dev/null
+++ b/packages/e2e-tests/src/tests/multipleClients.test.ts
@@ -0,0 +1,438 @@
+import {
+ App,
+ Channel,
+ ChannelContextMenu,
+ CreateCommunityModal,
+ DebugModeModal,
+ JoinCommunityModal,
+ RegisterUsernameModal,
+ Sidebar,
+} from '../selectors'
+import logger from '../logger'
+const log = logger('ManyClients')
+
+interface UserTestData {
+ username: string
+ app: App
+ messages: string[]
+}
+
+jest.setTimeout(900000)
+describe('Multiple Clients', () => {
+ let generalChannelOwner: Channel
+ let generalChannelUser1: Channel
+ let generalChannelUser3: Channel
+
+ let secondChannelUser1: Channel
+
+ let channelContextMenuOwner: ChannelContextMenu
+
+ let invitationCode: string
+
+ let sidebarOwner: Sidebar
+ let sidebarUser1: Sidebar
+
+ let users: Record
+
+ const communityName = 'testcommunity'
+ const displayedCommunityName = 'Testcommunity'
+ const newChannelName = 'mid-night-club'
+
+ const sleep = async (time = 1000) => {
+ await new Promise(resolve =>
+ setTimeout(() => {
+ resolve()
+ }, time)
+ )
+ }
+
+ beforeAll(async () => {
+ const commonApp = new App()
+ users = {
+ owner: {
+ username: 'owner',
+ messages: ['Hi', 'Hello', 'After guest left the app'],
+ app: new App(),
+ },
+ user1: {
+ username: 'user-joining-1',
+ messages: ['Nice to meet you all'],
+ app: commonApp,
+ },
+ user2: {
+ username: 'user-joining-1-1',
+ messages: ['Nice to meet you again'],
+ app: commonApp,
+ },
+ user3: {
+ username: 'user-joining-2',
+ messages: ['Hi everyone'],
+ app: new App(),
+ },
+ }
+ })
+
+ afterAll(async () => {
+ for (const user of Object.values(users)) {
+ await user.app.close()
+ }
+ })
+
+ beforeEach(async () => {
+ await sleep(1000)
+ })
+
+ describe('Stages:', () => {
+ it('Owner opens the app', async () => {
+ await users.owner.app.open()
+ })
+
+ it('Owner sees "join community" modal and switches to "create community" modal', async () => {
+ const joinModal = new JoinCommunityModal(users.owner.app.driver)
+ const isJoinModal = await joinModal.element.isDisplayed()
+ expect(isJoinModal).toBeTruthy()
+ await joinModal.switchToCreateCommunity()
+ })
+ it('Owner submits valid community name', async () => {
+ const createModal = new CreateCommunityModal(users.owner.app.driver)
+ const isCreateModal = await createModal.element.isDisplayed()
+ expect(isCreateModal).toBeTruthy()
+ await createModal.typeCommunityName(communityName)
+ await createModal.submit()
+ })
+ it('Owner sees "register username" modal and submits valid username', async () => {
+ const registerModal = new RegisterUsernameModal(users.owner.app.driver)
+ const isRegisterModal = await registerModal.element.isDisplayed()
+ expect(isRegisterModal).toBeTruthy()
+ await registerModal.typeUsername(users.owner.username)
+ await registerModal.submit()
+ })
+ it('Owner registers successfully and sees general channel', async () => {
+ generalChannelOwner = new Channel(users.owner.app.driver, 'general')
+ const isGeneralChannel = await generalChannelOwner.element.isDisplayed()
+ const generalChannelText = await generalChannelOwner.element.getText()
+ expect(isGeneralChannel).toBeTruthy()
+ expect(generalChannelText).toEqual('# general')
+ })
+ it('Owner sends a message', async () => {
+ const isMessageInput = await generalChannelOwner.messageInput.isDisplayed()
+ expect(isMessageInput).toBeTruthy()
+ await generalChannelOwner.sendMessage(users.owner.messages[0])
+ })
+ it("Owner's message is visible on channel", async () => {
+ const messages = await generalChannelOwner.getUserMessages(users.owner.username)
+ const text = await messages[1].getText()
+ expect(text).toEqual(users.owner.messages[0])
+ })
+ it('Owner opens the settings tab and gets an invitation code', async () => {
+ const settingsModal = await new Sidebar(users.owner.app.driver).openSettings()
+ const isSettingsModal = await settingsModal.element.isDisplayed()
+ expect(isSettingsModal).toBeTruthy()
+ await sleep(2000)
+ await settingsModal.switchTab('invite') // TODO: Fix - the invite tab should be default for the owner
+ await sleep(2000)
+ const invitationCodeElement = await settingsModal.invitationCode()
+ await sleep(2000)
+ invitationCode = await invitationCodeElement.getText()
+ await sleep(2000)
+ console.log({ invitationCode })
+ expect(invitationCode).not.toBeUndefined()
+ log('Received invitation code:', invitationCode)
+ await settingsModal.close()
+ })
+
+ it('First user opens the app', async () => {
+ console.log('Second client')
+ await users.user1.app.open()
+ })
+
+ it('First user submits invitation code received from owner', async () => {
+ console.log('new user - 3')
+ const joinCommunityModal = new JoinCommunityModal(users.user1.app.driver)
+ const isJoinCommunityModal = await joinCommunityModal.element.isDisplayed()
+ expect(isJoinCommunityModal).toBeTruthy()
+ console.log({ invitationCode })
+ await joinCommunityModal.typeCommunityCode(invitationCode)
+ await joinCommunityModal.submit()
+ })
+
+ it('First user submits valid username', async () => {
+ console.log('new user - 5')
+ const registerModal = new RegisterUsernameModal(users.user1.app.driver)
+ const isRegisterModal = await registerModal.element.isDisplayed()
+ expect(isRegisterModal).toBeTruthy()
+ await registerModal.clearInput()
+ await registerModal.typeUsername(users.user1.username)
+ await registerModal.submit()
+ })
+
+ it('First user joins successfully sees general channel and sends a message', async () => {
+ console.log('new user - 7')
+ generalChannelUser1 = new Channel(users.user1.app.driver, 'general')
+ await generalChannelUser1.element.isDisplayed()
+ const isMessageInput2 = await generalChannelUser1.messageInput.isDisplayed()
+ expect(isMessageInput2).toBeTruthy()
+ console.log('FETCHING CHANNEL MESSAGES!')
+ await new Promise(resolve =>
+ setTimeout(() => {
+ resolve()
+ }, 15000)
+ )
+ await generalChannelUser1.sendMessage(users.user1.messages[0])
+ })
+ it("First user's sent message is visible in a channel", async () => {
+ const messages2 = await generalChannelUser1.getUserMessages(users.user1.username)
+ const messages1 = await generalChannelUser1.getUserMessages(users.owner.username)
+ console.log({ messages1, messages2 })
+ const text2 = await messages2[0].getText()
+ expect(text2).toEqual(users.user1.messages[0])
+ })
+ it('First user opens the settings tab and copies updated invitation code', async () => {
+ const settingsModal = await new Sidebar(users.user1.app.driver).openSettings()
+ const isSettingsModal = await settingsModal.element.isDisplayed()
+ expect(isSettingsModal).toBeTruthy()
+ await sleep(2000)
+ await settingsModal.switchTab('invite')
+ await sleep(2000)
+ const invitationCodeElement = await settingsModal.invitationCode()
+ await sleep(2000)
+ invitationCode = await invitationCodeElement.getText()
+ await sleep(2000)
+ console.log(`${invitationCode} copied from non owner`)
+ expect(invitationCode).not.toBeUndefined()
+ await settingsModal.close()
+ })
+
+ it('Owner goes offline', async () => {
+ await users.owner.app.close()
+ })
+
+ it('Second user opens the app', async () => {
+ console.log('Third client')
+ await users.user3.app.open()
+ const debugModal = new DebugModeModal(users.user3.app.driver)
+ await debugModal.close()
+ })
+
+ it('Second user starts to join when owner is offline', async () => {
+ const joinCommunityModal = new JoinCommunityModal(users.user3.app.driver)
+ const isJoinCommunityModal = await joinCommunityModal.element.isDisplayed()
+ expect(isJoinCommunityModal).toBeTruthy()
+ console.log({ invitationCode })
+ await joinCommunityModal.typeCommunityCode(invitationCode)
+ await joinCommunityModal.submit()
+ })
+
+ it('Second user submits valid, not-duplicated username', async () => {
+ console.log('nereeew user - 5')
+ const registerModal = new RegisterUsernameModal(users.user3.app.driver)
+ const isRegisterModal = await registerModal.element.isDisplayed()
+ expect(isRegisterModal).toBeTruthy()
+ await registerModal.clearInput()
+ await registerModal.typeUsername(users.user3.username)
+ await registerModal.submit()
+ })
+
+ it('Second user sees general channel', async () => {
+ console.log('new user - 7')
+ generalChannelUser3 = new Channel(users.user3.app.driver, 'general')
+ await generalChannelUser3.element.isDisplayed()
+ const isMessageInput = await generalChannelUser3.messageInput.isDisplayed()
+ expect(isMessageInput).toBeTruthy()
+ })
+
+ it('Second user can send a message, they see their message tagged as "unregistered"', async () => {
+ console.log('Second guest FETCHING CHANNEL MESSAGES!')
+ await new Promise(resolve =>
+ setTimeout(() => {
+ resolve()
+ }, 15000)
+ )
+ await generalChannelUser3.sendMessage(users.user3.messages[0])
+ generalChannelUser3 = new Channel(users.user3.app.driver, 'general')
+ await generalChannelUser3.waitForLabel(users.user3.username, 'Unregistered')
+ })
+
+ it('First user sees that unregistered user\'s messages are marked as "unregistered"', async () => {
+ await generalChannelUser1.waitForLabel(users.user3.username, 'Unregistered')
+ })
+
+ it('Owner goes back online', async () => {
+ await users.owner.app.open()
+ const debugModal = new DebugModeModal(users.owner.app.driver)
+ await debugModal.close()
+ })
+
+ it('Second user receives certificate, they can see confirmation that they registered', async () => {
+ await generalChannelUser3.waitForUserMessage(
+ users.owner.username,
+ `@${users.user3.username} has joined ${displayedCommunityName}!`
+ )
+ })
+
+ it('"Unregistered" label is removed from second user\'s messages', async () => {
+ generalChannelOwner = new Channel(users.owner.app.driver, 'general')
+ await generalChannelOwner.waitForLabelsNotPresent(users.user3.username)
+ })
+
+ it('Channel creation - Owner creates second channel', async () => {
+ sidebarOwner = new Sidebar(users.owner.app.driver)
+ await sidebarOwner.addNewChannel(newChannelName)
+ await sidebarOwner.switchChannel(newChannelName)
+ const channels = await sidebarOwner.getChannelList()
+ expect(channels.length).toEqual(2)
+ })
+ it('Channel creation - Owner sends message in second channel', async () => {
+ const newChannel = new Channel(users.owner.app.driver, newChannelName)
+ const isMessageInput = await newChannel.messageInput.isDisplayed()
+ expect(isMessageInput).toBeTruthy()
+ await newChannel.sendMessage(users.owner.messages[1])
+ })
+ it('Channel creation - User reads message in second channel', async () => {
+ sidebarUser1 = new Sidebar(users.user1.app.driver)
+ await sidebarUser1.switchChannel(newChannelName)
+ secondChannelUser1 = new Channel(users.user1.app.driver, newChannelName)
+ await new Promise(resolve =>
+ setTimeout(() => {
+ resolve()
+ }, 2000)
+ )
+ await secondChannelUser1.waitForUserMessage(users.owner.username, users.owner.messages[1])
+ })
+ it('Channel deletion - Owner deletes second channel', async () => {
+ channelContextMenuOwner = new ChannelContextMenu(users.owner.app.driver)
+ await channelContextMenuOwner.openMenu()
+ await channelContextMenuOwner.openDeletionChannelModal()
+ await channelContextMenuOwner.deleteChannel()
+ const channels = await sidebarOwner.getChannelList()
+ expect(channels.length).toEqual(1)
+ })
+ it('Channel deletion - User sees info about channel deletion in general channel', async () => {
+ await sleep(5000)
+ await generalChannelUser1.waitForUserMessage(
+ users.owner.username,
+ `@${users.owner.username} deleted #${newChannelName}`
+ )
+ })
+ it('Channel deletion - User can create channel with the same name and is fresh channel', async () => {
+ await sidebarUser1.addNewChannel(newChannelName)
+ await sidebarUser1.switchChannel(newChannelName)
+ const messages = await secondChannelUser1.getUserMessages(users.user1.username)
+ expect(messages.length).toEqual(1)
+ await new Promise(resolve =>
+ setTimeout(() => {
+ resolve()
+ }, 2000)
+ )
+ const channels = await sidebarOwner.getChannelList()
+ expect(channels.length).toEqual(2)
+ })
+ // End of tests for Windows
+ if (process.platform !== 'win32') {
+ it('Leave community', async () => {
+ console.log('TEST 2')
+ const settingsModal = await new Sidebar(users.user1.app.driver).openSettings()
+ const isSettingsModal = await settingsModal.element.isDisplayed()
+ expect(isSettingsModal).toBeTruthy()
+ await settingsModal.openLeaveCommunityModal()
+ await settingsModal.leaveCommunityButton()
+ })
+ // Delete general channel while guest is absent
+ it('Channel deletion - Owner recreates general channel', async () => {
+ console.log('TEST 3')
+ await new Promise(resolve => setTimeout(() => resolve(), 10000))
+ const isGeneralChannel = await generalChannelOwner.messageInput.isDisplayed()
+ expect(isGeneralChannel).toBeTruthy()
+ await channelContextMenuOwner.openMenu()
+ await channelContextMenuOwner.openDeletionChannelModal()
+ await channelContextMenuOwner.deleteChannel()
+ const channels = await sidebarOwner.getChannelList()
+ expect(channels.length).toEqual(2)
+ })
+
+ it('Leave community - Guest re-join to community successfully', async () => {
+ console.log('TEST 4')
+ const debugModal = new DebugModeModal(users.user1.app.driver)
+ await debugModal.close()
+ const joinCommunityModal = new JoinCommunityModal(users.user1.app.driver)
+ const isJoinCommunityModal = await joinCommunityModal.element.isDisplayed()
+ expect(isJoinCommunityModal).toBeTruthy()
+ await joinCommunityModal.typeCommunityCode(invitationCode)
+ await joinCommunityModal.submit()
+ })
+ it('Leave community - Guest registers new username', async () => {
+ console.log('TEST 5')
+ const registerModal2 = new RegisterUsernameModal(users.user1.app.driver)
+ const isRegisterModal2 = await registerModal2.element.isDisplayed()
+ expect(isRegisterModal2).toBeTruthy()
+ await registerModal2.typeUsername(users.user2.username)
+ await registerModal2.submit()
+ })
+
+ // Check correct channels replication
+ it('Channel deletion - User sees information about recreation general channel and see correct amount of messages', async () => {
+ console.log('TEST 6')
+ generalChannelUser1 = new Channel(users.user1.app.driver, 'general')
+ await generalChannelUser1.element.isDisplayed()
+ await new Promise(resolve =>
+ setTimeout(() => {
+ resolve()
+ }, 10000)
+ )
+
+ await generalChannelUser1.waitForUserMessage(
+ users.owner.username,
+ `@${users.owner.username} deleted all messages in #general`
+ )
+ await generalChannelUser1.waitForUserMessage(
+ users.owner.username,
+ `@${users.user2.username} has joined Testcommunity! 🎉`
+ )
+ })
+
+ it('Leave community - Guest sends a message after rejoining community as a new user', async () => {
+ console.log('TEST 7')
+ generalChannelUser1 = new Channel(users.user1.app.driver, 'general')
+ await generalChannelUser1.element.isDisplayed()
+ const isMessageInput2 = await generalChannelUser1.messageInput.isDisplayed()
+ expect(isMessageInput2).toBeTruthy()
+ await new Promise(resolve =>
+ setTimeout(() => {
+ resolve()
+ }, 5000)
+ )
+ await generalChannelUser1.sendMessage(users.user2.messages[0])
+ })
+ it('Leave community - Sent message is visible in a channel', async () => {
+ console.log('TEST 8')
+ await generalChannelUser1.waitForUserMessage(users.user2.username, users.user2.messages[0])
+ })
+ it('Owner closes app', async () => {
+ await users.owner.app.close({ forceSaveState: true })
+ await new Promise(resolve => setTimeout(() => resolve(), 20000))
+ })
+
+ it('Guest closes app', async () => {
+ console.log('TEST 9')
+ await users.user1.app?.close()
+ })
+
+ it('Owner re-opens app', async () => {
+ await users.owner.app?.open()
+ await new Promise(resolve => setTimeout(() => resolve(), 10000))
+ })
+
+ it('Guest closes app - Owner sends another message after guest left the app', async () => {
+ console.log('TEST 10')
+ generalChannelOwner = new Channel(users.owner.app.driver, 'general')
+ const isMessageInput = await generalChannelOwner.messageInput.isDisplayed()
+ expect(isMessageInput).toBeTruthy()
+ await generalChannelOwner.sendMessage(users.owner.messages[2])
+ })
+ it('Guest closes app - Check if message is visible for owner', async () => {
+ console.log('TEST 11')
+ await generalChannelOwner.waitForUserMessage(users.owner.username, users.owner.messages[2])
+ })
+ }
+ })
+})
diff --git a/packages/e2e-tests/src/tests/oneClient.test.ts b/packages/e2e-tests/src/tests/oneClient.test.ts
index ce774dcc4e..090f268708 100644
--- a/packages/e2e-tests/src/tests/oneClient.test.ts
+++ b/packages/e2e-tests/src/tests/oneClient.test.ts
@@ -26,13 +26,6 @@ describe('One Client', () => {
await app.close()
})
describe('User opens app for the first time', () => {
- if (process.env.TEST_MODE) {
- it('Close debug modal', async () => {
- const debugModal = new DebugModeModal(app.driver)
- await debugModal.close()
- })
- }
-
it('Get opened app process data', () => {
const processData = app.buildSetup.getProcessData()
dataDirPath = processData.dataDirPath
@@ -110,13 +103,6 @@ describe('One Client', () => {
await app.open()
})
- if (process.env.TEST_MODE) {
- it('Close debug modal', async () => {
- const debugModal = new DebugModeModal(app.driver)
- await debugModal.close()
- })
- }
-
it('User sees "general channel" page', async () => {
const generalChannel = new Channel(app.driver, 'general')
const isGeneralChannel = await generalChannel.element.isDisplayed()
diff --git a/packages/e2e-tests/src/tests/twoClients.test.ts b/packages/e2e-tests/src/tests/twoClients.test.ts
deleted file mode 100644
index 463f585ef3..0000000000
--- a/packages/e2e-tests/src/tests/twoClients.test.ts
+++ /dev/null
@@ -1,380 +0,0 @@
-import {
- App,
- Channel,
- ChannelContextMenu,
- CreateCommunityModal,
- DebugModeModal,
- JoinCommunityModal,
- JoiningLoadingPanel,
- RegisterUsernameModal,
- Sidebar,
-} from '../selectors'
-import logger from '../logger'
-const log = logger('Two Clients:')
-
-jest.setTimeout(900000)
-describe('Two Clients', () => {
- let ownerApp: App
- let guestApp: App
-
- let registerModal2: RegisterUsernameModal
-
- let generalChannel: Channel
- let generalChannel2: Channel
-
- let secondChannel: Channel
- let secondChannel2: Channel
-
- let channelContextMenu: ChannelContextMenu
-
- let invitationCode: string
-
- let sidebar: Sidebar
- let sidebar2: Sidebar
-
- const communityName = 'testcommunity'
- const ownerUsername = 'bob'
- const ownerMessages = ['Hi', 'Hello', 'After guest leave app']
- const joiningUserUsername = 'alice-joining'
- const joiningUserUsername2 = 'alice2'
- const joiningUserMessages = ['Nice to meet you all', 'Nice to meet you again']
- const newChannelName = 'mid-night-club'
-
- const sleep = async (time = 1000) =>
- await new Promise(resolve =>
- setTimeout(() => {
- resolve()
- }, time)
- )
-
- beforeAll(async () => {
- ownerApp = new App()
- })
-
- afterAll(async () => {
- await ownerApp?.close()
- })
-
- beforeEach(async () => {
- await sleep(1000)
- })
-
- describe('Stages:', () => {
- it('Owner opens the app', async () => {
- await ownerApp.open()
- })
-
- if (process.env.TEST_MODE) {
- it('Close debug modal', async () => {
- const debugModal = new DebugModeModal(ownerApp.driver)
- await debugModal.close()
- })
- }
-
- it('JoinCommunityModal - owner switch to create community', async () => {
- const joinModal = new JoinCommunityModal(ownerApp.driver)
- const isJoinModal = await joinModal.element.isDisplayed()
- expect(isJoinModal).toBeTruthy()
- await joinModal.switchToCreateCommunity()
- })
- it('CreateCommunityModal - owner create his community', async () => {
- const createModal = new CreateCommunityModal(ownerApp.driver)
- const isCreateModal = await createModal.element.isDisplayed()
- expect(isCreateModal).toBeTruthy()
- await createModal.typeCommunityName(communityName)
- await createModal.submit()
- })
- it('RegisterUsernameModal - owner has registered', async () => {
- const registerModal = new RegisterUsernameModal(ownerApp.driver)
- const isRegisterModal = await registerModal.element.isDisplayed()
- expect(isRegisterModal).toBeTruthy()
- await registerModal.typeUsername(ownerUsername)
- await registerModal.submit()
- })
- it('Connecting to peers modal', async () => {
- const loadingPanelCommunity = new JoiningLoadingPanel(ownerApp.driver)
- const isLoadingPanelCommunity = await loadingPanelCommunity.element.isDisplayed()
- expect(isLoadingPanelCommunity).toBeTruthy()
- })
- it('General channel check', async () => {
- generalChannel = new Channel(ownerApp.driver, 'general')
- const isGeneralChannel = await generalChannel.element.isDisplayed()
- const generalChannelText = await generalChannel.element.getText()
- expect(isGeneralChannel).toBeTruthy()
- expect(generalChannelText).toEqual('# general')
- })
- it('Send message', async () => {
- const isMessageInput = await generalChannel.messageInput.isDisplayed()
- expect(isMessageInput).toBeTruthy()
- await generalChannel.sendMessage(ownerMessages[0])
- })
- it('Visible message', async () => {
- const messages = await generalChannel.getUserMessages(ownerUsername)
- const text = await messages[1].getText()
- expect(text).toEqual(ownerMessages[0])
- })
- it('Opens the settings tab and gets an invitation code', async () => {
- const settingsModal = await new Sidebar(ownerApp.driver).openSettings()
- const isSettingsModal = await settingsModal.element.isDisplayed()
- expect(isSettingsModal).toBeTruthy()
- await sleep(2000)
- await settingsModal.switchTab('invite') // TODO: Fix - the invite tab should be default for the owner
- await sleep(2000)
- const invitationCodeElement = await settingsModal.invitationCode()
- await sleep(2000)
- invitationCode = await invitationCodeElement.getText()
- await sleep(2000)
- console.log({ invitationCode })
- expect(invitationCode).not.toBeUndefined()
- log('Received invitation code:', invitationCode)
- await settingsModal.close()
- })
-
- it('Guest setup', async () => {
- console.log('Second client')
- guestApp = new App()
- await guestApp.open()
- })
- if (process.env.TEST_MODE) {
- it('Close debug modal', async () => {
- const debugModal = new DebugModeModal(guestApp.driver)
- await debugModal.close()
- })
- }
-
- it('Guest joins the new community successfully', async () => {
- console.log('new user - 3')
- const joinCommunityModal = new JoinCommunityModal(guestApp.driver)
- const isJoinCommunityModal = await joinCommunityModal.element.isDisplayed()
- expect(isJoinCommunityModal).toBeTruthy()
- console.log({ invitationCode })
- await joinCommunityModal.typeCommunityCode(invitationCode)
- await joinCommunityModal.submit()
- })
-
- it.skip('RegisterUsernameModal - User tries to register already taken username, sees error', async () => {
- console.log('new user - 4')
- registerModal2 = new RegisterUsernameModal(guestApp.driver)
- const isRegisterModal2 = await registerModal2.element.isDisplayed()
- expect(isRegisterModal2).toBeTruthy()
- await registerModal2.typeUsername(ownerUsername)
- await registerModal2.submit()
- const usernameTakenError = await registerModal2.error.isDisplayed()
- expect(usernameTakenError).toBeTruthy()
- })
-
- it('RegisterUsernameModal - User successfully register not taken username', async () => {
- console.log('new user - 5')
- registerModal2 = new RegisterUsernameModal(guestApp.driver)
- const isRegisterModal = await registerModal2.element.isDisplayed()
- expect(isRegisterModal).toBeTruthy()
- await registerModal2.clearInput()
- await registerModal2.typeUsername(joiningUserUsername)
- await registerModal2.submit()
- })
-
- it.skip('JoiningLoadingPanel', async () => {
- console.log('new user - 6')
- const loadingPanelCommunity2 = new JoiningLoadingPanel(ownerApp.driver)
- const isLoadingPanelCommunity2 = await loadingPanelCommunity2.element.isDisplayed()
- expect(isLoadingPanelCommunity2).toBeTruthy()
- })
- it('User sends a message', async () => {
- console.log('new user - 7')
- generalChannel2 = new Channel(guestApp.driver, 'general')
- await generalChannel2.element.isDisplayed()
- const isMessageInput2 = await generalChannel2.messageInput.isDisplayed()
- expect(isMessageInput2).toBeTruthy()
- console.log('FETCHING CHANNEL MESSAGES!')
- await new Promise(resolve =>
- setTimeout(() => {
- resolve()
- }, 15000)
- )
- await generalChannel2.sendMessage(joiningUserMessages[0])
- })
- it('Sent message is visible in a channel', async () => {
- console.log('new user - 8')
- const messages2 = await generalChannel2.getUserMessages(joiningUserUsername)
- const messages1 = await generalChannel2.getUserMessages(ownerUsername)
-
- console.log({ messages1, messages2 })
- const text2 = await messages2[0].getText()
- expect(text2).toEqual(joiningUserMessages[0])
- })
-
- it('Channel creation - Owner create second channel', async () => {
- sidebar = new Sidebar(ownerApp.driver)
- await sidebar.addNewChannel(newChannelName)
- await sidebar.switchChannel(newChannelName)
- const channels = await sidebar.getChannelList()
- expect(channels.length).toEqual(2)
- })
- it('Channel creation - Owner send message in second channel', async () => {
- secondChannel = new Channel(ownerApp.driver, newChannelName)
- const isMessageInput = await secondChannel.messageInput.isDisplayed()
- expect(isMessageInput).toBeTruthy()
- await secondChannel.sendMessage(ownerMessages[1])
- })
- it('Channel creation - User read message in second channel', async () => {
- sidebar2 = new Sidebar(guestApp.driver)
- await sidebar2.switchChannel(newChannelName)
- secondChannel2 = new Channel(guestApp.driver, newChannelName)
- await new Promise(resolve =>
- setTimeout(() => {
- resolve()
- }, 2000)
- )
- const messages = await secondChannel2.getUserMessages(ownerUsername)
- const text = await messages[1].getText()
- expect(text).toEqual(ownerMessages[1])
- })
- it('Channel deletion - Owner delete second channel', async () => {
- channelContextMenu = new ChannelContextMenu(ownerApp.driver)
- await channelContextMenu.openMenu()
- await channelContextMenu.openDeletionChannelModal()
- await channelContextMenu.deleteChannel()
- const channels = await sidebar.getChannelList()
- expect(channels.length).toEqual(1)
- })
- it('Channel deletion - User see info about channel deletion in general channel', async () => {
- await sleep(5000)
- const messages = await generalChannel2.getUserMessages(ownerUsername)
- const text = await messages[3].getText()
- expect(text).toEqual(`@${ownerUsername} deleted #${newChannelName}`)
- })
- it('Channel deletion - User can create channel with the same name and is fresh channel', async () => {
- console.log('TEST 1')
- await sidebar2.addNewChannel(newChannelName)
- await sidebar2.switchChannel(newChannelName)
- const messages = await secondChannel2.getUserMessages(joiningUserUsername)
- expect(messages.length).toEqual(1)
- await new Promise(resolve =>
- setTimeout(() => {
- resolve()
- }, 2000)
- )
- const channels = await sidebar.getChannelList()
- expect(channels.length).toEqual(2)
- })
- // End of tests for Windows
- if (process.platform !== 'win32') {
- it('Leave community', async () => {
- console.log('TEST 2')
- const settingsModal = await new Sidebar(guestApp.driver).openSettings()
- const isSettingsModal = await settingsModal.element.isDisplayed()
- expect(isSettingsModal).toBeTruthy()
- await settingsModal.openLeaveCommunityModal()
- await settingsModal.leaveCommunityButton()
- })
- if (process.env.TEST_MODE) {
- it('Leave community - Close debug modal', async () => {
- const debugModal = new DebugModeModal(guestApp.driver)
- await debugModal.close()
- })
- }
- // Delete general channel while guest is absent
- it('Channel deletion - Owner recreate general channel', async () => {
- console.log('TEST 3')
- await new Promise(resolve => setTimeout(() => resolve(), 10000))
- const isGeneralChannel = await generalChannel.messageInput.isDisplayed()
- expect(isGeneralChannel).toBeTruthy()
- await channelContextMenu.openMenu()
- await channelContextMenu.openDeletionChannelModal()
- await channelContextMenu.deleteChannel()
- const channels = await sidebar.getChannelList()
- expect(channels.length).toEqual(2)
- })
-
- it('Leave community - Guest re-join to community successfully', async () => {
- console.log('TEST 4')
- const joinCommunityModal = new JoinCommunityModal(guestApp.driver)
- const isJoinCommunityModal = await joinCommunityModal.element.isDisplayed()
- expect(isJoinCommunityModal).toBeTruthy()
- await joinCommunityModal.typeCommunityCode(invitationCode)
- await joinCommunityModal.submit()
- })
- it('Leave community - Guest register new username', async () => {
- console.log('TEST 5')
- const registerModal2 = new RegisterUsernameModal(guestApp.driver)
- const isRegisterModal2 = await registerModal2.element.isDisplayed()
- expect(isRegisterModal2).toBeTruthy()
- await registerModal2.typeUsername(joiningUserUsername2)
- await registerModal2.submit()
- })
-
- // Check correct channels replication
- it('Channel deletion - User see information about recreation general channel and see correct amount of messages', async () => {
- console.log('TEST 6')
- generalChannel2 = new Channel(guestApp.driver, 'general')
- await generalChannel2.element.isDisplayed()
- await new Promise(resolve =>
- setTimeout(() => {
- resolve()
- }, 10000)
- )
- const messages = await generalChannel2.getUserMessages(ownerUsername)
- const text1 = await messages[0].getText()
- const text2 = await messages[1].getText()
- expect(messages.length).toEqual(2)
- expect(text1).toEqual(`@${ownerUsername} deleted all messages in #general`)
- expect(text2).toEqual(`@${joiningUserUsername2} has joined Testcommunity! 🎉`)
- })
-
- it('Leave community - Guest sends a message', async () => {
- console.log('TEST 7')
- generalChannel2 = new Channel(guestApp.driver, 'general')
- await generalChannel2.element.isDisplayed()
- const isMessageInput2 = await generalChannel2.messageInput.isDisplayed()
- expect(isMessageInput2).toBeTruthy()
- await new Promise(resolve =>
- setTimeout(() => {
- resolve()
- }, 5000)
- )
- await generalChannel2.sendMessage(joiningUserMessages[1])
- })
- it('Leave community - Sent message is visible in a channel', async () => {
- console.log('TEST 8')
- const messages2 = await generalChannel2.getUserMessages(joiningUserUsername2)
- const text2 = await messages2[0].getText()
- expect(text2).toEqual(joiningUserMessages[1])
- })
- it('Owner close app', async () => {
- await ownerApp.close({ forceSaveState: true })
- await new Promise(resolve => setTimeout(() => resolve(), 20000))
- })
-
- it('Guest close app', async () => {
- console.log('TEST 9')
- await guestApp?.close()
- })
-
- it('Owner re-open app', async () => {
- await ownerApp?.open()
- await new Promise(resolve => setTimeout(() => resolve(), 10000))
- })
-
- if (process.env.TEST_MODE) {
- it('Close debug modal', async () => {
- const debugModal = new DebugModeModal(ownerApp.driver)
- await debugModal.close()
- })
- }
-
- it('Guest close app - Owner send another message after guest leave app', async () => {
- console.log('TEST 10')
- generalChannel = new Channel(ownerApp.driver, 'general')
- const isMessageInput = await generalChannel.messageInput.isDisplayed()
- expect(isMessageInput).toBeTruthy()
- await generalChannel.sendMessage(ownerMessages[2])
- })
- it('Guest close app - Check if message is visible for owner', async () => {
- console.log('TEST 11')
- const messages = await generalChannel.getUserMessages(ownerUsername)
- const text = await messages[messages.length - 1].getText()
- expect(text).toEqual(ownerMessages[2])
- })
- }
- })
-})
diff --git a/packages/e2e-tests/src/utils.ts b/packages/e2e-tests/src/utils.ts
index 70ba424d44..7379e81199 100644
--- a/packages/e2e-tests/src/utils.ts
+++ b/packages/e2e-tests/src/utils.ts
@@ -1,5 +1,5 @@
import { Browser, Builder, type ThenableWebDriver } from 'selenium-webdriver'
-import { spawn, exec, type ChildProcessWithoutNullStreams, execSync } from 'child_process'
+import { spawn, exec, execSync, type ChildProcessWithoutNullStreams } from 'child_process'
import { type SupportedPlatformDesktop } from '@quiet/types'
import getPort from 'get-port'
import path from 'path'
@@ -15,8 +15,6 @@ export interface BuildSetupInit {
export class BuildSetup {
private driver?: ThenableWebDriver | null
- public containerId?: string
- public ipAddress?: string
public port?: number
public debugPort?: number
public dataDir?: string
@@ -104,16 +102,16 @@ export class BuildSetup {
await this.initPorts()
const env = {
DATA_DIR: this.dataDir || 'Quiet',
- DEBUG: 'backend*',
+ DEBUG: 'backend*,desktop*',
}
if (process.platform === 'win32') {
console.log('!WINDOWS!')
- this.child = spawn(`cd node_modules/.bin & chromedriver.cmd --port=${this.port}`, [], {
+ this.child = spawn(`cd node_modules/.bin & chromedriver.cmd --port=${this.port} --verbose`, [], {
shell: true,
env: Object.assign(process.env, env),
})
} else {
- this.child = spawn(`node_modules/.bin/chromedriver --port=${this.port}`, [], {
+ this.child = spawn(`node_modules/.bin/chromedriver --port=${this.port} --verbose`, [], {
shell: true,
detached: false,
env: Object.assign(process.env, env),
@@ -127,7 +125,7 @@ export class BuildSetup {
)
this.child.on('error', () => {
- console.log('ERROR')
+ console.error('ERROR')
this.killNine()
})
@@ -145,7 +143,7 @@ export class BuildSetup {
console.log('message', data)
})
this.child.on('error', data => {
- console.log('error', data)
+ console.error('error', data)
})
this.child.stdout.on('data', data => {
@@ -153,11 +151,17 @@ export class BuildSetup {
})
this.child.stderr.on('data', data => {
- console.error(`stderr: ${data}`)
+ // Quiet logs (handled by 'debug' package) are available in stderr and only with 'verbose' flag on chromedriver
+ const trashLogs = ['DevTools', 'COMMAND', 'INFO:CONSOLE', '[INFO]:', 'libnotify-WARNING', 'ALSA lib']
+ const dataString = `${data}`
+ for (const l of trashLogs) {
+ if (dataString.includes(l)) return
+ }
+ console.log(dataString)
})
this.child.stdin.on('data', data => {
- console.error(`stdin: ${data}`)
+ console.log(`stdin: ${data}`)
})
}
@@ -196,7 +200,7 @@ export class BuildSetup {
}
}
if (this.driver == null || this.driver === undefined) {
- throw new Error('elo')
+ throw new Error('No driver')
}
return this.driver
diff --git a/packages/state-manager/src/index.ts b/packages/state-manager/src/index.ts
index fc41960a33..697ae67bc1 100644
--- a/packages/state-manager/src/index.ts
+++ b/packages/state-manager/src/index.ts
@@ -82,8 +82,6 @@ export * from './constants'
export { formatBytes } from './utils/functions/formatBytes/formatBytes'
-export { sortPeers } from './utils/functions/sortPeers/sortPeers'
-
export { getInvitationCodes } from './utils/functions/invitationCode/invitationCode'
export type { Socket } from './types'
diff --git a/packages/state-manager/src/sagas/appConnection/connection.selectors.ts b/packages/state-manager/src/sagas/appConnection/connection.selectors.ts
index 876d69b5dc..b0f7606fcf 100644
--- a/packages/state-manager/src/sagas/appConnection/connection.selectors.ts
+++ b/packages/state-manager/src/sagas/appConnection/connection.selectors.ts
@@ -5,9 +5,9 @@ import { allUsers } from '../users/users.selectors'
import { communitiesSelectors } from '../communities/communities.selectors'
import { peersStatsAdapter } from './connection.adapter'
import { connectedPeers } from '../network/network.selectors'
-import { sortPeers } from '../../utils/functions/sortPeers/sortPeers'
import { type NetworkStats } from './connection.types'
import { type User } from '../users/users.types'
+import { sortPeers } from '@quiet/common'
const connectionSlice: CreatedSelectors[StoreKeys.Connection] = (state: StoreState) => state[StoreKeys.Connection]
diff --git a/packages/state-manager/src/utils/functions/sortPeers/sortPeers.ts b/packages/state-manager/src/utils/functions/sortPeers/sortPeers.ts
deleted file mode 100644
index c96c895203..0000000000
--- a/packages/state-manager/src/utils/functions/sortPeers/sortPeers.ts
+++ /dev/null
@@ -1,48 +0,0 @@
-import { isDefined } from '@quiet/common'
-import { type NetworkStats } from '@quiet/types'
-
-/**
-This is the very simple algorithm for evaluating the most wanted peers.
-1. It takes the peers stats list that contains statistics for every peer our node was ever connected to.
-2. Two sorted arrays are created - one sorted by last seen and other by most uptime shared.
-3. Arrays are merged taking one element from list one and one element from the second list. Duplicates are ommited
-4. We end up with mix of last seen and most uptime descending array of peers, the it is enchanced to libp2p address.
- */
-export const sortPeers = (peersAddresses: string[], stats: NetworkStats[]): string[] => {
- const lastSeenSorted = [...stats].sort((a, b) => {
- return b.lastSeen - a.lastSeen
- })
- const mostUptimeSharedSorted = [...stats].sort((a, b) => {
- return b.connectionTime - a.connectionTime
- })
-
- const mostWantedPeers: NetworkStats[] = []
-
- for (let i = 0; i < stats.length; i++) {
- const peerOne = lastSeenSorted[i]
- const peerTwo = mostUptimeSharedSorted[i]
-
- if (!mostWantedPeers.includes(peerOne)) {
- mostWantedPeers.push(peerOne)
- }
-
- if (!mostWantedPeers.includes(peerTwo)) {
- mostWantedPeers.push(peerTwo)
- }
- }
-
- const peerList = mostWantedPeers.map(peerId => {
- return peersAddresses.find(peerAddress => {
- const id = peerAddress.split('/')[7]
- if (id === peerId.peerId) {
- peersAddresses.splice(peersAddresses.indexOf(peerAddress), 1)
- return true
- }
- })
- })
-
- return peerList
- .concat(peersAddresses)
- .filter(address => address !== null)
- .filter(isDefined)
-}