diff options
author | Paul Frazee <pfrazee@gmail.com> | 2023-03-31 13:17:26 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-03-31 13:17:26 -0500 |
commit | a3334a01a221877d3e06e02f960fda441f3460bd (patch) | |
tree | 64cdbb1232d1a3c00750c346b6e3ae529b51d1b0 /jest | |
parent | 19f3a2fa92a61ddb785fc4e42d73792c1d0e772c (diff) | |
download | voidsky-a3334a01a221877d3e06e02f960fda441f3460bd.tar.zst |
Lex refactor (#362)
* Remove the hackcheck for upgrades * Rename the PostEmbeds folder to match the codebase style * Updates to latest lex refactor * Update to use new bsky agent * Update to use api package's richtext library * Switch to upsertProfile * Add TextEncoder/TextDecoder polyfill * Add Intl.Segmenter polyfill * Update composer to calculate lengths by grapheme * Fix detox * Fix login in e2e * Create account e2e passing * Implement an e2e mocking framework * Don't use private methods on mobx models as mobx can't track them * Add tooling for e2e-specific builds and add e2e media-picker mock * Add some tests and fix some bugs around profile editing * Add shell tests * Add home screen tests * Add thread screen tests * Add tests for other user profile screens * Add search screen tests * Implement profile imagery change tools and tests * Update to new embed behaviors * Add post tests * Fix to profile-screen test * Fix session resumption * Update web composer to new api * 1.11.0 * Fix pagination cursor parameters * Add quote posts to notifications * Fix embed layouts * Remove youtube inline player and improve tap handling on link cards * Reset minimal shell mode on all screen loads and feed swipes (close #299) * Update podfile.lock * Improve post notfound UI (close #366) * Bump atproto packages
Diffstat (limited to 'jest')
-rw-r--r-- | jest/test-pds.ts | 259 |
1 files changed, 130 insertions, 129 deletions
diff --git a/jest/test-pds.ts b/jest/test-pds.ts index 32f3bc9b0..1e87df811 100644 --- a/jest/test-pds.ts +++ b/jest/test-pds.ts @@ -1,86 +1,73 @@ import {AddressInfo} from 'net' import os from 'os' +import net from 'net' import path from 'path' import * as crypto from '@atproto/crypto' -import PDSServer, { - Database as PDSDatabase, - MemoryBlobStore, - ServerConfig as PDSServerConfig, -} from '@atproto/pds' -import * as plc from '@atproto/plc' -import AtpAgent from '@atproto/api' +import {PDS, ServerConfig, Database, MemoryBlobStore} from '@atproto/pds' +import * as plc from '@did-plc/lib' +import {PlcServer, Database as PlcDatabase} from '@did-plc/server' +import {BskyAgent} from '@atproto/api' + +const ADMIN_PASSWORD = 'admin-pass' +const SECOND = 1000 +const MINUTE = SECOND * 60 +const HOUR = MINUTE * 60 export interface TestUser { email: string did: string - declarationCid: string handle: string password: string - agent: AtpAgent -} - -export interface TestUsers { - alice: TestUser - bob: TestUser - carla: TestUser + agent: BskyAgent } export interface TestPDS { pdsUrl: string - users: TestUsers + mocker: Mocker close: () => Promise<void> } -// NOTE -// deterministic date generator -// we use this to ensure the mock dataset is always the same -// which is very useful when testing -function* dateGen() { - let start = 1657846031914 - while (true) { - yield new Date(start).toISOString() - start += 1e3 - } -} - export async function createServer(): Promise<TestPDS> { - const keypair = await crypto.EcdsaKeypair.create() + const repoSigningKey = await crypto.Secp256k1Keypair.create() + const plcRotationKey = await crypto.Secp256k1Keypair.create() + const port = await getPort() + + const plcDb = PlcDatabase.mock() - // run plc server - const plcDb = plc.Database.memory() - await plcDb.migrateToLatestOrThrow() - const plcServer = plc.PlcServer.create({db: plcDb}) + const plcServer = PlcServer.create({db: plcDb}) const plcListener = await plcServer.start() const plcPort = (plcListener.address() as AddressInfo).port const plcUrl = `http://localhost:${plcPort}` - const recoveryKey = (await crypto.EcdsaKeypair.create()).did() + const recoveryKey = (await crypto.Secp256k1Keypair.create()).did() - const plcClient = new plc.PlcClient(plcUrl) - const serverDid = await plcClient.createDid( - keypair, - recoveryKey, - 'localhost', - 'https://pds.public.url', - ) + const plcClient = new plc.Client(plcUrl) + const serverDid = await plcClient.createDid({ + signingKey: repoSigningKey.did(), + rotationKeys: [recoveryKey, plcRotationKey.did()], + handle: 'localhost', + pds: `http://localhost:${port}`, + signer: plcRotationKey, + }) const blobstoreLoc = path.join(os.tmpdir(), crypto.randomStr(5, 'base32')) - const cfg = new PDSServerConfig({ + const cfg = new ServerConfig({ debugMode: true, version: '0.0.0', scheme: 'http', hostname: 'localhost', + port, serverDid, recoveryKey, - adminPassword: 'admin-pass', + adminPassword: ADMIN_PASSWORD, inviteRequired: false, didPlcUrl: plcUrl, jwtSecret: 'jwt-secret', availableUserDomains: ['.test'], appUrlPasswordReset: 'app://forgot-password', emailNoReplyAddress: 'noreply@blueskyweb.xyz', - publicUrl: 'https://pds.public.url', + publicUrl: `http://localhost:${port}`, imgUriSalt: '9dd04221f5755bce5f55f47464c27e1e', imgUriKey: 'f23ecd142835025f42c3db2cf25dd813956c178392760256211f9d315f8ab4d8', @@ -88,22 +75,33 @@ export async function createServer(): Promise<TestPDS> { blobstoreLocation: `${blobstoreLoc}/blobs`, blobstoreTmp: `${blobstoreLoc}/tmp`, maxSubscriptionBuffer: 200, - repoBackfillLimitMs: 1e3 * 60 * 60, + repoBackfillLimitMs: HOUR, }) - const db = PDSDatabase.memory() + const db = + cfg.dbPostgresUrl !== undefined + ? Database.postgres({ + url: cfg.dbPostgresUrl, + schema: cfg.dbPostgresSchema, + }) + : Database.memory() await db.migrateToLatestOrThrow() + const blobstore = new MemoryBlobStore() - const pds = PDSServer.create({db, blobstore, keypair, config: cfg}) - const pdsServer = await pds.start() - const pdsPort = (pdsServer.address() as AddressInfo).port - const pdsUrl = `http://localhost:${pdsPort}` - const testUsers = await genMockData(pdsUrl) + const pds = PDS.create({ + db, + blobstore, + repoSigningKey, + plcRotationKey, + config: cfg, + }) + await pds.start() + const pdsUrl = `http://localhost:${port}` return { pdsUrl, - users: testUsers, + mocker: new Mocker(pdsUrl), async close() { await pds.destroy() await plcServer.destroy() @@ -111,90 +109,93 @@ export async function createServer(): Promise<TestPDS> { } } -async function genMockData(pdsUrl: string): Promise<TestUsers> { - const date = dateGen() +class Mocker { + agent: BskyAgent + users: Record<string, TestUser> = {} - const agents = { - loggedout: new AtpAgent({service: pdsUrl}), - alice: new AtpAgent({service: pdsUrl}), - bob: new AtpAgent({service: pdsUrl}), - carla: new AtpAgent({service: pdsUrl}), + constructor(public service: string) { + this.agent = new BskyAgent({service}) } - const users: TestUser[] = [ - { - email: 'alice@test.com', - did: '', - declarationCid: '', - handle: 'alice.test', - password: 'hunter2', - agent: agents.alice, - }, - { - email: 'bob@test.com', - did: '', - declarationCid: '', - handle: 'bob.test', - password: 'hunter2', - agent: agents.bob, - }, - { - email: 'carla@test.com', - did: '', - declarationCid: '', - handle: 'carla.test', + + // NOTE + // deterministic date generator + // we use this to ensure the mock dataset is always the same + // which is very useful when testing + *dateGen() { + let start = 1657846031914 + while (true) { + yield new Date(start).toISOString() + start += 1e3 + } + } + + async createUser(name: string) { + const agent = new BskyAgent({service: this.agent.service}) + const email = `fake${Object.keys(this.users).length + 1}@fake.com` + const res = await agent.createAccount({ + email, + handle: name + '.test', password: 'hunter2', - agent: agents.carla, - }, - ] - const alice = users[0] - const bob = users[1] - const carla = users[2] - - let _i = 1 - for (const user of users) { - const res = await agents.loggedout.api.com.atproto.account.create({ - email: user.email, - handle: user.handle, - password: user.password, - }) - user.agent.api.setHeader('Authorization', `Bearer ${res.data.accessJwt}`) - const {data: profile} = await user.agent.api.app.bsky.actor.getProfile({ - actor: user.handle, }) - user.did = res.data.did - user.declarationCid = profile.declaration.cid - await user.agent.api.app.bsky.actor.profile.create( - {did: user.did}, - { - displayName: ucfirst(user.handle).slice(0, -5), - description: `Test user ${_i++}`, - }, - ) + this.users[name] = { + did: res.data.did, + email, + handle: name + '.test', + password: 'hunter2', + agent: agent, + } } - // everybody follows everybody - const follow = async (author: TestUser, subject: TestUser) => { - await author.agent.api.app.bsky.graph.follow.create( - {did: author.did}, - { - subject: { - did: subject.did, - declarationCid: subject.declarationCid, - }, - createdAt: date.next().value || '', - }, - ) + async follow(a: string, b: string) { + await this.users[a].agent.follow(this.users[b].did) + } + + async generateStandardGraph() { + await this.createUser('alice') + await this.createUser('bob') + await this.createUser('carla') + + await this.users.alice.agent.upsertProfile(() => ({ + displayName: 'Alice', + description: 'Test user 1', + })) + + await this.users.bob.agent.upsertProfile(() => ({ + displayName: 'Bob', + description: 'Test user 2', + })) + + await this.users.carla.agent.upsertProfile(() => ({ + displayName: 'Carla', + description: 'Test user 3', + })) + + await this.follow('alice', 'bob') + await this.follow('alice', 'carla') + await this.follow('bob', 'alice') + await this.follow('bob', 'carla') + await this.follow('carla', 'alice') + await this.follow('carla', 'bob') } - await follow(alice, bob) - await follow(alice, carla) - await follow(bob, alice) - await follow(bob, carla) - await follow(carla, alice) - await follow(carla, bob) - - return {alice, bob, carla} } -function ucfirst(str: string): string { - return str.at(0)?.toUpperCase() + str.slice(1) +const checkAvailablePort = (port: number) => + new Promise(resolve => { + const server = net.createServer() + server.unref() + server.on('error', () => resolve(false)) + server.listen({port}, () => { + server.close(() => { + resolve(true) + }) + }) + }) + +async function getPort() { + for (let i = 3000; i < 65000; i++) { + if (await checkAvailablePort(i)) { + return i + } + } + throw new Error('Unable to find an available port') } |