Skip to content

Commit

Permalink
Add file upload test cases for single user
Browse files Browse the repository at this point in the history
  • Loading branch information
islathehut committed Dec 17, 2024
1 parent e0f02d8 commit a5b758e
Show file tree
Hide file tree
Showing 7 changed files with 206 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import { SocketModule } from '../socket/socket.module'
import { StorageEvents } from '../storage/storage.types'
import { IpfsFileManagerModule } from './ipfs-file-manager.module'
import { IpfsFileManagerService } from './ipfs-file-manager.service'
import { sleep } from '../common/sleep'
import fs from 'fs'
import { createLogger } from '../common/logger'

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,7 @@ export const ChannelInputComponent: React.FC<ChannelInputProps> = ({
}}
/>
<input
data-testid='uploadFileInput'
ref={fileInput}
type='file'
onChange={handleFileInput}
Expand Down
5 changes: 5 additions & 0 deletions packages/e2e-tests/src/enums.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,8 @@ export enum X_DATA_TESTID {
EDIT_PROFILE = 'contextMenu-close-button-Editprofile',
PROFILE = 'contextMenu-close-button-Profile',
}

export enum UploadedFileType {
IMAGE = 'IMAGE',
FILE = 'FILE',
}
189 changes: 183 additions & 6 deletions packages/e2e-tests/src/selectors.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { By, Key, type ThenableWebDriver, type WebElement, until, error } from 'selenium-webdriver'
import { BuildSetup, logAndReturnError, promiseWithRetries, sleep, type BuildSetupInit } from './utils'
import path from 'path'
import { X_DATA_TESTID } from './enums'
import { UploadedFileType, X_DATA_TESTID } from './enums'
import { MessageIds, RetryConfig } from './types'
import { createLogger } from './logger'

Expand Down Expand Up @@ -345,7 +345,7 @@ export class Channel {
return this.driver.findElement(By.xpath('//ul[@id="messages-scroll"]'))
}

