@atproto/pds 0.4.217 → 0.4.219
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/CHANGELOG.md +32 -0
- package/dist/account-manager/oauth-store.d.ts.map +1 -1
- package/dist/account-manager/oauth-store.js +1 -1
- package/dist/account-manager/oauth-store.js.map +1 -1
- package/dist/actor-store/blob/transactor.d.ts +6 -6
- package/dist/actor-store/blob/transactor.d.ts.map +1 -1
- package/dist/actor-store/blob/transactor.js +1 -4
- package/dist/actor-store/blob/transactor.js.map +1 -1
- package/dist/api/com/atproto/repo/importRepo.js +1 -1
- package/dist/api/com/atproto/repo/importRepo.js.map +1 -1
- package/dist/api/com/atproto/repo/putRecord.js.map +1 -1
- package/dist/config/config.d.ts.map +1 -1
- package/dist/config/config.js +7 -3
- package/dist/config/config.js.map +1 -1
- package/dist/config/env.d.ts +4 -0
- package/dist/config/env.d.ts.map +1 -1
- package/dist/config/env.js +4 -0
- package/dist/config/env.js.map +1 -1
- package/dist/lexicons/app/bsky/actor/defs.defs.d.ts +1 -0
- package/dist/lexicons/app/bsky/actor/defs.defs.d.ts.map +1 -1
- package/dist/lexicons/app/bsky/actor/defs.defs.js +1 -0
- package/dist/lexicons/app/bsky/actor/defs.defs.js.map +1 -1
- package/dist/lexicons/app/bsky/actor/profile.defs.d.ts.map +1 -1
- package/dist/lexicons/app/bsky/actor/profile.defs.js +2 -10
- package/dist/lexicons/app/bsky/actor/profile.defs.js.map +1 -1
- package/dist/lexicons/app/bsky/embed/external.defs.d.ts.map +1 -1
- package/dist/lexicons/app/bsky/embed/external.defs.js +1 -1
- package/dist/lexicons/app/bsky/embed/external.defs.js.map +1 -1
- package/dist/lexicons/app/bsky/embed/images.defs.d.ts +3 -0
- package/dist/lexicons/app/bsky/embed/images.defs.d.ts.map +1 -1
- package/dist/lexicons/app/bsky/embed/images.defs.js +1 -5
- package/dist/lexicons/app/bsky/embed/images.defs.js.map +1 -1
- package/dist/lexicons/app/bsky/embed/video.defs.d.ts.map +1 -1
- package/dist/lexicons/app/bsky/embed/video.defs.js +2 -6
- package/dist/lexicons/app/bsky/embed/video.defs.js.map +1 -1
- package/dist/lexicons/app/bsky/feed/generator.defs.d.ts.map +1 -1
- package/dist/lexicons/app/bsky/feed/generator.defs.js +1 -5
- package/dist/lexicons/app/bsky/feed/generator.defs.js.map +1 -1
- package/dist/lexicons/app/bsky/graph/list.defs.d.ts.map +1 -1
- package/dist/lexicons/app/bsky/graph/list.defs.js +1 -5
- package/dist/lexicons/app/bsky/graph/list.defs.js.map +1 -1
- package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForDiscover.d.ts +3 -0
- package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForDiscover.d.ts.map +1 -0
- package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForDiscover.defs.d.ts +22 -0
- package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForDiscover.defs.d.ts.map +1 -0
- package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForDiscover.defs.js +53 -0
- package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForDiscover.defs.js.map +1 -0
- package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForDiscover.js +45 -0
- package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForDiscover.js.map +1 -0
- package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForDiscoverSkeleton.d.ts +3 -0
- package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForDiscoverSkeleton.d.ts.map +1 -0
- package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForDiscoverSkeleton.defs.d.ts +31 -0
- package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForDiscoverSkeleton.defs.d.ts.map +1 -0
- package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForDiscoverSkeleton.defs.js +20 -0
- package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForDiscoverSkeleton.defs.js.map +1 -0
- package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForDiscoverSkeleton.js +45 -0
- package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForDiscoverSkeleton.js.map +1 -0
- package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForExplore.d.ts +3 -0
- package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForExplore.d.ts.map +1 -0
- package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForExplore.defs.d.ts +24 -0
- package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForExplore.defs.d.ts.map +1 -0
- package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForExplore.defs.js +54 -0
- package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForExplore.defs.js.map +1 -0
- package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForExplore.js +45 -0
- package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForExplore.js.map +1 -0
- package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForExploreSkeleton.d.ts +3 -0
- package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForExploreSkeleton.d.ts.map +1 -0
- package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForExploreSkeleton.defs.d.ts +33 -0
- package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForExploreSkeleton.defs.d.ts.map +1 -0
- package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForExploreSkeleton.defs.js +21 -0
- package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForExploreSkeleton.defs.js.map +1 -0
- package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForExploreSkeleton.js +45 -0
- package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForExploreSkeleton.js.map +1 -0
- package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForSeeMore.d.ts +3 -0
- package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForSeeMore.d.ts.map +1 -0
- package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForSeeMore.defs.d.ts +24 -0
- package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForSeeMore.defs.d.ts.map +1 -0
- package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForSeeMore.defs.js +54 -0
- package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForSeeMore.defs.js.map +1 -0
- package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForSeeMore.js +45 -0
- package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForSeeMore.js.map +1 -0
- package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForSeeMoreSkeleton.d.ts +3 -0
- package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForSeeMoreSkeleton.d.ts.map +1 -0
- package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForSeeMoreSkeleton.defs.d.ts +33 -0
- package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForSeeMoreSkeleton.defs.d.ts.map +1 -0
- package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForSeeMoreSkeleton.defs.js +21 -0
- package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForSeeMoreSkeleton.defs.js.map +1 -0
- package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForSeeMoreSkeleton.js +45 -0
- package/dist/lexicons/app/bsky/unspecced/getSuggestedUsersForSeeMoreSkeleton.js.map +1 -0
- package/dist/lexicons/app/bsky/unspecced.d.ts +6 -0
- package/dist/lexicons/app/bsky/unspecced.d.ts.map +1 -1
- package/dist/lexicons/app/bsky/unspecced.js +7 -1
- package/dist/lexicons/app/bsky/unspecced.js.map +1 -1
- package/dist/lexicons/app/bsky/video/defs.defs.js +1 -1
- package/dist/lexicons/app/bsky/video/defs.defs.js.map +1 -1
- package/dist/lexicons/com/atproto/repo/uploadBlob.defs.d.ts +2 -6
- package/dist/lexicons/com/atproto/repo/uploadBlob.defs.d.ts.map +1 -1
- package/dist/lexicons/com/atproto/repo/uploadBlob.defs.js +1 -1
- package/dist/lexicons/com/atproto/repo/uploadBlob.defs.js.map +1 -1
- package/dist/pipethrough.d.ts.map +1 -1
- package/dist/pipethrough.js +11 -7
- package/dist/pipethrough.js.map +1 -1
- package/dist/read-after-write/viewer.d.ts.map +1 -1
- package/dist/read-after-write/viewer.js +7 -6
- package/dist/read-after-write/viewer.js.map +1 -1
- package/dist/repo/prepare.d.ts.map +1 -1
- package/dist/repo/prepare.js.map +1 -1
- package/dist/repo/types.d.ts +3 -3
- package/dist/repo/types.d.ts.map +1 -1
- package/dist/repo/types.js.map +1 -1
- package/package.json +13 -13
- package/src/account-manager/oauth-store.ts +2 -1
- package/src/actor-store/blob/transactor.ts +9 -15
- package/src/api/com/atproto/repo/importRepo.ts +1 -1
- package/src/api/com/atproto/repo/putRecord.ts +2 -2
- package/src/config/config.ts +13 -3
- package/src/config/env.ts +4 -0
- package/src/pipethrough.ts +15 -5
- package/src/read-after-write/viewer.ts +10 -7
- package/src/repo/prepare.ts +2 -2
- package/src/repo/types.ts +3 -3
- package/tests/_oauth_client_assets_middleware.ts +23 -0
- package/tests/_puppeteer.ts +71 -17
- package/tests/file-uploads.test.ts +17 -9
- package/tests/oauth.test.ts +52 -115
- package/tsconfig.build.tsbuildinfo +1 -1
package/tests/_puppeteer.ts
CHANGED
|
@@ -1,27 +1,71 @@
|
|
|
1
1
|
import assert from 'node:assert'
|
|
2
|
-
import { type Browser, type Page } from 'puppeteer'
|
|
2
|
+
import { type Browser, Handler, type Page, Target, TargetType } from 'puppeteer'
|
|
3
3
|
|
|
4
4
|
export class PageHelper implements AsyncDisposable {
|
|
5
5
|
constructor(protected readonly page: Page) {}
|
|
6
6
|
|
|
7
|
-
async goto(url: string) {
|
|
8
|
-
await this.page.goto(url)
|
|
7
|
+
async goto(url: string | URL) {
|
|
8
|
+
await this.page.goto(url.toString())
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
isClosed() {
|
|
12
|
+
return this.page.isClosed()
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
async title() {
|
|
16
|
+
await this.waitForNetworkIdle()
|
|
17
|
+
return this.page.title()
|
|
9
18
|
}
|
|
10
19
|
|
|
11
20
|
async waitForNetworkIdle() {
|
|
12
21
|
await this.page.waitForNetworkIdle()
|
|
13
22
|
}
|
|
14
23
|
|
|
15
|
-
async
|
|
16
|
-
const
|
|
24
|
+
async waitForPopup(run: () => Promise<unknown>): Promise<PageHelper> {
|
|
25
|
+
const browser = this.page.browser()
|
|
26
|
+
const popupPromise = new Promise<Page | null>((resolve, reject) => {
|
|
27
|
+
const cleanup = () => {
|
|
28
|
+
clearTimeout(timeout)
|
|
29
|
+
browser.off('targetcreated', targetcreated)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const timeout = setTimeout(() => {
|
|
33
|
+
cleanup()
|
|
34
|
+
reject(new Error('Timeout waiting for popup'))
|
|
35
|
+
}, 5_000)
|
|
36
|
+
|
|
37
|
+
const targetcreated: Handler<Target> = async (target) => {
|
|
38
|
+
switch (target.type()) {
|
|
39
|
+
case TargetType.BACKGROUND_PAGE:
|
|
40
|
+
case TargetType.PAGE: {
|
|
41
|
+
cleanup()
|
|
42
|
+
resolve(target.page())
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
browser.once('targetcreated', targetcreated)
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
await run()
|
|
51
|
+
const popup = await popupPromise
|
|
52
|
+
assert(popup, 'Popup page not found')
|
|
53
|
+
|
|
54
|
+
return new PageHelper(popup)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async navigationAction(run: () => unknown | Promise<unknown>): Promise<void> {
|
|
58
|
+
const promise = this.page.waitForNavigation({ timeout: 10_000 })
|
|
17
59
|
await run()
|
|
18
60
|
await promise
|
|
19
|
-
await this.waitForNetworkIdle()
|
|
20
61
|
}
|
|
21
62
|
|
|
22
|
-
async
|
|
23
|
-
|
|
24
|
-
|
|
63
|
+
async navigationClick(text: string, tag = 'button') {
|
|
64
|
+
return this.navigationAction(() => this.clickOnText(text, tag))
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async assertTitle(expected: string) {
|
|
68
|
+
await expect(this.title()).resolves.toBe(expected)
|
|
25
69
|
}
|
|
26
70
|
|
|
27
71
|
async clickOn(selector: string) {
|
|
@@ -30,8 +74,12 @@ export class PageHelper implements AsyncDisposable {
|
|
|
30
74
|
return elementHandle
|
|
31
75
|
}
|
|
32
76
|
|
|
33
|
-
async
|
|
34
|
-
return this.clickOn(
|
|
77
|
+
async clickOnText(text: string, tag = 'button') {
|
|
78
|
+
return this.clickOn(`${tag}::-p-text(${JSON.stringify(text)})`)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
async clickOnAriaLabel(label: string, tag = 'button') {
|
|
82
|
+
return this.clickOn(`${tag}[aria-label=${JSON.stringify(label)}]`)
|
|
35
83
|
}
|
|
36
84
|
|
|
37
85
|
async typeIn(selector: string, text: string) {
|
|
@@ -46,16 +94,22 @@ export class PageHelper implements AsyncDisposable {
|
|
|
46
94
|
}
|
|
47
95
|
|
|
48
96
|
async ensureTextVisibility(text: string, tag = 'p') {
|
|
49
|
-
await this.page.waitForSelector(
|
|
97
|
+
await this.page.waitForSelector(
|
|
98
|
+
`${tag}::-p-text(${JSON.stringify(text)})`,
|
|
99
|
+
{
|
|
100
|
+
visible: true,
|
|
101
|
+
timeout: 5_000,
|
|
102
|
+
},
|
|
103
|
+
)
|
|
50
104
|
}
|
|
51
105
|
|
|
52
106
|
protected async getVisibleElement(selector: string) {
|
|
53
|
-
const elementHandle = await this.page.waitForSelector(selector
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
107
|
+
const elementHandle = await this.page.waitForSelector(selector, {
|
|
108
|
+
visible: true,
|
|
109
|
+
timeout: 5_000,
|
|
110
|
+
})
|
|
57
111
|
|
|
58
|
-
|
|
112
|
+
assert(elementHandle, `Element not found: ${selector}`)
|
|
59
113
|
|
|
60
114
|
return elementHandle
|
|
61
115
|
}
|
|
@@ -1,10 +1,15 @@
|
|
|
1
|
+
import assert from 'node:assert'
|
|
1
2
|
import fs from 'node:fs/promises'
|
|
2
3
|
import { gzipSync } from 'node:zlib'
|
|
3
4
|
import * as uint8arrays from 'uint8arrays'
|
|
4
5
|
import { randomBytes } from '@atproto/crypto'
|
|
5
6
|
import { SeedClient, TestNetworkNoAppView } from '@atproto/dev-env'
|
|
6
7
|
import { Client, DidString } from '@atproto/lex'
|
|
7
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
TypedBlobRef,
|
|
10
|
+
getBlobCidString,
|
|
11
|
+
isTypedBlobRef,
|
|
12
|
+
} from '@atproto/lex-data'
|
|
8
13
|
import { AppContext } from '../src'
|
|
9
14
|
import { ActorDb } from '../src/actor-store/db'
|
|
10
15
|
import { DiskBlobStore } from '../src/disk-blobstore'
|
|
@@ -40,7 +45,7 @@ describe('file uploads', () => {
|
|
|
40
45
|
await network.close()
|
|
41
46
|
})
|
|
42
47
|
|
|
43
|
-
let smallBlob:
|
|
48
|
+
let smallBlob: TypedBlobRef
|
|
44
49
|
let smallFile: Uint8Array
|
|
45
50
|
|
|
46
51
|
it('handles client abort', async () => {
|
|
@@ -78,6 +83,7 @@ describe('file uploads', () => {
|
|
|
78
83
|
headers: sc.getHeaders(alice),
|
|
79
84
|
encoding: 'image/jpeg',
|
|
80
85
|
})
|
|
86
|
+
assert(isTypedBlobRef(res.body.blob))
|
|
81
87
|
smallBlob = res.body.blob
|
|
82
88
|
|
|
83
89
|
const found = await aliceDb.db
|
|
@@ -123,7 +129,7 @@ describe('file uploads', () => {
|
|
|
123
129
|
expect(uint8arrays.equals(smallFile, body)).toBeTruthy()
|
|
124
130
|
})
|
|
125
131
|
|
|
126
|
-
let largeBlob:
|
|
132
|
+
let largeBlob: TypedBlobRef
|
|
127
133
|
let largeFile: Uint8Array
|
|
128
134
|
|
|
129
135
|
it('does not allow referencing a file that is outside blob constraints', async () => {
|
|
@@ -132,6 +138,7 @@ describe('file uploads', () => {
|
|
|
132
138
|
headers: sc.getHeaders(alice),
|
|
133
139
|
encoding: 'image/jpeg',
|
|
134
140
|
})
|
|
141
|
+
assert(isTypedBlobRef(res.body.blob))
|
|
135
142
|
largeBlob = res.body.blob
|
|
136
143
|
|
|
137
144
|
const profilePromise = sc.updateProfile(alice, {
|
|
@@ -195,7 +202,7 @@ describe('file uploads', () => {
|
|
|
195
202
|
const blob = await aliceDb.db
|
|
196
203
|
.selectFrom('blob')
|
|
197
204
|
.selectAll()
|
|
198
|
-
.where('cid', '=', uploadAfterPermanent.blob
|
|
205
|
+
.where('cid', '=', getBlobCidString(uploadAfterPermanent.blob))
|
|
199
206
|
.executeTakeFirstOrThrow()
|
|
200
207
|
expect(blob.tempKey).toEqual(null)
|
|
201
208
|
})
|
|
@@ -208,6 +215,7 @@ describe('file uploads', () => {
|
|
|
208
215
|
'content-encoding': 'gzip',
|
|
209
216
|
},
|
|
210
217
|
})
|
|
218
|
+
assert(isTypedBlobRef(uploaded.blob))
|
|
211
219
|
expect(uploaded.blob.ref.equals(smallBlob.ref)).toBeTruthy()
|
|
212
220
|
})
|
|
213
221
|
|
|
@@ -221,7 +229,7 @@ describe('file uploads', () => {
|
|
|
221
229
|
const found = await aliceDb.db
|
|
222
230
|
.selectFrom('blob')
|
|
223
231
|
.selectAll()
|
|
224
|
-
.where('cid', '=', res.body.blob
|
|
232
|
+
.where('cid', '=', getBlobCidString(res.body.blob))
|
|
225
233
|
.executeTakeFirst()
|
|
226
234
|
|
|
227
235
|
expect(found?.mimeType).toBe('image/jpeg')
|
|
@@ -237,7 +245,7 @@ describe('file uploads', () => {
|
|
|
237
245
|
const found = await aliceDb.db
|
|
238
246
|
.selectFrom('blob')
|
|
239
247
|
.selectAll()
|
|
240
|
-
.where('cid', '=', res.body.blob
|
|
248
|
+
.where('cid', '=', getBlobCidString(res.body.blob))
|
|
241
249
|
.executeTakeFirst()
|
|
242
250
|
|
|
243
251
|
expect(found?.mimeType).toBe('image/png')
|
|
@@ -253,7 +261,7 @@ describe('file uploads', () => {
|
|
|
253
261
|
const found = await aliceDb.db
|
|
254
262
|
.selectFrom('blob')
|
|
255
263
|
.selectAll()
|
|
256
|
-
.where('cid', '=', res.body.blob
|
|
264
|
+
.where('cid', '=', getBlobCidString(res.body.blob))
|
|
257
265
|
.executeTakeFirst()
|
|
258
266
|
|
|
259
267
|
expect(found?.mimeType).toBe('test/fake')
|
|
@@ -269,7 +277,7 @@ describe('file uploads', () => {
|
|
|
269
277
|
const found = await aliceDb.db
|
|
270
278
|
.selectFrom('blob')
|
|
271
279
|
.selectAll()
|
|
272
|
-
.where('cid', '=', res.body.blob
|
|
280
|
+
.where('cid', '=', getBlobCidString(res.body.blob))
|
|
273
281
|
.executeTakeFirst()
|
|
274
282
|
|
|
275
283
|
expect(found?.mimeType).toBe('text/plain')
|
|
@@ -285,7 +293,7 @@ describe('file uploads', () => {
|
|
|
285
293
|
const found = await aliceDb.db
|
|
286
294
|
.selectFrom('blob')
|
|
287
295
|
.selectAll()
|
|
288
|
-
.where('cid', '=', res.body.blob
|
|
296
|
+
.where('cid', '=', getBlobCidString(res.body.blob))
|
|
289
297
|
.executeTakeFirst()
|
|
290
298
|
|
|
291
299
|
expect(found?.mimeType).toBe('application/json')
|
package/tests/oauth.test.ts
CHANGED
|
@@ -1,14 +1,9 @@
|
|
|
1
1
|
import { once } from 'node:events'
|
|
2
|
-
import {
|
|
3
|
-
IncomingMessage,
|
|
4
|
-
Server,
|
|
5
|
-
ServerResponse,
|
|
6
|
-
createServer,
|
|
7
|
-
} from 'node:http'
|
|
2
|
+
import { Server, createServer } from 'node:http'
|
|
8
3
|
import { AddressInfo } from 'node:net'
|
|
9
4
|
import { type Browser, launch } from 'puppeteer'
|
|
10
5
|
import { TestNetworkNoAppView } from '@atproto/dev-env'
|
|
11
|
-
import
|
|
6
|
+
import { oauthClientAssetsMiddleware } from './_oauth_client_assets_middleware.js'
|
|
12
7
|
import { PageHelper } from './_puppeteer.js'
|
|
13
8
|
|
|
14
9
|
describe('oauth', () => {
|
|
@@ -44,7 +39,7 @@ describe('oauth', () => {
|
|
|
44
39
|
password: 'alice-pass',
|
|
45
40
|
})
|
|
46
41
|
|
|
47
|
-
server = createServer(
|
|
42
|
+
server = createServer(oauthClientAssetsMiddleware)
|
|
48
43
|
server.listen(0)
|
|
49
44
|
await once(server, 'listening')
|
|
50
45
|
|
|
@@ -67,26 +62,24 @@ describe('oauth', () => {
|
|
|
67
62
|
|
|
68
63
|
// This uses prompt=create under the hood:
|
|
69
64
|
it('Allows to sign-up through OAuth', async () => {
|
|
70
|
-
|
|
65
|
+
await using page = await PageHelper.from(browser, { languages })
|
|
71
66
|
|
|
72
67
|
await page.goto(appUrl)
|
|
73
68
|
|
|
74
|
-
await page.
|
|
69
|
+
await page.assertTitle('OAuth Client Example')
|
|
75
70
|
|
|
76
|
-
await page.
|
|
77
|
-
await page.clickOnButton(`Sign up with ${new URL(network.pds.url).host}`)
|
|
78
|
-
})
|
|
71
|
+
await page.navigationClick(`Sign up with ${new URL(network.pds.url).host}`)
|
|
79
72
|
|
|
80
|
-
await page.
|
|
73
|
+
await page.assertTitle("S'inscrire")
|
|
81
74
|
|
|
82
75
|
await page.typeInInput('handle', 'bob')
|
|
83
76
|
|
|
84
|
-
await page.
|
|
77
|
+
await page.clickOnText('Suivant')
|
|
85
78
|
|
|
86
79
|
await page.typeInInput('email', 'bob@test.com')
|
|
87
80
|
await page.typeInInput('password', 'bob-pass')
|
|
88
81
|
|
|
89
|
-
await page.
|
|
82
|
+
await page.clickOnText("S'inscrire")
|
|
90
83
|
|
|
91
84
|
await page.ensureTextVisibility(
|
|
92
85
|
`L'application demande un contrôle total sur votre identité, ce qui signifie qu'elle pourrait casser de façon permanente, ou même usurper, votre compte. N'authorisez l'accès qu'aux applications auxquelles vous faites vraiment confiance.`,
|
|
@@ -96,54 +89,38 @@ describe('oauth', () => {
|
|
|
96
89
|
// the client to resolve the account's did
|
|
97
90
|
await network.processAll()
|
|
98
91
|
|
|
99
|
-
await page.
|
|
100
|
-
await page.clickOnButton("Authoriser l'accès")
|
|
101
|
-
})
|
|
92
|
+
await page.navigationClick('Autoriser')
|
|
102
93
|
|
|
103
|
-
await page.
|
|
94
|
+
await page.assertTitle('OAuth Client Example')
|
|
104
95
|
|
|
105
96
|
await page.ensureTextVisibility('Token info', 'h2')
|
|
106
97
|
|
|
107
|
-
await page.
|
|
98
|
+
await page.clickOnAriaLabel('User menu')
|
|
108
99
|
|
|
109
|
-
await page.
|
|
100
|
+
await page.clickOnText('Sign out')
|
|
110
101
|
|
|
111
102
|
await page.waitForNetworkIdle()
|
|
112
|
-
|
|
113
|
-
// TODO: Find out why we can't use "using" here
|
|
114
|
-
await page[Symbol.asyncDispose]()
|
|
115
103
|
})
|
|
116
104
|
|
|
117
|
-
it('Allows
|
|
118
|
-
|
|
105
|
+
it('Allows canceling the OAuth flow', async () => {
|
|
106
|
+
await using page = await PageHelper.from(browser, { languages })
|
|
119
107
|
|
|
120
108
|
await page.goto(appUrl)
|
|
121
109
|
|
|
122
|
-
await page.
|
|
123
|
-
|
|
124
|
-
await page.navigationAction(async () => {
|
|
125
|
-
await page.clickOnButton(`Login with ${new URL(network.pds.url).host}`)
|
|
126
|
-
})
|
|
110
|
+
await page.assertTitle('OAuth Client Example')
|
|
127
111
|
|
|
128
|
-
await page.
|
|
112
|
+
await page.navigationClick(`Login with ${new URL(network.pds.url).host}`)
|
|
129
113
|
|
|
130
|
-
await page.
|
|
131
|
-
await page.ensureTextVisibility('Se connecter', 'button')
|
|
132
|
-
await page.ensureTextVisibility('Créer un nouveau compte', 'button')
|
|
114
|
+
await page.assertTitle("S'identifier")
|
|
133
115
|
|
|
134
116
|
// Cancel the OAuth flow:
|
|
135
|
-
await page.
|
|
136
|
-
await page.clickOnButton('Annuler')
|
|
137
|
-
})
|
|
117
|
+
await page.navigationClick('Annuler')
|
|
138
118
|
|
|
139
|
-
await page.
|
|
119
|
+
await page.assertTitle('OAuth Client Example')
|
|
140
120
|
|
|
141
121
|
await page.ensureTextVisibility('Login with the Atmosphere', 'h2')
|
|
142
122
|
|
|
143
123
|
await page.waitForNetworkIdle()
|
|
144
|
-
|
|
145
|
-
// TODO: Find out why we can't use "using" here
|
|
146
|
-
await page[Symbol.asyncDispose]()
|
|
147
124
|
})
|
|
148
125
|
|
|
149
126
|
it('allows resetting the password', async () => {
|
|
@@ -153,31 +130,29 @@ describe('oauth', () => {
|
|
|
153
130
|
// noop
|
|
154
131
|
})
|
|
155
132
|
|
|
156
|
-
|
|
133
|
+
await using page = await PageHelper.from(browser, { languages })
|
|
157
134
|
|
|
158
135
|
await page.goto(appUrl)
|
|
159
136
|
|
|
160
|
-
await page.
|
|
137
|
+
await page.assertTitle('OAuth Client Example')
|
|
161
138
|
|
|
162
|
-
await page.
|
|
163
|
-
const input = await page.typeIn('input[name="identifier"]', 'alice.test')
|
|
139
|
+
const input = await page.typeInInput('identifier', 'alice.test')
|
|
164
140
|
|
|
165
|
-
|
|
166
|
-
})
|
|
141
|
+
await page.navigationAction(async () => input.press('Enter'))
|
|
167
142
|
|
|
168
|
-
await page.
|
|
143
|
+
await page.assertTitle('Connexion')
|
|
169
144
|
|
|
170
|
-
await page.
|
|
145
|
+
await page.clickOnText('Oublié ?')
|
|
171
146
|
|
|
172
|
-
await page.
|
|
147
|
+
await page.assertTitle('Mot de passe oublié')
|
|
173
148
|
|
|
174
149
|
await page.typeInInput('email', 'alice@test.com')
|
|
175
150
|
|
|
176
151
|
expect(sendTemplateMock).toHaveBeenCalledTimes(0)
|
|
177
152
|
|
|
178
|
-
await page.
|
|
153
|
+
await page.clickOnText('Suivant')
|
|
179
154
|
|
|
180
|
-
await page.
|
|
155
|
+
await page.assertTitle('Réinitialiser le mot de passe')
|
|
181
156
|
|
|
182
157
|
expect(sendTemplateMock).toHaveBeenCalledTimes(1)
|
|
183
158
|
|
|
@@ -191,34 +166,29 @@ describe('oauth', () => {
|
|
|
191
166
|
|
|
192
167
|
await page.typeInInput('password', 'alice-new-pass')
|
|
193
168
|
|
|
194
|
-
await page.
|
|
169
|
+
await page.clickOnText('Suivant')
|
|
195
170
|
|
|
196
|
-
await page.
|
|
171
|
+
await page.assertTitle('Mot de passe mis à jour')
|
|
197
172
|
|
|
198
173
|
await page.ensureTextVisibility('Mot de passe mis à jour !', 'h2')
|
|
199
174
|
|
|
200
|
-
// TODO: Find out why we can't use "using" here
|
|
201
|
-
await page[Symbol.asyncDispose]()
|
|
202
|
-
|
|
203
175
|
sendTemplateMock.mockRestore()
|
|
204
176
|
})
|
|
205
177
|
|
|
206
178
|
it('Allows to sign-in through OAuth', async () => {
|
|
207
|
-
|
|
179
|
+
await using page = await PageHelper.from(browser, { languages })
|
|
208
180
|
|
|
209
181
|
await page.goto(appUrl)
|
|
210
182
|
|
|
211
|
-
await page.
|
|
183
|
+
await page.assertTitle('OAuth Client Example')
|
|
212
184
|
|
|
213
|
-
await page.
|
|
214
|
-
const input = await page.typeIn('input[name="identifier"]', 'alice.test')
|
|
185
|
+
const input = await page.typeInInput('identifier', 'alice.test')
|
|
215
186
|
|
|
216
|
-
|
|
217
|
-
})
|
|
187
|
+
await page.navigationAction(async () => input.press('Enter'))
|
|
218
188
|
|
|
219
|
-
await page.
|
|
189
|
+
await page.assertTitle('Connexion')
|
|
220
190
|
|
|
221
|
-
await page.
|
|
191
|
+
await page.typeInInput('password', 'alice-new-pass')
|
|
222
192
|
|
|
223
193
|
// Make sure the warning is visible
|
|
224
194
|
await page.ensureTextVisibility('Avertissement', 'h3')
|
|
@@ -227,79 +197,46 @@ describe('oauth', () => {
|
|
|
227
197
|
'label::-p-text(Se souvenir de ce compte sur cet appareil)',
|
|
228
198
|
)
|
|
229
199
|
|
|
230
|
-
await page.
|
|
200
|
+
await page.clickOnText('Se connecter')
|
|
231
201
|
|
|
232
|
-
await page.
|
|
202
|
+
await page.assertTitle('Autoriser')
|
|
233
203
|
|
|
234
|
-
await page.
|
|
235
|
-
await page.clickOnButton("Authoriser l'accès")
|
|
236
|
-
})
|
|
204
|
+
await page.navigationClick('Autoriser')
|
|
237
205
|
|
|
238
|
-
await page.
|
|
206
|
+
await page.assertTitle('OAuth Client Example')
|
|
239
207
|
|
|
240
208
|
await page.ensureTextVisibility('Token info', 'h2')
|
|
241
209
|
|
|
242
|
-
await page.
|
|
210
|
+
await page.clickOnAriaLabel('User menu')
|
|
243
211
|
|
|
244
|
-
await page.
|
|
212
|
+
await page.clickOnText('Sign out')
|
|
245
213
|
|
|
246
214
|
await page.waitForNetworkIdle()
|
|
247
|
-
|
|
248
|
-
// TODO: Find out why we can't use "using" here
|
|
249
|
-
await page[Symbol.asyncDispose]()
|
|
250
215
|
})
|
|
251
216
|
|
|
252
217
|
it('remembers the session', async () => {
|
|
253
|
-
|
|
218
|
+
await using page = await PageHelper.from(browser, { languages })
|
|
254
219
|
|
|
255
220
|
await page.goto(appUrl)
|
|
256
221
|
|
|
257
|
-
await page.
|
|
222
|
+
await page.assertTitle('OAuth Client Example')
|
|
258
223
|
|
|
259
|
-
await page.
|
|
260
|
-
const input = await page.typeIn('input[name="identifier"]', 'alice.test')
|
|
224
|
+
const input = await page.typeInInput('identifier', 'alice.test')
|
|
261
225
|
|
|
262
|
-
|
|
263
|
-
})
|
|
226
|
+
await page.navigationAction(async () => input.press('Enter'))
|
|
264
227
|
|
|
265
|
-
await page.
|
|
228
|
+
await page.assertTitle('Autoriser')
|
|
266
229
|
|
|
267
|
-
await page.
|
|
268
|
-
await page.clickOnButton("Authoriser l'accès")
|
|
269
|
-
})
|
|
230
|
+
await page.navigationClick('Autoriser')
|
|
270
231
|
|
|
271
|
-
await page.
|
|
232
|
+
await page.assertTitle('OAuth Client Example')
|
|
272
233
|
|
|
273
234
|
await page.ensureTextVisibility('Token info', 'h2')
|
|
274
235
|
|
|
275
|
-
await page.
|
|
236
|
+
await page.clickOnAriaLabel('User menu')
|
|
276
237
|
|
|
277
|
-
await page.
|
|
238
|
+
await page.clickOnText('Sign out')
|
|
278
239
|
|
|
279
240
|
await page.waitForNetworkIdle()
|
|
280
|
-
|
|
281
|
-
// TODO: Find out why we can't use "using" here
|
|
282
|
-
await page[Symbol.asyncDispose]()
|
|
283
241
|
})
|
|
284
242
|
})
|
|
285
|
-
|
|
286
|
-
function clientHandler(
|
|
287
|
-
req: IncomingMessage,
|
|
288
|
-
res: ServerResponse,
|
|
289
|
-
next?: (err?: unknown) => void,
|
|
290
|
-
): void {
|
|
291
|
-
const path = req.url?.split('?')[0].slice(1) || 'index.html'
|
|
292
|
-
const file = Object.hasOwn(files, path) ? files[path] : null
|
|
293
|
-
|
|
294
|
-
if (file) {
|
|
295
|
-
res
|
|
296
|
-
.writeHead(200, 'OK', { 'content-type': file.mime })
|
|
297
|
-
.end(Buffer.from(file.data, 'base64'))
|
|
298
|
-
} else if (next) {
|
|
299
|
-
next()
|
|
300
|
-
} else {
|
|
301
|
-
res
|
|
302
|
-
.writeHead(404, 'Not Found', { 'content-type': 'text/plain' })
|
|
303
|
-
.end('Page not found')
|
|
304
|
-
}
|
|
305
|
-
}
|