atproto/packages/xrpc-server/tests/procedures.test.ts
Matthieu Sieben 7f26b17652
Add OAuth tests (#2874)
* Improve error message when using invalid client_id during code exchange

* Extract SPA example OAuth client in own package

* wip

* remove dependency on get-port

* Properly configure jest to only transpile "get-port" from node_modules

https://jestjs.io/docs/configuration#transformignorepatterns-arraystring

* Use dynamically assigned port number during tests

* use puppeteer to run tests

* remove login input "id" attribute

* code style

* add missing declaration

* tidy

* headless

* remove get-port dependency

* fix tests/proxied/admin.test.ts

* fix tests

* Allow unsecure oauth providers through configuration

* transpile "lande" during ozone tests

* Cache Puppeteer browser binaries

* Use puppeteer cache during all workflow steps

* remove use of set-output

* use get-port in xrpc-server tests

* Renamed to allowHttp

* tidy

* tidy
2024-10-18 15:40:05 +02:00

170 lines
4.3 KiB
TypeScript

import * as http from 'node:http'
import { Readable } from 'node:stream'
import { LexiconDoc } from '@atproto/lexicon'
import { XrpcClient } from '@atproto/xrpc'
import { createServer, closeServer } from './_util'
import * as xrpcServer from '../src'
import { AddressInfo } from 'node:net'
const LEXICONS: LexiconDoc[] = [
{
lexicon: 1,
id: 'io.example.pingOne',
defs: {
main: {
type: 'procedure',
parameters: {
type: 'params',
properties: {
message: { type: 'string' },
},
},
output: {
encoding: 'text/plain',
},
},
},
},
{
lexicon: 1,
id: 'io.example.pingTwo',
defs: {
main: {
type: 'procedure',
input: {
encoding: 'text/plain',
},
output: {
encoding: 'text/plain',
},
},
},
},
{
lexicon: 1,
id: 'io.example.pingThree',
defs: {
main: {
type: 'procedure',
input: {
encoding: 'application/octet-stream',
},
output: {
encoding: 'application/octet-stream',
},
},
},
},
{
lexicon: 1,
id: 'io.example.pingFour',
defs: {
main: {
type: 'procedure',
input: {
encoding: 'application/json',
schema: {
type: 'object',
required: ['message'],
properties: { message: { type: 'string' } },
},
},
output: {
encoding: 'application/json',
schema: {
type: 'object',
required: ['message'],
properties: { message: { type: 'string' } },
},
},
},
},
},
]
describe('Procedures', () => {
let s: http.Server
const server = xrpcServer.createServer(LEXICONS)
server.method('io.example.pingOne', (ctx: { params: xrpcServer.Params }) => {
return { encoding: 'text/plain', body: ctx.params.message }
})
server.method(
'io.example.pingTwo',
(ctx: { params: xrpcServer.Params; input?: xrpcServer.HandlerInput }) => {
return { encoding: 'text/plain', body: ctx.input?.body }
},
)
server.method(
'io.example.pingThree',
async (ctx: {
params: xrpcServer.Params
input?: xrpcServer.HandlerInput
}) => {
if (!(ctx.input?.body instanceof Readable))
throw new Error('Input not readable')
const buffers: Buffer[] = []
for await (const data of ctx.input.body) {
buffers.push(data)
}
return {
encoding: 'application/octet-stream',
body: Buffer.concat(buffers),
}
},
)
server.method(
'io.example.pingFour',
(ctx: { params: xrpcServer.Params; input?: xrpcServer.HandlerInput }) => {
return {
encoding: 'application/json',
body: { message: ctx.input?.body?.message },
}
},
)
let client: XrpcClient
beforeAll(async () => {
s = await createServer(server)
const { port } = s.address() as AddressInfo
client = new XrpcClient(`http://localhost:${port}`, LEXICONS)
})
afterAll(async () => {
await closeServer(s)
})
it('serves requests', async () => {
const res1 = await client.call('io.example.pingOne', {
message: 'hello world',
})
expect(res1.success).toBeTruthy()
expect(res1.headers['content-type']).toBe('text/plain; charset=utf-8')
expect(res1.data).toBe('hello world')
const res2 = await client.call('io.example.pingTwo', {}, 'hello world', {
encoding: 'text/plain',
})
expect(res2.success).toBeTruthy()
expect(res2.headers['content-type']).toBe('text/plain; charset=utf-8')
expect(res2.data).toBe('hello world')
const res3 = await client.call(
'io.example.pingThree',
{},
new TextEncoder().encode('hello world'),
{ encoding: 'application/octet-stream' },
)
expect(res3.success).toBeTruthy()
expect(res3.headers['content-type']).toBe('application/octet-stream')
expect(new TextDecoder().decode(res3.data)).toBe('hello world')
const res4 = await client.call(
'io.example.pingFour',
{},
{ message: 'hello world' },
)
expect(res4.success).toBeTruthy()
expect(res4.headers['content-type']).toBe('application/json; charset=utf-8')
expect(res4.data?.message).toBe('hello world')
})
})