Suite of AT Protocol TypeScript libraries built on web standards
1import type { LexiconDoc } from "@atp/lexicon";
2import { Client } from "./_xrpc-client.ts";
3import * as xrpcServer from "../mod.ts";
4import { closeServer, createServer } from "./_util.ts";
5import { assertEquals } from "@std/assert";
6
7const LEXICONS: LexiconDoc[] = [
8 {
9 lexicon: 1,
10 id: "io.example.pingOne",
11 defs: {
12 main: {
13 type: "procedure",
14 parameters: {
15 type: "params",
16 properties: {
17 message: { type: "string" },
18 },
19 },
20 output: {
21 encoding: "text/plain",
22 },
23 },
24 },
25 },
26 {
27 lexicon: 1,
28 id: "io.example.pingTwo",
29 defs: {
30 main: {
31 type: "procedure",
32 input: {
33 encoding: "text/plain",
34 },
35 output: {
36 encoding: "text/plain",
37 },
38 },
39 },
40 },
41 {
42 lexicon: 1,
43 id: "io.example.pingThree",
44 defs: {
45 main: {
46 type: "procedure",
47 input: {
48 encoding: "application/octet-stream",
49 },
50 output: {
51 encoding: "application/octet-stream",
52 },
53 },
54 },
55 },
56 {
57 lexicon: 1,
58 id: "io.example.pingFour",
59 defs: {
60 main: {
61 type: "procedure",
62 input: {
63 encoding: "application/json",
64 schema: {
65 type: "object",
66 required: ["message"],
67 properties: { message: { type: "string" } },
68 },
69 },
70 output: {
71 encoding: "application/json",
72 schema: {
73 type: "object",
74 required: ["message"],
75 properties: { message: { type: "string" } },
76 },
77 },
78 },
79 },
80 },
81];
82
83let server: ReturnType<typeof xrpcServer.createServer>;
84let s: Deno.HttpServer;
85let client: Client;
86
87Deno.test.beforeAll(async () => {
88 server = xrpcServer.createServer(LEXICONS);
89 server.method(
90 "io.example.pingOne",
91 (ctx: xrpcServer.HandlerContext) => {
92 return { encoding: "text/plain", body: ctx.params.message };
93 },
94 );
95 server.method(
96 "io.example.pingTwo",
97 (ctx: xrpcServer.HandlerContext) => {
98 return { encoding: "text/plain", body: ctx.input?.body };
99 },
100 );
101 server.method(
102 "io.example.pingThree",
103 (ctx: xrpcServer.HandlerContext) => {
104 return {
105 encoding: "application/octet-stream",
106 body: ctx.input?.body,
107 };
108 },
109 );
110 server.method(
111 "io.example.pingFour",
112 (ctx: xrpcServer.HandlerContext) => {
113 const body = ctx.input?.body as { message: string };
114 return {
115 encoding: "application/json",
116 body: { message: body?.message },
117 };
118 },
119 );
120 s = await createServer(server);
121 const port = (s as Deno.HttpServer & { port: number }).port;
122 client = new Client(`http://localhost:${port}`, LEXICONS);
123});
124
125Deno.test.afterAll(async () => {
126 await closeServer(s);
127});
128
129Deno.test("serves procedure with query parameters", {
130 sanitizeOps: false,
131 sanitizeResources: false,
132}, async () => {
133 const res1 = await client.call("io.example.pingOne", {
134 message: "hello world",
135 });
136 assertEquals(res1.success, true);
137 assertEquals(res1.headers["content-type"], "text/plain");
138 assertEquals(res1.data, "hello world");
139});
140
141Deno.test("serves procedure with text/plain input", {
142 sanitizeOps: false,
143 sanitizeResources: false,
144}, async () => {
145 const res2 = await client.call(
146 "io.example.pingTwo",
147 {},
148 "hello world",
149 {
150 encoding: "text/plain",
151 },
152 );
153 assertEquals(res2.success, true);
154 assertEquals(res2.headers["content-type"], "text/plain");
155 assertEquals(res2.data, "hello world");
156});
157
158Deno.test("serves procedure with octet-stream input", {
159 sanitizeOps: false,
160 sanitizeResources: false,
161}, async () => {
162 const res3 = await client.call(
163 "io.example.pingThree",
164 {},
165 new TextEncoder().encode("hello world"),
166 { encoding: "application/octet-stream" },
167 );
168 assertEquals(res3.success, true);
169 assertEquals(res3.headers["content-type"], "application/octet-stream");
170 assertEquals(new TextDecoder().decode(res3.data), "hello world");
171});
172
173Deno.test("serves procedure with JSON input", {
174 sanitizeOps: false,
175 sanitizeResources: false,
176}, async () => {
177 const res4 = await client.call(
178 "io.example.pingFour",
179 {},
180 { message: "hello world" },
181 );
182 assertEquals(res4.success, true);
183 assertEquals(
184 res4.headers["content-type"],
185 "application/json",
186 );
187 assertEquals(res4.data?.message, "hello world");
188});