Skip to content

Commit

Permalink
add test for remote attachment codec
Browse files Browse the repository at this point in the history
  • Loading branch information
cameronvoell committed Dec 9, 2024
1 parent c8c5562 commit 2eb0bbd
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 2 deletions.
8 changes: 7 additions & 1 deletion example/src/TestScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ import React, { useEffect, useState } from 'react'
import { View, Text, Button, ScrollView } from 'react-native'

import { clientTests } from './tests/clientTests'
import { contentTypeTests } from './tests/contentTypeTests'
import { conversationTests } from './tests/conversationTests'
import { dmTests } from './tests/dmTests'
import { groupPerformanceTests } from './tests/groupPerformanceTests'
import { groupPermissionsTests } from './tests/groupPermissionsTests'
import { groupTests } from './tests/groupTests'
import { restartStreamTests } from './tests/restartStreamsTests'
import { Test } from './tests/test-utils'

type Result = 'waiting' | 'running' | 'success' | 'failure' | 'error'

function TestView({
Expand Down Expand Up @@ -114,6 +114,7 @@ export enum TestCategory {
restartStreans = 'restartStreams',
groupPermissions = 'groupPermissions',
groupPerformance = 'groupPerformance',
contentType = 'contentType',
}

export default function TestScreen(): JSX.Element {
Expand All @@ -129,6 +130,7 @@ export default function TestScreen(): JSX.Element {
...conversationTests,
...restartStreamTests,
...groupPermissionsTests,
...contentTypeTests,
]
let activeTests, title
switch (params.testSelection) {
Expand Down Expand Up @@ -164,6 +166,10 @@ export default function TestScreen(): JSX.Element {
activeTests = groupPerformanceTests
title = 'Group Performance Unit Tests'
break
case TestCategory.contentType:
activeTests = contentTypeTests
title = 'Content Type Unit Tests'
break
}

return (
Expand Down
96 changes: 96 additions & 0 deletions example/src/tests/contentTypeTests.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import ReactNativeBlobUtil from 'react-native-blob-util'

import { Test, createClients, delayToPropogate } from './test-utils'
import { RemoteAttachmentContent } from '../../../src/index'
const { fs } = ReactNativeBlobUtil

export const contentTypeTests: Test[] = []
let counter = 1
function test(name: string, perform: () => Promise<boolean>) {
contentTypeTests.push({
name: String(counter++) + '. ' + name,
run: perform,
})
}

test('remote attachments should work', async () => {
const [alix, bo] = await createClients(2)
const convo = await alix.conversations.newConversation(bo.address)

// Alice is sending Bob a file from her phone.
const filename = `${Date.now()}.txt`
const file = `${fs.dirs.CacheDir}/${filename}`
await fs.writeFile(file, 'hello world', 'utf8')
const { encryptedLocalFileUri, metadata } = await alix.encryptAttachment({
fileUri: `file://${file}`,
mimeType: 'text/plain',
})

const encryptedFile = encryptedLocalFileUri.slice('file://'.length)
const originalContent = await fs.readFile(file, 'base64')
const encryptedContent = await fs.readFile(encryptedFile, 'base64')
if (encryptedContent === originalContent) {
throw new Error('encrypted file should not match original')
}

// This is where the app will upload the encrypted file to a remote server and generate a URL.
// let url = await uploadFile(encryptedLocalFileUri);
const url = 'https://example.com/123'

// Together with the metadata, we send the URL as a remoteAttachment message to the conversation.
await convo.send({
remoteAttachment: {
...metadata,
scheme: 'https://',
url,
},
})
await delayToPropogate()

// Now we should see the remote attachment message.
const messages = await convo.messages()
if (messages.length !== 1) {
throw new Error('Expected 1 message')
}
const message = messages[0]

if (message.contentTypeId !== 'xmtp.org/remoteStaticAttachment:1.0') {
throw new Error('Expected correctly formatted typeId')
}
if (!message.content()) {
throw new Error('Expected remoteAttachment')
}
if (
(message.content() as RemoteAttachmentContent).url !==
'https://example.com/123'
) {
throw new Error('Expected url to match')
}

// This is where the app prompts the user to download the encrypted file from `url`.
// TODO: let downloadedFile = await downloadFile(url);
// But to simplify this test, we're just going to copy
// the previously encrypted file and pretend that we just downloaded it.
const downloadedFileUri = `file://${fs.dirs.CacheDir}/${Date.now()}.bin`
await fs.cp(
new URL(encryptedLocalFileUri).pathname,
new URL(downloadedFileUri).pathname
)

// Now we can decrypt the downloaded file using the message metadata.
const attached = await alix.decryptAttachment({
encryptedLocalFileUri: downloadedFileUri,
metadata: message.content() as RemoteAttachmentContent,
})
if (attached.mimeType !== 'text/plain') {
throw new Error('Expected mimeType to match')
}
if (attached.filename !== filename) {
throw new Error(`Expected ${attached.filename} to equal ${filename}`)
}
const text = await fs.readFile(new URL(attached.fileUri).pathname, 'utf8')
if (text !== 'hello world') {
throw new Error('Expected text to match')
}
return true
})
8 changes: 7 additions & 1 deletion example/src/tests/test-utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { Platform } from 'expo-modules-core'
import { Client, GroupUpdatedCodec, Group } from 'xmtp-react-native-sdk'
import {
Client,
GroupUpdatedCodec,
Group,
RemoteAttachmentCodec,
} from 'xmtp-react-native-sdk'

export type Test = {
name: string
Expand Down Expand Up @@ -34,6 +39,7 @@ export async function createClients(numClients: number): Promise<Client[]> {
dbEncryptionKey: keyBytes,
})
client.register(new GroupUpdatedCodec())
client.register(new RemoteAttachmentCodec())
clients.push(client)
}
return clients
Expand Down

0 comments on commit 2eb0bbd

Please sign in to comment.