crud tests

This commit is contained in:
dholms 2022-09-09 15:25:36 -05:00
parent 3ef39fe34a
commit dad56e802f
13 changed files with 387 additions and 289 deletions

@ -27,15 +27,17 @@ export const describeRepoResponse = z.object({
export type DescribeRepoResponse = z.infer<typeof describeRepoResponse>
export const listRecordsParams = z.object({
count: z.number().optional(),
from: z.string().optional(),
limit: z.union([z.number(), def.common.strToInt]).optional(),
before: z.string().optional(),
after: z.string().optional(),
reverse: def.common.strToBool.optional(),
})
export type ListRecordsParams = z.infer<typeof listRecordsParams>
export const listRecordsResponse = z.object({
records: z.array(
z.object({
key: z.string(),
uri: z.string(),
value: z.any(),
}),
),
@ -43,7 +45,7 @@ export const listRecordsResponse = z.object({
export type ListRecordsResponse = z.infer<typeof listRecordsResponse>
export const getRecordResponse = z.object({
key: z.string(),
uri: z.string(),
value: z.any(),
})
export type GetRecordResponse = z.infer<typeof getRecordResponse>

@ -248,7 +248,7 @@ class AdxRepoCollectionClient {
async list(
schema: t.SchemaOpt,
params?: ht.ListRecordsParams,
): Promise<ht.ListRecordsResponse> {
): Promise<t.ListRecordsResponseValidated> {
const url = this.repo.pds.url(
PdsEndpoint.RepoCollection,
[this.repo.did, this.id],
@ -264,7 +264,7 @@ class AdxRepoCollectionClient {
records: resSafe.records.map((record) => {
const validation = validator.validate(record.value)
return {
key: record.key,
uri: record.uri,
value: record.value,
valid: validation.valid,
fullySupported: validation.fullySupported,
@ -296,7 +296,7 @@ class AdxRepoCollectionClient {
const validator = getRecordValidator(schema, this.repo.pds.client)
const validation = validator.validate(resSafe.value)
return {
key: resSafe.key,
uri: resSafe.uri,
value: resSafe.value,
valid: validation.valid,
fullySupported: validation.fullySupported,
@ -309,7 +309,11 @@ class AdxRepoCollectionClient {
/**
* Create a new record.
*/
async create(schema: t.SchemaOpt, value: any): Promise<AdxUri> {
async create(
schema: t.SchemaOpt,
value: any,
validate = true,
): Promise<AdxUri> {
if (!this.repo.writable) {
throw new err.WritePermissionError()
}
@ -320,7 +324,7 @@ class AdxRepoCollectionClient {
const url = this.repo.pds.url(
PdsEndpoint.RepoCollection,
[this.repo.did, this.id],
{ verified: true },
{ validate },
)
const res = await axios.post(url, value).catch(toAPIError)
const { uri } = ht.createRecordResponse.parse(res.data)
@ -330,7 +334,7 @@ class AdxRepoCollectionClient {
/**
* Write the record.
*/
async put(schema: t.SchemaOpt, key: string, value: any) {
async put(schema: t.SchemaOpt, key: string, value: any, validate = true) {
if (!this.repo.writable) {
throw new err.WritePermissionError()
}
@ -341,7 +345,7 @@ class AdxRepoCollectionClient {
const url = this.repo.pds.url(
PdsEndpoint.RepoRecord,
[this.repo.did, this.id, key],
{ verified: true },
{ validate },
)
const res = await axios.put(url, value).catch(toAPIError)
const { uri } = ht.createRecordResponse.parse(res.data)

@ -32,6 +32,10 @@ export interface GetRecordResponseValidated extends GetRecordResponse {
fallbacks?: string[] | undefined
}
export interface ListRecordsResponseValidated {
records: GetRecordResponseValidated[]
}
export interface BatchWrite {
action: 'create' | 'put' | 'del'
collection: string

@ -38,6 +38,8 @@ const strToInt = z
})
.transform((str) => parseInt(str))
const strToBool = z.string().transform((str) => str === 'true' || str === 't')
export const def = {
string: z.string(),
cid,
@ -45,4 +47,5 @@ export const def = {
did,
bytes,
strToInt,
strToBool,
}

@ -26,10 +26,24 @@ export class Collection {
return this.repo.blockstore.getUnchecked(cid)
}
async listRecords(count?: number): Promise<unknown[]> {
const vals = await this.repo.data.listWithPrefix(this.name(), count)
async listRecords(
count?: number,
after?: TID,
before?: TID,
): Promise<{ key: TID; value: unknown }[]> {
count = count || Number.MAX_SAFE_INTEGER
const afterKey = after ? this.dataIdForRecord(after) : this.name()
const beforeKey = before ? this.dataIdForRecord(before) : this.name() + 'a'
const vals = await this.repo.data.list(count, afterKey, beforeKey)
return Promise.all(
vals.map((val) => this.repo.blockstore.getUnchecked(val.value)),
vals.map(async (val) => {
const parts = val.key.split('/')
const tid = TID.fromStr(parts[parts.length - 1])
return {
key: tid,
value: await this.repo.blockstore.getUnchecked(val.value),
}
}),
)
}

@ -628,10 +628,12 @@ export class MST implements DataStore {
}
}
async list(from: string, count: number): Promise<Leaf[]> {
async list(count: number, after?: string, before?: string): Promise<Leaf[]> {
const vals: Leaf[] = []
for await (const leaf of this.walkLeavesFrom(from)) {
for await (const leaf of this.walkLeavesFrom(after || '')) {
if (leaf.key === after) continue
if (vals.length >= count) break
if (before && leaf.key >= before) break
vals.push(leaf)
}
return vals

@ -76,7 +76,7 @@ export interface DataStore {
update(key: string, value: CID): Promise<DataStore>
delete(key: string): Promise<DataStore>
get(key: string): Promise<CID | null>
list(from: string, count: number): Promise<DataValue[]>
list(count: number, after?: string, before?: string): Promise<DataValue[]>
listWithPrefix(prefix: string, count?: number): Promise<DataValue[]>
diff(other: DataStore): Promise<DataDiff>
save(): Promise<CID>

@ -5,7 +5,7 @@
"scripts": {
"build": "node ./build.js",
"start": "node dist/index.js",
"test": "jest tests/revamp.test.ts",
"test": "jest tests/crud.test.ts",
"prettier": "prettier --check src/",
"prettier:fix": "prettier --write src/",
"lint": "eslint . --ext .ts,.tsx",

@ -133,16 +133,17 @@ export class Database {
}
record.raw = JSON.stringify(obj)
const table = this.findTableForCollection(uri.collection)
await table.set(uri, obj)
const recordTable = this.db.getRepository(AdxRecord)
await recordTable.save(record)
const table = this.findTableForCollection(uri.collection)
await table.set(uri, obj)
}
async deleteRecord(uri: AdxUri) {
const table = this.findTableForCollection(uri.collection)
const recordTable = this.db.getRepository(AdxRecord)
await Promise.all([table.delete(uri), recordTable.delete(uri)])
await Promise.all([table.delete(uri), recordTable.delete(uri.toString())])
}
async listCollectionsForDid(did: string): Promise<string[]> {
@ -160,32 +161,41 @@ export class Database {
did: string,
collection: string,
limit: number,
reverse: boolean,
before?: string,
): Promise<unknown[]> {
after?: string,
): Promise<{ uri: string; value: unknown }[]> {
const builder = await this.db
.createQueryBuilder()
.select(['record.uri AS uri, record.raw AS raw'])
.from(AdxRecord, 'record')
.where('record.did = :did', { did })
.andWhere('record.collection = :collection', { collection })
.orderBy('record.tid', 'DESC')
.orderBy('record.tid', reverse ? 'DESC' : 'ASC')
.limit(limit)
if (before !== undefined) {
builder.andWhere('record.tid <= :before', { before })
builder.andWhere('record.tid < :before', { before })
}
if (after !== undefined) {
builder.andWhere('record.tid > :after', { after })
}
const res = await builder.getRawMany()
return res.map((row) => {
return {
...JSON.parse(row.raw),
uri: row.uri,
value: JSON.parse(row.raw),
}
})
}
async getRecord(uri: AdxUri): Promise<unknown | null> {
const table = this.findTableForCollection(uri.collection)
return table.get(uri)
const record = await this.db
.getRepository(AdxRecord)
.findOneBy({ uri: uri.toString() })
if (record === null) return null
return JSON.parse(record.raw)
}
findTableForCollection(collection: string) {

@ -6,6 +6,8 @@ import {
DescribeRepoResponse,
listRecordsParams,
batchWriteParams,
ListRecordsResponse,
GetRecordResponse,
} from '@adxp/api'
import { resolveName, AdxUri, BatchWrite, TID } from '@adxp/common'
import * as auth from '@adxp/auth'
@ -53,7 +55,7 @@ router.post('/:did', async (req, res) => {
}
}
await db.setRepoRoot(did, repo.cid)
res.status(200).send()
res.sendStatus(200)
})
router.post('/:did/c/:namespace/:dataset', async (req, res) => {
@ -86,7 +88,7 @@ router.post('/:did/c/:namespace/:dataset', async (req, res) => {
}
await db.setRepoRoot(did, repo.cid)
// @TODO update subscribers
res.status(200).send({ uri: uri.toString() })
res.json({ uri: uri.toString() })
})
router.put('/:did/c/:namespace/:dataset/r/:tid', async (req, res) => {
@ -119,7 +121,7 @@ router.put('/:did/c/:namespace/:dataset/r/:tid', async (req, res) => {
}
await db.setRepoRoot(did, repo.cid)
// @TODO update subscribers
res.status(200).send({ uri: uri.toString() })
res.json({ uri: uri.toString() })
})
router.delete('/:did/c/:namespace/:dataset/r/:tid', async (req, res) => {
@ -131,10 +133,10 @@ router.delete('/:did/c/:namespace/:dataset/r/:tid', async (req, res) => {
const repo = await util.loadRepo(res, did, authStore)
await repo.getCollection(collection).deleteRecord(TID.fromStr(tid))
const uri = new AdxUri(`${did}/${collection}/${tid.toString()}`)
await db.indexRecord(uri, req.body)
await db.deleteRecord(uri)
await db.setRepoRoot(did, repo.cid)
// @TODO update subscribers
res.status(200).send()
res.sendStatus(200)
})
// DESCRIBE REPO
@ -167,25 +169,44 @@ router.get('/:nameOrDid', async (req, res) => {
let didDoc: didSdk.DIDDocument
let nameIsCorrect: boolean | undefined
if (nameOrDid.startsWith('did:')) {
did = nameOrDid
didDoc = await resolveDidWrapped(did)
name = 'undefined' // TODO: need to decide how username gets published in the did doc
if (confirmName) {
const namesDeclaredDid = await resolveNameWrapped(name)
nameIsCorrect = did === namesDeclaredDid
}
} else {
name = nameOrDid
did = await resolveNameWrapped(name)
didDoc = await resolveDidWrapped(did)
if (confirmName) {
const didsDeclaredName = 'undefined' // TODO: need to decide how username gets published in the did doc
nameIsCorrect = name === didsDeclaredName
}
}
// @TODO add back once we have a did network
// if (nameOrDid.startsWith('did:')) {
// did = nameOrDid
// didDoc = await resolveDidWrapped(did)
// name = 'undefined' // TODO: need to decide how username gets published in the did doc
// if (confirmName) {
// const namesDeclaredDid = await resolveNameWrapped(name)
// nameIsCorrect = did === namesDeclaredDid
// }
// } else {
// name = nameOrDid
// did = await resolveNameWrapped(name)
// didDoc = await resolveDidWrapped(did)
// if (confirmName) {
// const didsDeclaredName = 'undefined' // TODO: need to decide how username gets published in the did doc
// nameIsCorrect = name === didsDeclaredName
// }
// }
const db = util.getDB(res)
if (nameOrDid.startsWith('did:')) {
did = nameOrDid
const found = await db.getUsernameForDid(did)
if (found === null) {
throw new ServerError(404, 'Could not find username for did')
}
name = found
} else {
name = nameOrDid
const found = await db.getDidForUsername(name)
if (found === null) {
throw new ServerError(404, 'Could not find did for username')
}
did = found
}
didDoc = {} as any
nameIsCorrect = true
const collections = await db.listCollectionsForDid(did)
const resBody: DescribeRepoResponse = {
@ -195,7 +216,6 @@ router.get('/:nameOrDid', async (req, res) => {
collections,
nameIsCorrect,
}
res.status(200)
res.json(resBody)
})
@ -205,14 +225,31 @@ router.get('/:nameOrDid', async (req, res) => {
router.get('/:nameOrDid/c/:namespace/:dataset', async (req, res) => {
const { nameOrDid, namespace, dataset } = req.params
const coll = namespace + '/' + dataset
const { count = 50, from } = util.checkReqBody(req.query, listRecordsParams)
const {
limit = 50,
before,
after,
reverse = false,
} = util.checkReqBody(req.query, listRecordsParams)
const db = util.getDB(res)
const did = nameOrDid.startsWith('did:')
? nameOrDid
: await resolveNameWrapped(nameOrDid)
: await db.getDidForUsername(nameOrDid)
if (!did) {
throw new ServerError(404, `Could not find did for ${nameOrDid}`)
}
const records = await db.listRecordsForCollection(did, coll, count, from)
res.status(200).send(records)
const records = await db.listRecordsForCollection(
did,
coll,
limit,
reverse,
before,
after,
)
res.json({ records } as ListRecordsResponse)
})
// GET RECORD
@ -232,7 +269,7 @@ router.get('/:nameOrDid/c/:namespace/:dataset/r/:tid', async (req, res) => {
if (record === null) {
throw new ServerError(404, `Could not locate record: ${uri}`)
}
res.status(200).send(record)
res.json({ uri: uri.toString(), value: record } as GetRecordResponse)
})
export default router

@ -0,0 +1,256 @@
import { AdxClient, AdxUri } from '@adxp/api'
import { schemas } from '@adxp/microblog'
const url = 'http://localhost:2583'
const adx = new AdxClient({
pds: url,
schemas: schemas,
})
const alice = { username: 'alice', did: 'did:example:alice' }
const bob = { username: 'bob', did: 'did:example:bob' }
describe('crud operations', () => {
it('registers users', async () => {
await adx.mainPds.registerRepo(alice)
await adx.mainPds.registerRepo(bob)
})
it('describes repo', async () => {
const description = await adx.mainPds.repo(alice.did).describe()
expect(description.name).toBe(alice.username)
expect(description.did).toBe(alice.did)
const description2 = await adx.mainPds.repo(bob.did).describe()
expect(description2.name).toBe(bob.username)
expect(description2.did).toBe(bob.did)
})
let uri: AdxUri
it('creates records', async () => {
uri = await adx.mainPds
.repo(alice.did)
.collection('bsky/posts')
.create('*', {
$type: 'blueskyweb.xyz:Post',
text: 'Hello, world!',
createdAt: new Date().toISOString(),
})
expect(uri.toString()).toBe(
`adx://${alice.did}/bsky/posts/${uri.recordKey}`,
)
})
it('lists records', async () => {
const res = await adx.mainPds
.repo(alice.did)
.collection('bsky/posts')
.list('*')
expect(res.records.length).toBe(1)
expect(res.records[0].uri).toBe(uri.toString())
expect(res.records[0].value.text).toBe('Hello, world!')
})
it('gets records', async () => {
const res = await adx.mainPds
.repo(alice.did)
.collection('bsky/posts')
.get('*', uri.recordKey)
expect(res.uri).toBe(uri.toString())
expect(res.value.text).toBe('Hello, world!')
})
it('puts records', async () => {
const res = await adx.mainPds
.repo(alice.did)
.collection('bsky/posts')
.put('*', uri.recordKey, {
$type: 'blueskyweb.xyz:Post',
text: 'Hello, universe!',
createdAt: new Date().toISOString(),
})
expect(res.toString()).toBe(uri.toString())
const res2 = await adx.mainPds
.repo(alice.did)
.collection('bsky/posts')
.get('*', uri.recordKey)
expect(res2.uri).toBe(uri.toString())
expect(res2.value.text).toBe('Hello, universe!')
})
it('deletes records', async () => {
await adx.mainPds
.repo(alice.did)
.collection('bsky/posts')
.del(uri.recordKey)
const res = await adx.mainPds
.repo(alice.did)
.collection('bsky/posts')
.list('*')
expect(res.records.length).toBe(0)
})
it('lists records with pagination', async () => {
const feed = adx.mainPds.repo(alice.did).collection('bsky/posts')
const uri1 = await feed.create('Post', {
$type: 'blueskyweb.xyz:Post',
text: 'Post 1',
createdAt: new Date().toISOString(),
})
const uri2 = await feed.create('Post', {
$type: 'blueskyweb.xyz:Post',
text: 'Post 2',
createdAt: new Date().toISOString(),
})
const uri3 = await feed.create('Post', {
$type: 'blueskyweb.xyz:Post',
text: 'Post 3',
createdAt: new Date().toISOString(),
})
const uri4 = await feed.create('Post', {
$type: 'blueskyweb.xyz:Post',
text: 'Post 4',
createdAt: new Date().toISOString(),
})
{
const list = await feed.list('Post', { limit: 2 })
expect(list.records.length).toBe(2)
expect(list.records[0].value.text).toBe('Post 1')
expect(list.records[1].value.text).toBe('Post 2')
}
{
const list = await feed.list('Post', { limit: 2, reverse: true })
expect(list.records.length).toBe(2)
expect(list.records[0].value.text).toBe('Post 4')
expect(list.records[1].value.text).toBe('Post 3')
}
{
const list = await feed.list('Post', { after: uri2.recordKey })
expect(list.records.length).toBe(2)
expect(list.records[0].value.text).toBe('Post 3')
expect(list.records[1].value.text).toBe('Post 4')
}
{
const list = await feed.list('Post', { before: uri3.recordKey })
expect(list.records.length).toBe(2)
expect(list.records[0].value.text).toBe('Post 1')
expect(list.records[1].value.text).toBe('Post 2')
}
{
const list = await feed.list('Post', {
before: uri4.recordKey,
after: uri1.recordKey,
})
expect(list.records.length).toBe(2)
expect(list.records[0].value.text).toBe('Post 2')
expect(list.records[1].value.text).toBe('Post 3')
}
await feed.del(uri1.recordKey)
await feed.del(uri2.recordKey)
await feed.del(uri3.recordKey)
await feed.del(uri4.recordKey)
})
})
describe('validation', () => {
it('requires a $type on records', async () => {
const feed = adx.mainPds.repo(alice.did).collection('bsky/posts')
await expect(feed.create('Post', {})).rejects.toThrow(
'The passed value does not declare a $type',
)
await expect(feed.put('Post', 'foo', {})).rejects.toThrow(
'The passed value does not declare a $type',
)
})
it('requires the schema to be known', async () => {
const feed = adx.mainPds.repo(alice.did).collection('bsky/posts')
await expect(feed.list('Foobar')).rejects.toThrow(
'Schema not found: Foobar',
)
await expect(feed.create('Foobar', {})).rejects.toThrow(
'Schema not found: Foobar',
)
await expect(feed.put('Foobar', 'foo', {})).rejects.toThrow(
'Schema not found: Foobar',
)
})
it('requires the $type to match the schema', async () => {
const feed = adx.mainPds.repo(alice.did).collection('bsky/posts')
await expect(
feed.create('Post', { $type: 'blueskyweb.xyz:Like' }),
).rejects.toThrow('Record type blueskyweb.xyz:Like is not supported')
await expect(
feed.put('Post', 'foo', { $type: 'blueskyweb.xyz:Like' }),
).rejects.toThrow('Record type blueskyweb.xyz:Like is not supported')
})
it('validates the record on write', async () => {
const feed = adx.mainPds.repo(alice.did).collection('bsky/posts')
await expect(
feed.create('Post', { $type: 'blueskyweb.xyz:Post' }),
).rejects.toThrow(
"Failed blueskyweb.xyz:Post validation for #/required: must have required property 'text'",
)
await expect(
feed.put('Post', 'foo', { $type: 'blueskyweb.xyz:Post' }),
).rejects.toThrow(
"Failed blueskyweb.xyz:Post validation for #/required: must have required property 'text'",
)
})
it('validates the record on read', async () => {
const feed = adx.mainPds.repo(alice.did).collection('bsky/posts')
const uri1 = await feed.create(
'*',
{
$type: 'blueskyweb.xyz:Post',
record: 'is bad',
},
false,
)
const uri2 = await feed.create(
'*',
{
$type: 'blueskyweb.xyz:Unknown',
dunno: 'lol',
},
false,
)
const res1 = await feed.list('Post')
expect(res1.records[0].value.record).toBe('is bad')
expect(res1.records[0].valid).toBeFalsy()
expect(res1.records[0].fullySupported).toBeFalsy()
expect(res1.records[0].compatible).toBeTruthy()
expect(res1.records[0].error).toBe(
`Failed blueskyweb.xyz:Post validation for #/required: must have required property 'text'`,
)
expect(res1.records[1].value.dunno).toBe('lol')
expect(res1.records[1].valid).toBeFalsy()
expect(res1.records[1].fullySupported).toBeFalsy()
expect(res1.records[1].compatible).toBeFalsy()
expect(res1.records[1].error).toBe(
`Record type blueskyweb.xyz:Unknown is not supported`,
)
const res2 = await feed.get('Post', uri1.recordKey)
expect(res2.value.record).toBe('is bad')
expect(res2.valid).toBeFalsy()
expect(res2.fullySupported).toBeFalsy()
expect(res2.compatible).toBeTruthy()
expect(res2.error).toBe(
`Failed blueskyweb.xyz:Post validation for #/required: must have required property 'text'`,
)
const res3 = await feed.get('Post', uri2.recordKey)
expect(res3.value.dunno).toBe('lol')
expect(res3.valid).toBeFalsy()
expect(res3.fullySupported).toBeFalsy()
expect(res3.compatible).toBeFalsy()
expect(res3.error).toBe(
`Record type blueskyweb.xyz:Unknown is not supported`,
)
await feed.del(uri1.recordKey)
await feed.del(uri2.recordKey)
})
})

@ -1,112 +0,0 @@
import { MicroblogDelegator, Post, Like } from '@adxp/common'
import { CloseFn, newClient, runTestServer } from './_util'
const USE_TEST_SERVER = true
const PORT = 2583
const HOST = `localhost:${PORT}`
const SERVER_URL = `http://${HOST}`
describe('@TODO', () => {
it('does not run tests', () => {
expect(true)
})
})
// describe('delegator client', () => {
// let alice: MicroblogDelegator
// let bob: MicroblogDelegator
// let closeFn: CloseFn | undefined
// beforeAll(async () => {
// if (USE_TEST_SERVER) {
// closeFn = await runTestServer(PORT)
// }
// alice = await newClient(SERVER_URL)
// bob = await newClient(SERVER_URL)
// })
// afterAll(() => {
// if (closeFn) {
// closeFn()
// }
// })
// it('works', () => {
// expect(true)
// })
// it('registers id', async () => {
// await alice.register('alice')
// await bob.register('bob')
// })
// it('retrieves id', async () => {
// const did = await alice.lookupDid(`alice@${HOST}`)
// expect(did).toBe(alice.did)
// })
// let post: Post
// const postText = 'hello world!'
// it('creates post', async () => {
// post = await alice.addPost(postText)
// })
// it('gets post', async () => {
// const got = await alice.getPost(post.tid)
// expect(got?.text).toBe(postText)
// })
// it('edits post', async () => {
// const newText = 'howdy universe!'
// await alice.editPost(post.tid, newText)
// const got = await alice.getPost(post.tid)
// expect(got?.text).toBe(newText)
// })
// let like: Like
// it('creates like', async () => {
// like = await bob.likePost(alice.did, post.tid)
// })
// it('lists likes', async () => {
// const likes = await bob.listLikes(10)
// expect(likes.length).toBe(1)
// expect(likes[0].tid.toString()).toBe(like.tid.toString())
// expect(likes[0].post_tid.toString()).toBe(post.tid.toString())
// })
// it('deletes like', async () => {
// await bob.deleteLike(like.tid)
// const likes = await bob.listLikes(10)
// expect(likes.length).toBe(0)
// })
// it('deletes post', async () => {
// await alice.deletePost(post.tid)
// const got = await alice.getPost(post.tid)
// expect(got).toBe(null)
// })
// it('follows user', async () => {
// // register bob
// await alice.followUser(`bob@${HOST}`)
// })
// it('lists follows', async () => {
// const follows = await alice.listFollows()
// expect(follows.length).toBe(1)
// expect(follows[0].did).toBe(bob.did)
// expect(follows[0].username).toBe(`bob@${HOST}`)
// })
// it('unfollows user', async () => {
// await alice.unfollowUser(bob.did)
// const follows = await alice.listFollows()
// expect(follows.length).toBe(0)
// })
// })

@ -1,122 +0,0 @@
import { MicroblogDelegator, Post, TimelinePost } from '@adxp/common'
import { CloseFn, newClient, runTestServer } from './_util'
const USE_TEST_SERVER = true
const PORT_ONE = USE_TEST_SERVER ? 2585 : 2583
const HOST_ONE = `localhost:${PORT_ONE}`
const SERVER_ONE = `http://${HOST_ONE}`
const PORT_TWO = USE_TEST_SERVER ? 2586 : 2584
const HOST_TWO = `localhost:${PORT_TWO}`
const SERVER_TWO = `http://${HOST_TWO}`
process.env['DID_NETWORK_URL'] = `${SERVER_ONE}/did-network`
describe('@TODO', () => {
it('does not run tests', () => {
expect(true)
})
})
// describe('indexer', () => {
// let alice: MicroblogDelegator
// let bob: MicroblogDelegator
// let carol: MicroblogDelegator
// let dan: MicroblogDelegator
// let closeFn1, closeFn2: CloseFn | undefined
// beforeAll(async () => {
// if (USE_TEST_SERVER) {
// closeFn1 = await runTestServer(PORT_ONE)
// closeFn2 = await runTestServer(PORT_TWO)
// }
// alice = await newClient(SERVER_ONE)
// bob = await newClient(SERVER_ONE)
// carol = await newClient(SERVER_TWO)
// dan = await newClient(SERVER_TWO)
// await alice.register('alice')
// await bob.register('bob')
// await carol.register('carol')
// await dan.register('dan')
// })
// afterAll(async () => {
// if (closeFn1) {
// await closeFn1()
// }
// if (closeFn2) {
// await closeFn2()
// }
// })
// it('follow multiple users', async () => {
// await alice.followUser(`bob@${HOST_ONE}`)
// await alice.followUser(`carol@${HOST_TWO}`)
// await alice.followUser(`dan@${HOST_TWO}`)
// })
// it('populate the timeline', async () => {
// await bob.addPost('one')
// await bob.addPost('two')
// await carol.addPost('three')
// await dan.addPost('four')
// await carol.addPost('five')
// await bob.addPost('six')
// await dan.addPost('seven')
// await dan.addPost('eight')
// await carol.addPost('nine')
// await bob.addPost('ten')
// })
// it('get timeline', async () => {
// const timeline = await alice.retrieveTimeline(10)
// const timelineText = timeline.map((p: TimelinePost) => p.text)
// const expected = [
// 'ten',
// 'nine',
// 'eight',
// 'seven',
// 'six',
// 'five',
// 'four',
// 'three',
// 'two',
// 'one',
// ]
// expect(timelineText).toEqual(expected)
// })
// it('get old timeline', async () => {
// const timeline = await alice.retrieveTimeline(2)
// const lastSeen = timeline[1].tid
// const oldTimeline = await alice.retrieveTimeline(10, lastSeen)
// const timelineText = oldTimeline.map((p: TimelinePost) => p.text)
// const expected = [
// 'eight',
// 'seven',
// 'six',
// 'five',
// 'four',
// 'three',
// 'two',
// 'one',
// ]
// expect(timelineText).toEqual(expected)
// })
// let post: Post
// it('get some likes on your post', async () => {
// post = await alice.addPost('hello world!')
// const tid = post.tid
// await bob.likePost(alice.did, tid)
// await carol.likePost(alice.did, tid)
// await dan.likePost(alice.did, tid)
// })
// it('count likes on post', async () => {
// const count = await alice.likeCount(alice.did, post.tid)
// expect(count).toBe(3)
// })
// })