From bb87a965ee1d477b13b223176cdaf467ee353ee3 Mon Sep 17 00:00:00 2001 From: Alex Risch Date: Wed, 12 Jun 2024 10:56:30 -0600 Subject: [PATCH 1/4] App Tests Added app tests --- example/src/TestScreen.tsx | 7 ++ example/src/tests/appTests.ts | 179 ++++++++++++++++++++++++++++++++ example/src/tests/test-utils.ts | 4 +- 3 files changed, 187 insertions(+), 3 deletions(-) create mode 100644 example/src/tests/appTests.ts diff --git a/example/src/TestScreen.tsx b/example/src/TestScreen.tsx index 1d6b847c6..b4bbaa466 100644 --- a/example/src/TestScreen.tsx +++ b/example/src/TestScreen.tsx @@ -6,6 +6,7 @@ import { createdAtTests } from './tests/createdAtTests' import { groupPermissionsTests } from './tests/groupPermissionsTests' import { groupTests } from './tests/groupTests' import { restartStreamTests } from './tests/restartStreamsTests' +import { appTests } from './tests/appTests' import { Test } from './tests/test-utils' import { tests } from './tests/tests' @@ -110,6 +111,7 @@ export enum TestCategory { createdAt = 'createdAt', restartStreans = 'restartStreams', groupPermissions = 'groupPermissions', + appTests = 'appTests', } export default function TestScreen(): JSX.Element { @@ -124,6 +126,7 @@ export default function TestScreen(): JSX.Element { ...createdAtTests, ...restartStreamTests, ...groupPermissionsTests, + ...appTests, ] let activeTests, title switch (params.testSelection) { @@ -151,6 +154,10 @@ export default function TestScreen(): JSX.Element { activeTests = groupPermissionsTests title = 'Group Permissions Unit Tests' break + case TestCategory.appTests: + activeTests = appTests + title = 'Stream Tests Example' + break } return ( diff --git a/example/src/tests/appTests.ts b/example/src/tests/appTests.ts new file mode 100644 index 000000000..9615bb840 --- /dev/null +++ b/example/src/tests/appTests.ts @@ -0,0 +1,179 @@ +import RNFS from 'react-native-fs' + +import { Test, assert, createClients, delayToPropogate } from './test-utils' +import { Client, Group } from '../../../src/index' + +export const appTests: Test[] = [] +let counter = 1 +function test(name: string, perform: () => Promise) { + appTests.push({ + name: String(counter++) + '. ' + name, + run: perform, + }) +} + +// test('stream example', async () => { +// const [alice, bob] = await createClients(2) + +// const aliceGroups = await alice.conversations.listGroups() +// assert(aliceGroups.length === 0, 'alice should have no groups') + +// let groupCallbacks = 0 +// let messageCallbacks = 0 + +// await alice.conversations.streamGroups(async () => { +// groupCallbacks++ +// }) + +// await alice.conversations.streamAllMessages(async () => { +// messageCallbacks++ +// }, true) + +// await delayToPropogate() + +// const group = await bob.conversations.newGroup([alice.address]) +// await group.send('hello') + +// assert(group instanceof Group, 'group should be a Group') + +// await delayToPropogate() + +// assert(groupCallbacks === 1, 'group stream should have received 1 group') +// assert( +// messageCallbacks === 1, +// 'message stream should have received 1 message' +// ) + +// return true +// }) + +// test('installation', async () => { +// const [alice] = await createClients(1) +// const aliceKey = await alice.exportKeyBundle() +// await Client.createFromKeyBundle(aliceKey, { +// env: 'local', +// }) + +// return true +// }) + +// test('can list groups', async () => { +// const now = Date.now() +// const [alice, bo] = await createClients(2) +// console.log('created clients') +// const aliceGroup = await alice.conversations.newGroup([bo.address]) +// await aliceGroup.updateGroupName('hello') +// await aliceGroup.sync() +// await aliceGroup.send('hello1') +// console.log('starting stream') +// await bo.conversations.streamAllMessages(async () => { +// console.log('message received') +// }, true) + +// await bo.conversations.syncGroups() +// const bobGroups = await bo.conversations.listGroups() +// assert(bobGroups.length === 1, 'bob should have 1 group') +// await bo.conversations.streamAllMessages(async () => { +// console.log('message received') +// }, true) +// const bobGroup = bobGroups[0] +// await bobGroup.sync() +// await bobGroup.streamGroupMessages(async () => { +// console.log('message received on group') +// }) +// const bobMessages1 = await bobGroup.messages({ +// direction: 'SORT_DIRECTION_DESCENDING', +// after: now, +// }) + +// assert( +// bobMessages1.length === 2, +// `should have 2 messages on first load received ${bobMessages1.length}` +// ) +// await aliceGroup.send('hello2') +// await bobGroup.sync() +// await bobGroup.send('hello3') +// await aliceGroup.send('hello4') +// await aliceGroup.send('hello5') +// await bobGroup.sync() +// const bobMessages2 = await bobGroup.messages() +// assert( +// bobMessages2.length === 6, +// `should have 6 messages on second load received ${bobMessages2.length}` +// ) +// return true +// }) + +test('can list groups', async () => { + const [alix, bo] = await createClients(2) + console.log('created clients') + let groupCallbacks = 0 + //#region Stream groups + await bo.conversations.streamGroups(async () => { + console.log('group received') + groupCallbacks++ + }) + //#region Stream All Messages + await bo.conversations.streamAllMessages(async () => { + console.log('message received') + }, false) // <<--------- Changing this to true will cause the test to fail + //#endregion + // #region create group + const alixGroup = await alix.conversations.newGroup([bo.address]) + await alixGroup.updateGroupName('hello') + await alixGroup.send('hello1') + console.log('sent group message') + // #endregion + // #region sync groups + await bo.conversations.syncGroups() + // #endregion + const boGroups = await bo.conversations.listGroups() + assert(boGroups.length === 1, 'bo should have 1 group') + const boGroup = boGroups[0] + await boGroup.sync() + + const boMessages1 = await boGroup.messages() + assert( + boMessages1.length === 2, + `should have 2 messages on first load received ${boMessages1.length}` + ) + await boGroup.send('hello2') + await boGroup.send('hello3') + await alixGroup.sync() + const alixMessages = await alixGroup.messages() + for (const message of alixMessages) { + console.log( + 'message', + message.contentTypeId, + message.contentTypeId === 'xmtp.org/text:1.0' + ? message.content() + : 'Group Updated' + ) + } + // alix sees 3 messages + assert( + alixMessages.length === 5, + `should have 5 messages on first load received ${alixMessages.length}` + ) + await alixGroup.send('hello4') + await boGroup.sync() + const boMessages2 = await boGroup.messages() + for (const message of boMessages2) { + console.log( + 'message', + message.contentTypeId, + message.contentTypeId === 'xmtp.org/text:1.0' + ? message.content() + : 'Group Updated' + ) + } + // bo sees 4 messages + assert( + boMessages2.length === 5, + `should have 5 messages on second load received ${boMessages2.length}` + ) + + assert(groupCallbacks === 1, 'group stream should have received 1 group') + + return true +}) diff --git a/example/src/tests/test-utils.ts b/example/src/tests/test-utils.ts index 417988969..43f101fb1 100644 --- a/example/src/tests/test-utils.ts +++ b/example/src/tests/test-utils.ts @@ -21,9 +21,7 @@ export function assert(condition: boolean, msg: string) { } } -export async function createClients( - numClients: number -): Promise[]> { +export async function createClients(numClients: number): Promise { const clients = [] for (let i = 0; i < numClients; i++) { const keyBytes = new Uint8Array([ From 3ad3786eac013a4071d6648db7b862f4f7534096 Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Mon, 17 Jun 2024 13:19:33 -0700 Subject: [PATCH 2/4] update the tests and get them passing in iOS --- example/ios/Podfile.lock | 14 +-- example/src/TestScreen.tsx | 6 -- example/src/tests/appTests.ts | 179 -------------------------------- example/src/tests/groupTests.ts | 75 +++++++++++++ ios/XMTPReactNative.podspec | 2 +- 5 files changed, 83 insertions(+), 193 deletions(-) delete mode 100644 example/src/tests/appTests.ts diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 0d6287e1d..bee7fc802 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -56,7 +56,7 @@ PODS: - hermes-engine/Pre-built (= 0.71.14) - hermes-engine/Pre-built (0.71.14) - libevent (2.1.12) - - LibXMTP (0.5.1-beta2) + - LibXMTP (0.5.2-beta0) - Logging (1.0.0) - MessagePacker (0.4.7) - MMKV (1.3.5): @@ -449,16 +449,16 @@ PODS: - GenericJSON (~> 2.0) - Logging (~> 1.0.0) - secp256k1.swift (~> 0.1) - - XMTP (0.12.0): + - XMTP (0.12.1): - Connect-Swift (= 0.12.0) - GzipSwift - - LibXMTP (= 0.5.1-beta2) + - LibXMTP (= 0.5.2-beta0) - web3.swift - XMTPReactNative (0.1.0): - ExpoModulesCore - MessagePacker - secp256k1.swift - - XMTP (= 0.12.0) + - XMTP (= 0.12.1) - Yoga (1.14.0) DEPENDENCIES: @@ -711,7 +711,7 @@ SPEC CHECKSUMS: GzipSwift: 893f3e48e597a1a4f62fafcb6514220fcf8287fa hermes-engine: d7cc127932c89c53374452d6f93473f1970d8e88 libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 - LibXMTP: 954acfb393be3b19bf44ea9009af558c00222450 + LibXMTP: b56bf1afe38e21e967d6b3c8d840a41164ffdb64 Logging: 9ef4ecb546ad3169398d5a723bc9bea1c46bef26 MessagePacker: ab2fe250e86ea7aedd1a9ee47a37083edd41fd02 MMKV: 506311d0494023c2f7e0b62cc1f31b7370fa3cfb @@ -763,8 +763,8 @@ SPEC CHECKSUMS: secp256k1.swift: a7e7a214f6db6ce5db32cc6b2b45e5c4dd633634 SwiftProtobuf: 407a385e97fd206c4fbe880cc84123989167e0d1 web3.swift: 2263d1e12e121b2c42ffb63a5a7beb1acaf33959 - XMTP: 3d34d8922840d75b8d281ed989843ee813000582 - XMTPReactNative: 4d103fca76e388aebf1cb829e37f4a8e36193e58 + XMTP: 5e28d39dd43b9f8b85861b09cce47efce1da2d8e + XMTPReactNative: 47e3bcf71f97ea840aa07af3220245ccb7626ef4 Yoga: e71803b4c1fff832ccf9b92541e00f9b873119b9 PODFILE CHECKSUM: 95d6ace79946933ecf80684613842ee553dd76a2 diff --git a/example/src/TestScreen.tsx b/example/src/TestScreen.tsx index b4bbaa466..06bc242ce 100644 --- a/example/src/TestScreen.tsx +++ b/example/src/TestScreen.tsx @@ -6,7 +6,6 @@ import { createdAtTests } from './tests/createdAtTests' import { groupPermissionsTests } from './tests/groupPermissionsTests' import { groupTests } from './tests/groupTests' import { restartStreamTests } from './tests/restartStreamsTests' -import { appTests } from './tests/appTests' import { Test } from './tests/test-utils' import { tests } from './tests/tests' @@ -126,7 +125,6 @@ export default function TestScreen(): JSX.Element { ...createdAtTests, ...restartStreamTests, ...groupPermissionsTests, - ...appTests, ] let activeTests, title switch (params.testSelection) { @@ -154,10 +152,6 @@ export default function TestScreen(): JSX.Element { activeTests = groupPermissionsTests title = 'Group Permissions Unit Tests' break - case TestCategory.appTests: - activeTests = appTests - title = 'Stream Tests Example' - break } return ( diff --git a/example/src/tests/appTests.ts b/example/src/tests/appTests.ts deleted file mode 100644 index 9615bb840..000000000 --- a/example/src/tests/appTests.ts +++ /dev/null @@ -1,179 +0,0 @@ -import RNFS from 'react-native-fs' - -import { Test, assert, createClients, delayToPropogate } from './test-utils' -import { Client, Group } from '../../../src/index' - -export const appTests: Test[] = [] -let counter = 1 -function test(name: string, perform: () => Promise) { - appTests.push({ - name: String(counter++) + '. ' + name, - run: perform, - }) -} - -// test('stream example', async () => { -// const [alice, bob] = await createClients(2) - -// const aliceGroups = await alice.conversations.listGroups() -// assert(aliceGroups.length === 0, 'alice should have no groups') - -// let groupCallbacks = 0 -// let messageCallbacks = 0 - -// await alice.conversations.streamGroups(async () => { -// groupCallbacks++ -// }) - -// await alice.conversations.streamAllMessages(async () => { -// messageCallbacks++ -// }, true) - -// await delayToPropogate() - -// const group = await bob.conversations.newGroup([alice.address]) -// await group.send('hello') - -// assert(group instanceof Group, 'group should be a Group') - -// await delayToPropogate() - -// assert(groupCallbacks === 1, 'group stream should have received 1 group') -// assert( -// messageCallbacks === 1, -// 'message stream should have received 1 message' -// ) - -// return true -// }) - -// test('installation', async () => { -// const [alice] = await createClients(1) -// const aliceKey = await alice.exportKeyBundle() -// await Client.createFromKeyBundle(aliceKey, { -// env: 'local', -// }) - -// return true -// }) - -// test('can list groups', async () => { -// const now = Date.now() -// const [alice, bo] = await createClients(2) -// console.log('created clients') -// const aliceGroup = await alice.conversations.newGroup([bo.address]) -// await aliceGroup.updateGroupName('hello') -// await aliceGroup.sync() -// await aliceGroup.send('hello1') -// console.log('starting stream') -// await bo.conversations.streamAllMessages(async () => { -// console.log('message received') -// }, true) - -// await bo.conversations.syncGroups() -// const bobGroups = await bo.conversations.listGroups() -// assert(bobGroups.length === 1, 'bob should have 1 group') -// await bo.conversations.streamAllMessages(async () => { -// console.log('message received') -// }, true) -// const bobGroup = bobGroups[0] -// await bobGroup.sync() -// await bobGroup.streamGroupMessages(async () => { -// console.log('message received on group') -// }) -// const bobMessages1 = await bobGroup.messages({ -// direction: 'SORT_DIRECTION_DESCENDING', -// after: now, -// }) - -// assert( -// bobMessages1.length === 2, -// `should have 2 messages on first load received ${bobMessages1.length}` -// ) -// await aliceGroup.send('hello2') -// await bobGroup.sync() -// await bobGroup.send('hello3') -// await aliceGroup.send('hello4') -// await aliceGroup.send('hello5') -// await bobGroup.sync() -// const bobMessages2 = await bobGroup.messages() -// assert( -// bobMessages2.length === 6, -// `should have 6 messages on second load received ${bobMessages2.length}` -// ) -// return true -// }) - -test('can list groups', async () => { - const [alix, bo] = await createClients(2) - console.log('created clients') - let groupCallbacks = 0 - //#region Stream groups - await bo.conversations.streamGroups(async () => { - console.log('group received') - groupCallbacks++ - }) - //#region Stream All Messages - await bo.conversations.streamAllMessages(async () => { - console.log('message received') - }, false) // <<--------- Changing this to true will cause the test to fail - //#endregion - // #region create group - const alixGroup = await alix.conversations.newGroup([bo.address]) - await alixGroup.updateGroupName('hello') - await alixGroup.send('hello1') - console.log('sent group message') - // #endregion - // #region sync groups - await bo.conversations.syncGroups() - // #endregion - const boGroups = await bo.conversations.listGroups() - assert(boGroups.length === 1, 'bo should have 1 group') - const boGroup = boGroups[0] - await boGroup.sync() - - const boMessages1 = await boGroup.messages() - assert( - boMessages1.length === 2, - `should have 2 messages on first load received ${boMessages1.length}` - ) - await boGroup.send('hello2') - await boGroup.send('hello3') - await alixGroup.sync() - const alixMessages = await alixGroup.messages() - for (const message of alixMessages) { - console.log( - 'message', - message.contentTypeId, - message.contentTypeId === 'xmtp.org/text:1.0' - ? message.content() - : 'Group Updated' - ) - } - // alix sees 3 messages - assert( - alixMessages.length === 5, - `should have 5 messages on first load received ${alixMessages.length}` - ) - await alixGroup.send('hello4') - await boGroup.sync() - const boMessages2 = await boGroup.messages() - for (const message of boMessages2) { - console.log( - 'message', - message.contentTypeId, - message.contentTypeId === 'xmtp.org/text:1.0' - ? message.content() - : 'Group Updated' - ) - } - // bo sees 4 messages - assert( - boMessages2.length === 5, - `should have 5 messages on second load received ${boMessages2.length}` - ) - - assert(groupCallbacks === 1, 'group stream should have received 1 group') - - return true -}) diff --git a/example/src/tests/groupTests.ts b/example/src/tests/groupTests.ts index c212afd7b..3b9d57bbb 100644 --- a/example/src/tests/groupTests.ts +++ b/example/src/tests/groupTests.ts @@ -1657,6 +1657,81 @@ test('can read and update group name', async () => { return true }) +test('can list groups does not fork', async () => { + const [alix, bo] = await createClients(2) + console.log('created clients') + let groupCallbacks = 0 + //#region Stream groups + await bo.conversations.streamGroups(async () => { + console.log('group received') + groupCallbacks++ + }) + //#region Stream All Messages + await bo.conversations.streamAllMessages(async () => { + console.log('message received') + }, true) + //#endregion + // #region create group + const alixGroup = await alix.conversations.newGroup([bo.address]) + await alixGroup.updateGroupName('hello') + await alixGroup.send('hello1') + console.log('sent group message') + // #endregion + // #region sync groups + await bo.conversations.syncGroups() + // #endregion + const boGroups = await bo.conversations.listGroups() + assert(boGroups.length === 1, 'bo should have 1 group') + const boGroup = boGroups[0] + await boGroup.sync() + + const boMessages1 = await boGroup.messages() + assert( + boMessages1.length === 2, + `should have 2 messages on first load received ${boMessages1.length}` + ) + await boGroup.send('hello2') + await boGroup.send('hello3') + await alixGroup.sync() + const alixMessages = await alixGroup.messages() + for (const message of alixMessages) { + console.log( + 'message', + message.contentTypeId, + message.contentTypeId === 'xmtp.org/text:1.0' + ? message.content() + : 'Group Updated' + ) + } + // alix sees 3 messages + assert( + alixMessages.length === 5, + `should have 5 messages on first load received ${alixMessages.length}` + ) + await alixGroup.send('hello4') + await boGroup.sync() + const boMessages2 = await boGroup.messages() + for (const message of boMessages2) { + console.log( + 'message', + message.contentTypeId, + message.contentTypeId === 'xmtp.org/text:1.0' + ? message.content() + : 'Group Updated' + ) + } + // bo sees 4 messages + assert( + boMessages2.length === 5, + `should have 5 messages on second load received ${boMessages2.length}` + ) + + assert(groupCallbacks === 1, 'group stream should have received 1 group') + + return true +}) + + // Commenting this out so it doesn't block people, but nice to have? // test('can stream messages for a long time', async () => { // const bo = await Client.createRandom({ env: 'local', enableV3: true }) diff --git a/ios/XMTPReactNative.podspec b/ios/XMTPReactNative.podspec index 3c9544525..faba7ad6e 100644 --- a/ios/XMTPReactNative.podspec +++ b/ios/XMTPReactNative.podspec @@ -26,5 +26,5 @@ Pod::Spec.new do |s| s.source_files = "**/*.{h,m,swift}" s.dependency 'secp256k1.swift' s.dependency "MessagePacker" - s.dependency "XMTP", "= 0.12.0" + s.dependency "XMTP", "= 0.12.1" end From eb8637de4cf844ad50f8c9287e95996f592ba3e0 Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Mon, 17 Jun 2024 13:23:46 -0700 Subject: [PATCH 3/4] remove app test --- example/src/TestScreen.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/example/src/TestScreen.tsx b/example/src/TestScreen.tsx index 06bc242ce..1d6b847c6 100644 --- a/example/src/TestScreen.tsx +++ b/example/src/TestScreen.tsx @@ -110,7 +110,6 @@ export enum TestCategory { createdAt = 'createdAt', restartStreans = 'restartStreams', groupPermissions = 'groupPermissions', - appTests = 'appTests', } export default function TestScreen(): JSX.Element { From 0eb765d4d6171fc21595366b658805289fa99bba Mon Sep 17 00:00:00 2001 From: Naomi Plasterer Date: Mon, 17 Jun 2024 16:00:03 -0700 Subject: [PATCH 4/4] fix: bump the android version --- android/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/build.gradle b/android/build.gradle index 1d431c066..104ec5c55 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -98,7 +98,7 @@ repositories { dependencies { implementation project(':expo-modules-core') implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${getKotlinVersion()}" - implementation "org.xmtp:android:0.13.5" + implementation "org.xmtp:android:0.13.6" implementation 'com.google.code.gson:gson:2.10.1' implementation 'com.facebook.react:react-native:0.71.3' implementation "com.daveanthonythomas.moshipack:moshipack:1.0.1"