@evanp/activitypub-bot 0.13.0 → 0.13.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/.github/dependabot.yml +0 -11
- package/.github/workflows/main.yml +0 -34
- package/.github/workflows/tag.yml +0 -106
- package/.nvmrc +0 -1
- package/Dockerfile +0 -17
- package/docs/activitypub.bot.drawio +0 -110
- package/tests/activitydistributor.test.js +0 -606
- package/tests/activityhandler.test.js +0 -2276
- package/tests/activitypubclient.test.js +0 -210
- package/tests/actorstorage.test.js +0 -283
- package/tests/app.test.js +0 -17
- package/tests/authorizer.test.js +0 -301
- package/tests/bot.donothing.test.js +0 -30
- package/tests/bot.ok.test.js +0 -101
- package/tests/botcontext.test.js +0 -720
- package/tests/botdatastorage.test.js +0 -88
- package/tests/botfactory.provincebotfactory.test.js +0 -430
- package/tests/digester.test.js +0 -56
- package/tests/fixtures/bots.js +0 -27
- package/tests/fixtures/eventloggingbot.js +0 -57
- package/tests/fixtures/provincebotfactory.js +0 -53
- package/tests/httpsignature.test.js +0 -199
- package/tests/httpsignatureauthenticator.test.js +0 -463
- package/tests/index.test.js +0 -12
- package/tests/keystorage.test.js +0 -124
- package/tests/microsyntax.test.js +0 -123
- package/tests/objectcache.test.js +0 -133
- package/tests/objectstorage.test.js +0 -149
- package/tests/remotekeystorage.test.js +0 -78
- package/tests/routes.actor.test.js +0 -214
- package/tests/routes.collection.test.js +0 -310
- package/tests/routes.health.test.js +0 -41
- package/tests/routes.inbox.test.js +0 -216
- package/tests/routes.object.test.js +0 -525
- package/tests/routes.server.test.js +0 -69
- package/tests/routes.sharedinbox.test.js +0 -473
- package/tests/routes.webfinger.test.js +0 -68
- package/tests/urlformatter.test.js +0 -164
- package/tests/utils/digest.js +0 -7
- package/tests/utils/nock.js +0 -499
|
@@ -1,210 +0,0 @@
|
|
|
1
|
-
import { describe, before, after, it, beforeEach } from 'node:test'
|
|
2
|
-
import { KeyStorage } from '../lib/keystorage.js'
|
|
3
|
-
import { UrlFormatter } from '../lib/urlformatter.js'
|
|
4
|
-
import { ActivityPubClient } from '../lib/activitypubclient.js'
|
|
5
|
-
import assert from 'node:assert'
|
|
6
|
-
import { Sequelize } from 'sequelize'
|
|
7
|
-
import as2 from '../lib/activitystreams.js'
|
|
8
|
-
import Logger from 'pino'
|
|
9
|
-
import { HTTPSignature } from '../lib/httpsignature.js'
|
|
10
|
-
import { Digester } from '../lib/digester.js'
|
|
11
|
-
import { runMigrations } from '../lib/migrations/index.js'
|
|
12
|
-
import {
|
|
13
|
-
nockSetup,
|
|
14
|
-
getRequestHeaders,
|
|
15
|
-
resetRequestHeaders,
|
|
16
|
-
addToCollection,
|
|
17
|
-
nockFormat
|
|
18
|
-
} from './utils/nock.js'
|
|
19
|
-
|
|
20
|
-
describe('ActivityPubClient', async () => {
|
|
21
|
-
let connection = null
|
|
22
|
-
let keyStorage = null
|
|
23
|
-
let formatter = null
|
|
24
|
-
let client = null
|
|
25
|
-
let signer = null
|
|
26
|
-
let digester = null
|
|
27
|
-
let logger = null
|
|
28
|
-
const remoteUser = 'remote1'
|
|
29
|
-
const remoteCollection = 1
|
|
30
|
-
const remoteOrderedCollection = 2
|
|
31
|
-
const remotePagedCollection = 3
|
|
32
|
-
const remotePagedOrderedCollection = 4
|
|
33
|
-
const maxItems = 10
|
|
34
|
-
before(async () => {
|
|
35
|
-
logger = new Logger({
|
|
36
|
-
level: 'silent'
|
|
37
|
-
})
|
|
38
|
-
digester = new Digester(logger)
|
|
39
|
-
signer = new HTTPSignature(logger)
|
|
40
|
-
connection = new Sequelize({ dialect: 'sqlite', storage: ':memory:', logging: false })
|
|
41
|
-
await connection.authenticate()
|
|
42
|
-
await runMigrations(connection)
|
|
43
|
-
keyStorage = new KeyStorage(connection, logger)
|
|
44
|
-
formatter = new UrlFormatter('https://activitypubbot.example')
|
|
45
|
-
const remote = 'social.example'
|
|
46
|
-
nockSetup(remote, logger)
|
|
47
|
-
for (let i = 0; i < maxItems; i++) {
|
|
48
|
-
const id = nockFormat({ username: remoteUser, type: 'note', num: i })
|
|
49
|
-
addToCollection(remoteUser, remoteCollection, id, remote)
|
|
50
|
-
}
|
|
51
|
-
for (let i = maxItems; i < 2 * maxItems; i++) {
|
|
52
|
-
const id = nockFormat({ username: remoteUser, type: 'note', num: i })
|
|
53
|
-
addToCollection(remoteUser, remoteOrderedCollection, id, remote)
|
|
54
|
-
}
|
|
55
|
-
for (let i = 2 * maxItems; i < 7 * maxItems; i++) {
|
|
56
|
-
const id = nockFormat({ username: remoteUser, type: 'note', num: i })
|
|
57
|
-
addToCollection(remoteUser, remotePagedCollection, id, remote)
|
|
58
|
-
}
|
|
59
|
-
for (let i = 7 * maxItems; i < 12 * maxItems; i++) {
|
|
60
|
-
const id = nockFormat({ username: remoteUser, type: 'note', num: i })
|
|
61
|
-
addToCollection(remoteUser, remotePagedOrderedCollection, id, remote)
|
|
62
|
-
}
|
|
63
|
-
})
|
|
64
|
-
after(async () => {
|
|
65
|
-
await connection.close()
|
|
66
|
-
keyStorage = null
|
|
67
|
-
connection = null
|
|
68
|
-
formatter = null
|
|
69
|
-
client = null
|
|
70
|
-
logger = null
|
|
71
|
-
digester = null
|
|
72
|
-
signer = null
|
|
73
|
-
})
|
|
74
|
-
beforeEach(async () => {
|
|
75
|
-
resetRequestHeaders()
|
|
76
|
-
})
|
|
77
|
-
it('can initialize', () => {
|
|
78
|
-
client = new ActivityPubClient(keyStorage, formatter, signer, digester, logger)
|
|
79
|
-
assert.ok(client)
|
|
80
|
-
})
|
|
81
|
-
it('can get a remote object with a username', async () => {
|
|
82
|
-
const id = 'https://social.example/user/evan/note/1'
|
|
83
|
-
const obj = await client.get(id, 'foobot')
|
|
84
|
-
assert.ok(obj)
|
|
85
|
-
assert.equal(typeof obj, 'object')
|
|
86
|
-
assert.equal(obj.id, id)
|
|
87
|
-
const h = getRequestHeaders(id)
|
|
88
|
-
assert.ok(h.signature)
|
|
89
|
-
assert.match(h.signature, /^keyId="https:\/\/activitypubbot\.example\/user\/foobot\/publickey",headers="\(request-target\) host date user-agent accept",signature=".*",algorithm="rsa-sha256"$/)
|
|
90
|
-
assert.equal(typeof h.digest, 'undefined')
|
|
91
|
-
assert.equal(typeof h.date, 'string')
|
|
92
|
-
assert.match(h.date, /^\w{3}, \d{2} \w{3} \d{4} \d{2}:\d{2}:\d{2} GMT$/)
|
|
93
|
-
assert.doesNotThrow(() => {
|
|
94
|
-
Date.parse(h.date)
|
|
95
|
-
})
|
|
96
|
-
})
|
|
97
|
-
it('can get a remote object without a username', async () => {
|
|
98
|
-
const id = 'https://social.example/user/evan/note/1'
|
|
99
|
-
const obj = await client.get(id)
|
|
100
|
-
assert.ok(obj)
|
|
101
|
-
assert.equal(typeof obj, 'object')
|
|
102
|
-
assert.equal(obj.id, id)
|
|
103
|
-
const h = getRequestHeaders(id)
|
|
104
|
-
assert.ok(h.signature)
|
|
105
|
-
assert.match(h.signature, /^keyId="https:\/\/activitypubbot\.example\/publickey",headers="\(request-target\) host date user-agent accept",signature=".*",algorithm="rsa-sha256"$/)
|
|
106
|
-
assert.equal(typeof h.digest, 'undefined')
|
|
107
|
-
assert.equal(typeof h.date, 'string')
|
|
108
|
-
assert.match(h.date, /^\w{3}, \d{2} \w{3} \d{4} \d{2}:\d{2}:\d{2} GMT$/)
|
|
109
|
-
assert.doesNotThrow(() => {
|
|
110
|
-
Date.parse(h.date)
|
|
111
|
-
})
|
|
112
|
-
})
|
|
113
|
-
it('can get a remote key without a signature', async () => {
|
|
114
|
-
const id = 'https://social.example/user/evan/publickey'
|
|
115
|
-
const obj = await client.getKey(id)
|
|
116
|
-
assert.ok(obj)
|
|
117
|
-
assert.equal(typeof obj, 'object')
|
|
118
|
-
assert.equal(obj.id, id)
|
|
119
|
-
const h = getRequestHeaders(id)
|
|
120
|
-
assert.equal(h.signature, undefined)
|
|
121
|
-
assert.equal(typeof h.digest, 'undefined')
|
|
122
|
-
assert.equal(typeof h.date, 'string')
|
|
123
|
-
assert.match(h.date, /^\w{3}, \d{2} \w{3} \d{4} \d{2}:\d{2}:\d{2} GMT$/)
|
|
124
|
-
assert.doesNotThrow(() => {
|
|
125
|
-
Date.parse(h.date)
|
|
126
|
-
})
|
|
127
|
-
})
|
|
128
|
-
it('can deliver an activity', async () => {
|
|
129
|
-
const obj = as2.follow()
|
|
130
|
-
.actor('https://activitypubbot.example/user/foobot')
|
|
131
|
-
.object('https://social.example/user/evan')
|
|
132
|
-
.to('https://social.example/user/evan')
|
|
133
|
-
.publishedNow()
|
|
134
|
-
.get()
|
|
135
|
-
const inbox = 'https://social.example/user/evan/inbox'
|
|
136
|
-
await client.post(inbox, obj, 'foobot')
|
|
137
|
-
const h = getRequestHeaders(inbox)
|
|
138
|
-
assert.ok(h.signature)
|
|
139
|
-
assert.ok(h.digest)
|
|
140
|
-
assert.match(h.signature, /^keyId="https:\/\/activitypubbot\.example\/user\/foobot\/publickey",headers="\(request-target\) host date user-agent content-type digest",signature=".*",algorithm="rsa-sha256"$/)
|
|
141
|
-
assert.match(h.digest, /^sha-256=[0-9a-zA-Z=+/]*$/)
|
|
142
|
-
assert.equal(typeof h.date, 'string')
|
|
143
|
-
assert.match(h.date, /^\w{3}, \d{2} \w{3} \d{4} \d{2}:\d{2}:\d{2} GMT$/)
|
|
144
|
-
assert.doesNotThrow(() => {
|
|
145
|
-
Date.parse(h.date)
|
|
146
|
-
})
|
|
147
|
-
})
|
|
148
|
-
it('throws an error on a non-2xx response', async () => {
|
|
149
|
-
const inbox = 'https://social.example/user/evan/inbox'
|
|
150
|
-
try {
|
|
151
|
-
await client.get(inbox, 'foobot')
|
|
152
|
-
assert.fail('should have thrown')
|
|
153
|
-
} catch (error) {
|
|
154
|
-
assert.ok(error)
|
|
155
|
-
assert.equal(error.status, 403)
|
|
156
|
-
}
|
|
157
|
-
})
|
|
158
|
-
it('can iterate over a Collection', async () => {
|
|
159
|
-
const collectionUri = nockFormat({
|
|
160
|
-
username: remoteUser,
|
|
161
|
-
type: 'Collection',
|
|
162
|
-
num: remoteCollection
|
|
163
|
-
})
|
|
164
|
-
let counter = 0
|
|
165
|
-
for await (const item of client.items(collectionUri)) {
|
|
166
|
-
assert.ok(item)
|
|
167
|
-
counter = counter + 1
|
|
168
|
-
}
|
|
169
|
-
assert.strictEqual(counter, maxItems)
|
|
170
|
-
})
|
|
171
|
-
it('can iterate over an OrderedCollection', async () => {
|
|
172
|
-
const collectionUri = nockFormat({
|
|
173
|
-
username: remoteUser,
|
|
174
|
-
type: 'OrderedCollection',
|
|
175
|
-
num: remoteOrderedCollection
|
|
176
|
-
})
|
|
177
|
-
let counter = 0
|
|
178
|
-
for await (const item of client.items(collectionUri)) {
|
|
179
|
-
assert.ok(item)
|
|
180
|
-
counter = counter + 1
|
|
181
|
-
}
|
|
182
|
-
assert.strictEqual(counter, maxItems)
|
|
183
|
-
})
|
|
184
|
-
it('can iterate over a paged Collection', async () => {
|
|
185
|
-
const collectionUri = nockFormat({
|
|
186
|
-
username: remoteUser,
|
|
187
|
-
type: 'PagedCollection', // Fake type
|
|
188
|
-
num: remotePagedCollection
|
|
189
|
-
})
|
|
190
|
-
let counter = 0
|
|
191
|
-
for await (const item of client.items(collectionUri)) {
|
|
192
|
-
assert.ok(item)
|
|
193
|
-
counter = counter + 1
|
|
194
|
-
}
|
|
195
|
-
assert.strictEqual(counter, 5 * maxItems)
|
|
196
|
-
})
|
|
197
|
-
it('can iterate over a paged OrderedCollection', async () => {
|
|
198
|
-
const collectionUri = nockFormat({
|
|
199
|
-
username: remoteUser,
|
|
200
|
-
type: 'PagedOrderedCollection', // Fake type
|
|
201
|
-
num: remotePagedOrderedCollection
|
|
202
|
-
})
|
|
203
|
-
let counter = 0
|
|
204
|
-
for await (const item of client.items(collectionUri)) {
|
|
205
|
-
assert.ok(item)
|
|
206
|
-
counter = counter + 1
|
|
207
|
-
}
|
|
208
|
-
assert.strictEqual(counter, 5 * maxItems)
|
|
209
|
-
})
|
|
210
|
-
})
|
|
@@ -1,283 +0,0 @@
|
|
|
1
|
-
import { describe, it, before, after } from 'node:test'
|
|
2
|
-
import assert from 'node:assert'
|
|
3
|
-
import { ActorStorage } from '../lib/actorstorage.js'
|
|
4
|
-
import { Sequelize } from 'sequelize'
|
|
5
|
-
import { UrlFormatter } from '../lib/urlformatter.js'
|
|
6
|
-
import as2 from '../lib/activitystreams.js'
|
|
7
|
-
import { runMigrations } from '../lib/migrations/index.js'
|
|
8
|
-
|
|
9
|
-
const AS2_NS = 'https://www.w3.org/ns/activitystreams#'
|
|
10
|
-
|
|
11
|
-
describe('ActorStorage', () => {
|
|
12
|
-
let connection = null
|
|
13
|
-
let storage = null
|
|
14
|
-
let formatter = null
|
|
15
|
-
let other = null
|
|
16
|
-
let unfollowed = null
|
|
17
|
-
before(async () => {
|
|
18
|
-
connection = new Sequelize({ dialect: 'sqlite', storage: ':memory:', logging: false })
|
|
19
|
-
await connection.authenticate()
|
|
20
|
-
await runMigrations(connection)
|
|
21
|
-
formatter = new UrlFormatter('https://activitypubbot.example')
|
|
22
|
-
other = await as2.import({
|
|
23
|
-
id: 'https://social.example/user/test2',
|
|
24
|
-
type: 'Person'
|
|
25
|
-
})
|
|
26
|
-
unfollowed = await as2.import({
|
|
27
|
-
id: 'https://social.example/user/test3',
|
|
28
|
-
type: 'Person'
|
|
29
|
-
})
|
|
30
|
-
})
|
|
31
|
-
after(async () => {
|
|
32
|
-
await connection.close()
|
|
33
|
-
connection = null
|
|
34
|
-
formatter = null
|
|
35
|
-
})
|
|
36
|
-
it('can create an instance', () => {
|
|
37
|
-
storage = new ActorStorage(connection, formatter)
|
|
38
|
-
assert.ok(storage instanceof ActorStorage)
|
|
39
|
-
})
|
|
40
|
-
it('can initialize the storage', async () => {
|
|
41
|
-
})
|
|
42
|
-
it('can get an actor', async () => {
|
|
43
|
-
const actor = await storage.getActor('test')
|
|
44
|
-
assert.ok(actor)
|
|
45
|
-
assert.ok(actor.id)
|
|
46
|
-
assert.ok(actor.inbox)
|
|
47
|
-
assert.ok(actor.outbox)
|
|
48
|
-
assert.ok(actor.followers)
|
|
49
|
-
assert.ok(actor.following)
|
|
50
|
-
assert.ok(actor.liked)
|
|
51
|
-
assert.strictEqual(actor.get('preferredUsername').first, 'test')
|
|
52
|
-
})
|
|
53
|
-
|
|
54
|
-
it('can get an actor by id', async () => {
|
|
55
|
-
const actor = await storage.getActorById('https://activitypubbot.example/user/test')
|
|
56
|
-
assert.ok(actor)
|
|
57
|
-
assert.ok(actor.id)
|
|
58
|
-
assert.ok(actor.inbox)
|
|
59
|
-
assert.ok(actor.outbox)
|
|
60
|
-
assert.ok(actor.followers)
|
|
61
|
-
assert.ok(actor.following)
|
|
62
|
-
assert.ok(actor.liked)
|
|
63
|
-
assert.strictEqual(actor.get('preferredUsername').first, 'test')
|
|
64
|
-
})
|
|
65
|
-
it('can get an empty collection', async () => {
|
|
66
|
-
const collection = await storage.getCollection('test', 'followers')
|
|
67
|
-
assert.ok(collection)
|
|
68
|
-
assert.strictEqual(collection.id, 'https://activitypubbot.example/user/test/followers')
|
|
69
|
-
assert.strictEqual(collection.type, 'https://www.w3.org/ns/activitystreams#OrderedCollection')
|
|
70
|
-
assert.strictEqual(collection.totalItems, 0)
|
|
71
|
-
assert.ok(collection.first)
|
|
72
|
-
assert.ok(collection.last)
|
|
73
|
-
})
|
|
74
|
-
it('can get an empty collection page', async () => {
|
|
75
|
-
const page = await storage.getCollectionPage('test', 'followers', 1)
|
|
76
|
-
assert.ok(page)
|
|
77
|
-
assert.strictEqual(
|
|
78
|
-
page.id,
|
|
79
|
-
'https://activitypubbot.example/user/test/followers/1'
|
|
80
|
-
)
|
|
81
|
-
assert.strictEqual(page.type, 'https://www.w3.org/ns/activitystreams#OrderedCollectionPage')
|
|
82
|
-
assert.strictEqual(
|
|
83
|
-
page.partOf.id,
|
|
84
|
-
'https://activitypubbot.example/user/test/followers'
|
|
85
|
-
)
|
|
86
|
-
assert.ok(!page.next)
|
|
87
|
-
assert.ok(!page.prev)
|
|
88
|
-
})
|
|
89
|
-
it('can add to a collection', async () => {
|
|
90
|
-
const collection = await storage.getCollection('test3', 'followers')
|
|
91
|
-
assert.strictEqual(collection.totalItems, 0)
|
|
92
|
-
await storage.addToCollection(
|
|
93
|
-
'test3',
|
|
94
|
-
'followers',
|
|
95
|
-
other
|
|
96
|
-
)
|
|
97
|
-
const collection2 = await storage.getCollection('test3', 'followers')
|
|
98
|
-
assert.strictEqual(collection2.totalItems, 1)
|
|
99
|
-
const page = await storage.getCollectionPage('test3', 'followers', 1)
|
|
100
|
-
assert.strictEqual(page.items.length, 1)
|
|
101
|
-
assert.strictEqual(Array.from(page.items)[0].id, 'https://social.example/user/test2')
|
|
102
|
-
})
|
|
103
|
-
it('can remove from a collection', async () => {
|
|
104
|
-
await storage.removeFromCollection(
|
|
105
|
-
'test3',
|
|
106
|
-
'followers',
|
|
107
|
-
other
|
|
108
|
-
)
|
|
109
|
-
const collection2 = await storage.getCollection('test3', 'followers')
|
|
110
|
-
assert.strictEqual(collection2.totalItems, 0)
|
|
111
|
-
const page = await storage.getCollectionPage('test3', 'followers', 1)
|
|
112
|
-
assert.ok(!page.items)
|
|
113
|
-
})
|
|
114
|
-
it('can add a lot of items a collection', async () => {
|
|
115
|
-
for (let i = 0; i < 100; i++) {
|
|
116
|
-
const other = await as2.import({
|
|
117
|
-
id: `https://social.example/user/foo/note/${i}`,
|
|
118
|
-
type: 'Note',
|
|
119
|
-
content: `Hello World ${i}`
|
|
120
|
-
})
|
|
121
|
-
await storage.addToCollection(
|
|
122
|
-
'test4',
|
|
123
|
-
'liked',
|
|
124
|
-
other
|
|
125
|
-
)
|
|
126
|
-
}
|
|
127
|
-
const collection = await storage.getCollection('test4', 'liked')
|
|
128
|
-
assert.strictEqual(collection.totalItems, 100)
|
|
129
|
-
const page = await storage.getCollectionPage('test4', 'liked', 3)
|
|
130
|
-
assert.strictEqual(page.items.length, 20)
|
|
131
|
-
assert.strictEqual(page.next.id, 'https://activitypubbot.example/user/test4/liked/2')
|
|
132
|
-
})
|
|
133
|
-
it('can iterate over a collection', async () => {
|
|
134
|
-
const seen = new Set()
|
|
135
|
-
for await (const item of storage.items('test4', 'liked')) {
|
|
136
|
-
assert.ok(!(item.id in seen))
|
|
137
|
-
seen.add(item.id)
|
|
138
|
-
}
|
|
139
|
-
assert.strictEqual(seen.size, 100)
|
|
140
|
-
})
|
|
141
|
-
it('can add twice and remove once from a collection', async () => {
|
|
142
|
-
const other = await as2.import({
|
|
143
|
-
id: 'https://social.example/user/foo/note/200',
|
|
144
|
-
type: 'Note',
|
|
145
|
-
content: 'Hello World 200'
|
|
146
|
-
})
|
|
147
|
-
const other2 = await as2.import({
|
|
148
|
-
id: 'https://social.example/user/foo/note/201',
|
|
149
|
-
type: 'Note',
|
|
150
|
-
content: 'Hello World 201'
|
|
151
|
-
})
|
|
152
|
-
const collection = await storage.getCollection('test5', 'liked')
|
|
153
|
-
assert.strictEqual(collection.totalItems, 0)
|
|
154
|
-
await storage.addToCollection(
|
|
155
|
-
'test5',
|
|
156
|
-
'liked',
|
|
157
|
-
other
|
|
158
|
-
)
|
|
159
|
-
await storage.addToCollection(
|
|
160
|
-
'test5',
|
|
161
|
-
'liked',
|
|
162
|
-
other2
|
|
163
|
-
)
|
|
164
|
-
const collection2 = await storage.getCollection('test5', 'liked')
|
|
165
|
-
assert.strictEqual(collection2.totalItems, 2)
|
|
166
|
-
await storage.removeFromCollection(
|
|
167
|
-
'test5',
|
|
168
|
-
'liked',
|
|
169
|
-
other
|
|
170
|
-
)
|
|
171
|
-
const collection3 = await storage.getCollection('test5', 'liked')
|
|
172
|
-
assert.strictEqual(collection3.totalItems, 1)
|
|
173
|
-
})
|
|
174
|
-
it('can check if something is in the collection', async () => {
|
|
175
|
-
const other = await as2.import({
|
|
176
|
-
id: 'https://social.example/user/foo/note/300',
|
|
177
|
-
type: 'Note',
|
|
178
|
-
content: 'Hello World 300'
|
|
179
|
-
})
|
|
180
|
-
const other2 = await as2.import({
|
|
181
|
-
id: 'https://social.example/user/foo/note/301',
|
|
182
|
-
type: 'Note',
|
|
183
|
-
content: 'Hello World 301'
|
|
184
|
-
})
|
|
185
|
-
let collection = await storage.getCollection('test6', 'liked')
|
|
186
|
-
assert.strictEqual(collection.totalItems, 0)
|
|
187
|
-
await storage.addToCollection(
|
|
188
|
-
'test6',
|
|
189
|
-
'liked',
|
|
190
|
-
other
|
|
191
|
-
)
|
|
192
|
-
collection = await storage.getCollection('test6', 'liked')
|
|
193
|
-
assert.strictEqual(collection.totalItems, 1)
|
|
194
|
-
assert.ok(await storage.isInCollection(
|
|
195
|
-
'test6',
|
|
196
|
-
'liked',
|
|
197
|
-
other
|
|
198
|
-
))
|
|
199
|
-
assert.ok(!await storage.isInCollection(
|
|
200
|
-
'test6',
|
|
201
|
-
'liked',
|
|
202
|
-
other2
|
|
203
|
-
))
|
|
204
|
-
})
|
|
205
|
-
|
|
206
|
-
it('retains totalItems when we remove an absent object', async () => {
|
|
207
|
-
const other = await as2.import({
|
|
208
|
-
id: 'https://social.example/user/foo/note/400',
|
|
209
|
-
type: 'Note',
|
|
210
|
-
content: 'Hello World 400'
|
|
211
|
-
})
|
|
212
|
-
const other2 = await as2.import({
|
|
213
|
-
id: 'https://social.example/user/foo/note/401',
|
|
214
|
-
type: 'Note',
|
|
215
|
-
content: 'Hello World 401'
|
|
216
|
-
})
|
|
217
|
-
const other3 = await as2.import({
|
|
218
|
-
id: 'https://social.example/user/foo/note/402',
|
|
219
|
-
type: 'Note',
|
|
220
|
-
content: 'Hello World 402'
|
|
221
|
-
})
|
|
222
|
-
let collection = await storage.getCollection('test7', 'liked')
|
|
223
|
-
assert.strictEqual(collection.totalItems, 0)
|
|
224
|
-
await storage.addToCollection(
|
|
225
|
-
'test7',
|
|
226
|
-
'liked',
|
|
227
|
-
other
|
|
228
|
-
)
|
|
229
|
-
await storage.addToCollection(
|
|
230
|
-
'test7',
|
|
231
|
-
'liked',
|
|
232
|
-
other2
|
|
233
|
-
)
|
|
234
|
-
collection = await storage.getCollection('test7', 'liked')
|
|
235
|
-
assert.strictEqual(collection.totalItems, 2)
|
|
236
|
-
await storage.removeFromCollection(
|
|
237
|
-
'test7',
|
|
238
|
-
'liked',
|
|
239
|
-
other3
|
|
240
|
-
)
|
|
241
|
-
collection = await storage.getCollection('test7', 'liked')
|
|
242
|
-
assert.strictEqual(collection.totalItems, 2)
|
|
243
|
-
})
|
|
244
|
-
it('can get an actor with custom properties', async () => {
|
|
245
|
-
const props = {
|
|
246
|
-
name: 'Test User',
|
|
247
|
-
summary: 'A test user',
|
|
248
|
-
type: 'Person'
|
|
249
|
-
}
|
|
250
|
-
const actor = await storage.getActor('test8', props)
|
|
251
|
-
assert.ok(actor)
|
|
252
|
-
assert.ok(actor.id)
|
|
253
|
-
assert.ok(actor.inbox)
|
|
254
|
-
assert.ok(actor.outbox)
|
|
255
|
-
assert.ok(actor.followers)
|
|
256
|
-
assert.ok(actor.following)
|
|
257
|
-
assert.ok(actor.liked)
|
|
258
|
-
assert.strictEqual(actor.get('preferredUsername').first, 'test8')
|
|
259
|
-
assert.strictEqual(actor.name.get(), 'Test User')
|
|
260
|
-
assert.strictEqual(actor.summary.get(), 'A test user')
|
|
261
|
-
assert.ok(Array.isArray(actor.type))
|
|
262
|
-
assert.ok(actor.type.includes(AS2_NS + 'Person'))
|
|
263
|
-
assert.ok(actor.type.includes(AS2_NS + 'Service'))
|
|
264
|
-
})
|
|
265
|
-
|
|
266
|
-
it('can get all actors with an object in a collection', async () => {
|
|
267
|
-
for (const i of [101, 102, 103, 104, 105]) {
|
|
268
|
-
await storage.addToCollection(`test${i}`, 'following', other)
|
|
269
|
-
}
|
|
270
|
-
const usernames = await storage.getUsernamesWith('following', other)
|
|
271
|
-
assert.strictEqual(usernames.length, 5)
|
|
272
|
-
assert.ok(usernames.includes('test101'))
|
|
273
|
-
assert.ok(usernames.includes('test102'))
|
|
274
|
-
assert.ok(usernames.includes('test103'))
|
|
275
|
-
assert.ok(usernames.includes('test104'))
|
|
276
|
-
assert.ok(usernames.includes('test105'))
|
|
277
|
-
})
|
|
278
|
-
|
|
279
|
-
it('gets zero usernames when an object is in no collection', async () => {
|
|
280
|
-
const usernames = await storage.getUsernamesWith('following', unfollowed)
|
|
281
|
-
assert.strictEqual(usernames.length, 0)
|
|
282
|
-
})
|
|
283
|
-
})
|
package/tests/app.test.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { describe, it } from 'node:test'
|
|
2
|
-
import assert from 'node:assert'
|
|
3
|
-
import { makeApp } from '../lib/app.js'
|
|
4
|
-
import bots from './fixtures/bots.js'
|
|
5
|
-
|
|
6
|
-
describe('app', async () => {
|
|
7
|
-
const databaseUrl = 'sqlite::memory:'
|
|
8
|
-
const origin = 'https://activitypubbot.test'
|
|
9
|
-
let app = null
|
|
10
|
-
it('should be a function', async () => {
|
|
11
|
-
assert.strictEqual(typeof makeApp, 'function')
|
|
12
|
-
})
|
|
13
|
-
it('should return a function', async () => {
|
|
14
|
-
app = await makeApp(databaseUrl, origin, bots, 'silent')
|
|
15
|
-
assert.strictEqual(typeof app, 'function')
|
|
16
|
-
})
|
|
17
|
-
})
|