async waitForUserMessage(username: string, messageContent: string) {
async waitForUserMessageByText(username: string, messageContent: string) {
logger.info(`Waiting for user "${username}" message "${messageContent}"`)
return this.driver.wait(async () => {
const messages = await this.getUserMessages(username)
Expand All @@ -361,6 +361,82 @@ export class Channel {
})
}

async waitForUserMessageByFilename(
username: string,
filename: string,
fileType: UploadedFileType
): Promise<WebElement> {
logger.info(`Waiting for user "${username}" message with uploaded file "${filename}"`)
return this.driver.wait(async () => {
const messages = await this.getUserMessages(username)
for (const element of messages) {
const filenameElement = await this.getUploadedFilenameElementByType(filename, fileType, element)
if (filenameElement != null) {
logger.info(`Found message with matching filename ${filename}`)
return element
}
}
throw logAndReturnError(`No message found for user ${username} and filename ${filename}`)
})
}

private async getUploadedFilenameElementByType(
filename: string,
fileType: UploadedFileType,
baseElement: WebElement
): Promise<WebElement | undefined> {
let filenameElement: WebElement | undefined = undefined
switch (fileType) {
case UploadedFileType.IMAGE:
filenameElement = await this.getUploadedImageFilenameElement(filename, baseElement)
break
case UploadedFileType.FILE:
filenameElement = await this.getUploadedFileFilenameElement(filename, baseElement)
break
}

return filenameElement
}

private async getUploadedFileFilenameElement(
filename: string,
baseElement: WebElement
): Promise<WebElement | undefined> {
try {
const filenameComponentElement = await baseElement.findElement(By.xpath(`//*[@class='FileComponentfilename']`))
const parsedPath = path.parse(filename)
// this is split because we print the message as multiple lines and contains doesn't return true when searching the full filename
const filenameElement = await filenameComponentElement.findElement(
By.xpath(`//h5[contains(text(), "${parsedPath.name}")]`)
)
if ((await filenameElement.getText()) === filename) {
return filenameElement
}
} catch (e) {
if (!e.message.includes('no such element')) {
throw e
}
}

return undefined
}

private async getUploadedImageFilenameElement(
filename: string,
baseElement: WebElement
): Promise<WebElement | undefined> {
try {
const filenameElement = await baseElement.findElement(By.xpath(`//p[text()='${filename}']`))
return filenameElement
} catch (e) {
if (!e.message.includes('no such element')) {
throw e
}
}

return undefined
}

get getAllMessages() {
return this.driver.wait(until.elementsLocated(By.xpath('//*[contains(@data-testid, "userMessages-")]')))
}
Expand All @@ -373,16 +449,34 @@ export class Channel {
return this.driver.wait(until.elementLocated(By.xpath('//*[@data-testid="messageInput"]')))
}

get uploadFileInput() {
return this.driver.wait(until.elementLocated(By.xpath('//*[@data-testid="uploadFileInput"]')))
}

async sendMessage(message: string, username: string): Promise<MessageIds> {
const communityNameInput = await this.messageInput
await communityNameInput.sendKeys(message)
await communityNameInput.sendKeys(Key.ENTER)
const sendMessageInput = await this.messageInput
await sendMessageInput.sendKeys(message)
await sendMessageInput.sendKeys(Key.ENTER)
await sleep(5000)
return this.getMessageIdsByText(message, username)
}

async uploadFile(
filename: string,
filePath: string,
fileType: UploadedFileType,
username: string
): Promise<MessageIds> {
const uploadFileInput = await this.uploadFileInput
await uploadFileInput.sendKeys(filePath)
const sendMessageInput = await this.messageInput
await sendMessageInput.sendKeys(Key.ENTER)
await sleep(10_000)
return this.getMessageIdsByFile(filename, fileType, username)
}

async getMessageIdsByText(message: string, username: string): Promise<MessageIds> {
const messageElement = await this.waitForUserMessage(username, message)
const messageElement = await this.waitForUserMessageByText(username, message)
if (!messageElement) {
throw logAndReturnError(`No message element found for message ${message}`)
}
Expand All @@ -407,6 +501,32 @@ export class Channel {
}
}

async getMessageIdsByFile(filename: string, fileType: UploadedFileType, username: string): Promise<MessageIds> {
const messageElement = await this.waitForUserMessageByFilename(username, filename, fileType)
if (!messageElement) {
throw logAndReturnError(`No message element found for filename ${filename}`)
}

let testId = await messageElement.getAttribute('data-testid')
logger.info(`Data Test ID for message content: ${testId}`)
let testIdSplit = testId.split('-')
const parentMessageId = testIdSplit[testIdSplit.length - 1]

const contentElement = await this.waitForMessageContentByFilename(filename, fileType, messageElement)
if (!contentElement) {
throw logAndReturnError(`No message content element found for filename ${filename}`)
}

testId = await contentElement.getAttribute('data-testid')
logger.info(`Data Test ID for message content: ${testId}`)
testIdSplit = testId.split('-')
const messageId = testIdSplit[testIdSplit.length - 1]
return {
messageId,
parentMessageId,
}
}

async getUserMessages(username: string) {
return await this.driver.wait(
until.elementsLocated(By.xpath(`//*[contains(@data-testid, "userMessages-${username}")]`))
Expand Down Expand Up @@ -495,6 +615,63 @@ export class Channel {
throw logAndReturnError(`Failed to find content for message with content ${messageContent}`)
}

async waitForMessageContentByFilename(
filename: string,
fileType: UploadedFileType,
messageElement: WebElement
): Promise<WebElement> {
logger.info(`Waiting for file content for message with filename ${filename} and type ${fileType}`)
const messageContentElements = await this.driver.wait(
messageElement.findElements(By.xpath(`//*[contains(@data-testid, "messagesGroupContent-")]`))
)
for (const element of messageContentElements) {
logger.info(await element.getId())
logger.info(`Testing content for type ${fileType}`)
let containerElements: WebElement[] = []
switch (fileType) {
case UploadedFileType.IMAGE:
containerElements = await this.driver.wait(
element.findElements(By.xpath(`//*[@class='UploadedImagecontainer']`))
)
break
case UploadedFileType.FILE:
containerElements = await this.driver.wait(
element.findElements(By.xpath(`//*[contains(@data-testid, "-fileComponent")]`))
)
break
}

for (const container of containerElements) {
logger.info(`Testing uploaded file container ${await container.getId()}`)
const filenameElement = await this.getUploadedFilenameElementByType(filename, fileType, container)
if (filenameElement == null) {
continue
}

let contentElement: WebElement | undefined = undefined
switch (fileType) {
case UploadedFileType.IMAGE:
contentElement = await this.driver.wait(
container.findElement(By.xpath(`//img[@class='UploadedImageimage']`))
)
break
case UploadedFileType.FILE:
contentElement = await this.driver.wait(
container.findElement(By.xpath(`//img[@class='FileComponentactionIcon']`))
)
break
}

if (contentElement != null && (await contentElement.isDisplayed())) {
logger.info(`Found content element for message with filename ${filename} and type ${fileType}`)
return element
}
}
}

throw logAndReturnError(`Failed to find content for message with filename ${filename} and type ${fileType}`)
}

async waitForLabelsNotPresent(username: string) {
logger.info(`Waiting for user's "${username}" label to not be present`)
await this.driver.wait(async () => {
Expand Down
17 changes: 17 additions & 0 deletions packages/e2e-tests/src/tests/oneClient.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { fork } from 'child_process'
import path from 'path'
import { createLogger } from '../logger'
import { sleep } from '../utils'
import { UploadedFileType } from '../enums'

const logger = createLogger('oneClient')

Expand Down Expand Up @@ -204,4 +205,20 @@ describe('One Client', () => {
await generalChannel.sendMessage('this shows up as sent again', ownerUserName)
})
})

describe('Uploading files', () => {
it('Owner uploads an image', async () => {
const filename = 'testImage.gif'
const uploadFilePath = path.resolve('./src/tests/resources/', filename)
logger.info(`Upload image path`, uploadFilePath)
await generalChannel.uploadFile(filename, uploadFilePath, UploadedFileType.IMAGE, ownerUserName)
})

it('Owner uploads a non-image file', async () => {
const filename = 'testFile.pdf'
const uploadFilePath = path.resolve('./src/tests/resources/', filename)
logger.info(`Upload file path`, uploadFilePath)
await generalChannel.uploadFile(filename, uploadFilePath, UploadedFileType.FILE, ownerUserName)
})
})
})
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit a5b758e

Please sign in to comment.