@crossauth/sveltekit 1.0.1 → 1.1.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.
Files changed (47) hide show
  1. package/README.md +1 -1
  2. package/dist/index.d.ts +1 -1
  3. package/dist/index.js +16 -6181
  4. package/dist/sveltekitadminclientendpoints.d.ts +13 -12
  5. package/dist/sveltekitadminclientendpoints.js +187 -0
  6. package/dist/sveltekitadminendpoints.d.ts +5 -4
  7. package/dist/sveltekitadminendpoints.js +766 -0
  8. package/dist/sveltekitapikey.d.ts +4 -3
  9. package/dist/sveltekitapikey.js +81 -0
  10. package/dist/sveltekitoauthclient.d.ts +6 -4
  11. package/dist/sveltekitoauthclient.js +2309 -0
  12. package/dist/sveltekitoauthserver.d.ts +4 -4
  13. package/dist/sveltekitoauthserver.js +1350 -0
  14. package/dist/sveltekitresserver.d.ts +6 -4
  15. package/dist/sveltekitresserver.js +286 -0
  16. package/dist/sveltekitserver.d.ts +11 -9
  17. package/dist/sveltekitserver.js +393 -0
  18. package/dist/sveltekitsession.d.ts +6 -5
  19. package/dist/sveltekitsession.js +1112 -0
  20. package/dist/sveltekitsessionadapter.d.ts +2 -3
  21. package/dist/sveltekitsessionadapter.js +2 -0
  22. package/dist/sveltekitsharedclientendpoints.d.ts +7 -6
  23. package/dist/sveltekitsharedclientendpoints.js +630 -0
  24. package/dist/sveltekituserclientendpoints.d.ts +13 -12
  25. package/dist/sveltekituserclientendpoints.js +270 -0
  26. package/dist/sveltekituserendpoints.d.ts +6 -5
  27. package/dist/sveltekituserendpoints.js +1813 -0
  28. package/dist/tests/sveltekitadminclientendpoints.test.js +330 -0
  29. package/dist/tests/sveltekitadminendpoints.test.js +242 -0
  30. package/dist/tests/sveltekitapikeyserver.test.js +44 -0
  31. package/dist/tests/sveltekitoauthclient.test.d.ts +5 -5
  32. package/dist/tests/sveltekitoauthclient.test.js +1016 -0
  33. package/dist/tests/sveltekitoauthresserver.test.d.ts +4 -4
  34. package/dist/tests/sveltekitoauthresserver.test.js +185 -0
  35. package/dist/tests/sveltekitoauthserver.test.js +673 -0
  36. package/dist/tests/sveltekituserclientendpoints.test.js +244 -0
  37. package/dist/tests/sveltekituserendpoints.test.js +152 -0
  38. package/dist/tests/sveltemock.test.js +36 -0
  39. package/dist/tests/sveltemocks.d.ts +22 -8
  40. package/dist/tests/sveltemocks.js +114 -0
  41. package/dist/tests/sveltesessionhooks.test.js +224 -0
  42. package/dist/tests/testshared.d.ts +8 -8
  43. package/dist/tests/testshared.js +344 -0
  44. package/dist/utils.d.ts +1 -2
  45. package/dist/utils.js +123 -0
  46. package/package.json +23 -15
  47. package/dist/index.cjs +0 -1
@@ -0,0 +1,244 @@
1
+ // Copyright (c) 2026 Matthew Baker. All rights reserved. Licenced under the Apache Licence 2.0. See LICENSE file
2
+ import { MockRequestEvent } from './sveltemocks';
3
+ import { test, expect } from 'vitest';
4
+ import { makeServer, getCsrfToken, login } from './testshared';
5
+ export var passwordResetData;
6
+ test('SvelteKitUserClientEndpoints.selectClients', async () => {
7
+ const { server, resolver, handle, } = await makeServer();
8
+ // log in
9
+ let resp = await login(server, resolver, handle);
10
+ let loginEvent = resp.event;
11
+ loginEvent = resp.event;
12
+ const { csrfToken, csrfCookieValue } = await getCsrfToken(server, resolver, handle);
13
+ let sessionCookieValue = loginEvent.cookies.get("SESSIONID");
14
+ let sessionId = server.sessionServer?.sessionManager.getSessionId(sessionCookieValue ?? "");
15
+ // select clients
16
+ let getRequest = new Request("http://ex.com/oauth/clients", {
17
+ method: "POST",
18
+ body: "csrfToken=" + csrfToken,
19
+ headers: [
20
+ ["cookie", "CSRFTOKEN=" + csrfCookieValue],
21
+ ["cookie", "SESSIONID=" + sessionCookieValue],
22
+ ["content-type", "application/x-www-form-urlencoded"],
23
+ ]
24
+ });
25
+ let event = new MockRequestEvent("1", getRequest, { id: "bob" });
26
+ event.locals.csrfToken = csrfToken;
27
+ event.locals.sessionId = sessionId;
28
+ event.locals.authType = "cookie";
29
+ event.locals.user = loginEvent.locals.user;
30
+ let resp1 = await server.sessionServer?.userClientEndpoints.searchClients(event);
31
+ expect(resp1?.ok).toBe(true);
32
+ expect(resp1?.clients?.length).toBe(1);
33
+ });
34
+ test('SvelteKitUserClientEndpoints.updateClient', async () => {
35
+ const { server, resolver, handle } = await makeServer();
36
+ // log in
37
+ let resp = await login(server, resolver, handle);
38
+ let loginEvent = resp.event;
39
+ loginEvent = resp.event;
40
+ const { csrfToken, csrfCookieValue } = await getCsrfToken(server, resolver, handle);
41
+ let sessionCookieValue = loginEvent.cookies.get("SESSIONID");
42
+ let sessionId = server.sessionServer?.sessionManager.getSessionId(sessionCookieValue ?? "");
43
+ let getRequest = new Request("http://ex.com/oauth/clients", {
44
+ method: "GET",
45
+ headers: [
46
+ ["cookie", "CSRFTOKEN=" + csrfCookieValue],
47
+ ["cookie", "SESSIONID=" + sessionCookieValue],
48
+ ["content-type", "application/x-www-form-urlencoded"],
49
+ ]
50
+ });
51
+ let event = new MockRequestEvent("1", getRequest, { client_id: "ABC" });
52
+ event.locals.csrfToken = csrfToken;
53
+ let status = 200;
54
+ let resp1 = {};
55
+ try {
56
+ resp1 = await server.sessionServer?.userClientEndpoints.updateClientEndpoint.load(event);
57
+ }
58
+ catch (e) {
59
+ if (e && typeof (e) == "object" && "status" in e && typeof (e.status) == "number")
60
+ status = e.status;
61
+ }
62
+ expect(status).toBe(302);
63
+ event = new MockRequestEvent("1", getRequest, { client_id: "ABC" });
64
+ event.locals.csrfToken = csrfToken;
65
+ event.locals.sessionId = sessionId;
66
+ event.locals.authType = "cookie";
67
+ event.locals.user = loginEvent.locals.user;
68
+ status = 200;
69
+ try {
70
+ resp1 = await server.sessionServer?.userClientEndpoints.updateClientEndpoint.load(event);
71
+ }
72
+ catch (e) {
73
+ if (e && typeof (e) == "object" && "status" in e && typeof (e.status) == "number")
74
+ status = e.status;
75
+ }
76
+ expect(status).toBe(401);
77
+ event = new MockRequestEvent("1", getRequest, { client_id: "bob_ABC" });
78
+ event.locals.csrfToken = csrfToken;
79
+ event.locals.sessionId = sessionId;
80
+ event.locals.authType = "cookie";
81
+ event.locals.user = loginEvent.locals.user;
82
+ resp1 = await server.sessionServer?.userClientEndpoints.updateClientEndpoint.load(event);
83
+ expect(resp1?.ok).toBe(true);
84
+ let postRequest = new Request("http://ex.com/oauth/clients", {
85
+ method: "POST",
86
+ body: "csrfToken=" + csrfToken + "&client_name=newName&confidential=on&redirect_uri=http://uri1.com/redirect&authorizationCode=on",
87
+ headers: [
88
+ ["cookie", "CSRFTOKEN=" + csrfCookieValue],
89
+ ["cookie", "SESSIONID=" + sessionCookieValue],
90
+ ["content-type", "application/x-www-form-urlencoded"],
91
+ ]
92
+ });
93
+ event = new MockRequestEvent("1", postRequest, { client_id: "bob_ABC" });
94
+ event.locals.csrfToken = csrfToken;
95
+ event.locals.sessionId = sessionId;
96
+ event.locals.authType = "cookie";
97
+ event.locals.user = loginEvent.locals.user;
98
+ resp1 = await server.sessionServer?.userClientEndpoints.updateClientEndpoint.actions.default(event);
99
+ expect(resp1?.ok).toBe(true);
100
+ expect(resp1?.client?.client_name).toBe("newName");
101
+ expect(resp1?.plaintextSecret).toBeUndefined();
102
+ expect(resp1?.client?.client_secret).toContain("pbkdf2:sha256");
103
+ postRequest = new Request("http://ex.com/oauth/clients", {
104
+ method: "POST",
105
+ body: "csrfToken=" + csrfToken + "&client_name=newName&confidential=on&redirect_uri=http://uri1.com/redirect&authorizationCode=on&resetSecret=on",
106
+ headers: [
107
+ ["cookie", "CSRFTOKEN=" + csrfCookieValue],
108
+ ["cookie", "SESSIONID=" + sessionCookieValue],
109
+ ["content-type", "application/x-www-form-urlencoded"],
110
+ ]
111
+ });
112
+ event = new MockRequestEvent("1", postRequest, { client_id: "bob_ABC" });
113
+ event.locals.csrfToken = csrfToken;
114
+ event.locals.sessionId = sessionId;
115
+ event.locals.authType = "cookie";
116
+ event.locals.user = loginEvent.locals.user;
117
+ resp1 = await server.sessionServer?.userClientEndpoints.updateClientEndpoint.actions.default(event);
118
+ expect(resp1?.ok).toBe(true);
119
+ expect(resp1?.plaintextSecret).toBeDefined();
120
+ expect(resp1?.client?.client_secret).not.toContain("pbkdf2:sha256");
121
+ });
122
+ test('SvelteKitUserClientEndpoints.deleteClient', async () => {
123
+ const { server, resolver, handle } = await makeServer();
124
+ // log in
125
+ let resp = await login(server, resolver, handle);
126
+ let loginEvent = resp.event;
127
+ loginEvent = resp.event;
128
+ const { csrfToken, csrfCookieValue } = await getCsrfToken(server, resolver, handle);
129
+ let sessionCookieValue = loginEvent.cookies.get("SESSIONID");
130
+ let sessionId = server.sessionServer?.sessionManager.getSessionId(sessionCookieValue ?? "");
131
+ let getRequest = new Request("http://ex.com/oauth/clients", {
132
+ method: "GET",
133
+ headers: [
134
+ ["cookie", "CSRFTOKEN=" + csrfCookieValue],
135
+ ["cookie", "SESSIONID=" + sessionCookieValue],
136
+ ["content-type", "application/x-www-form-urlencoded"],
137
+ ]
138
+ });
139
+ let event = new MockRequestEvent("1", getRequest, { client_id: "ABC" });
140
+ event.locals.csrfToken = csrfToken;
141
+ let status = 200;
142
+ let resp1 = {};
143
+ try {
144
+ resp1 = await server.sessionServer?.userClientEndpoints.deleteClientEndpoint.load(event);
145
+ }
146
+ catch (e) {
147
+ if (e && typeof (e) == "object" && "status" in e && typeof (e.status) == "number")
148
+ status = e.status;
149
+ }
150
+ expect(status).toBe(302);
151
+ event = new MockRequestEvent("1", getRequest, { client_id: "ABC" });
152
+ event.locals.csrfToken = csrfToken;
153
+ event.locals.sessionId = sessionId;
154
+ event.locals.authType = "cookie";
155
+ event.locals.user = loginEvent.locals.user;
156
+ status = 200;
157
+ try {
158
+ resp1 = await server.sessionServer?.userClientEndpoints.deleteClientEndpoint.load(event);
159
+ }
160
+ catch (e) {
161
+ if (e && typeof (e) == "object" && "status" in e && typeof (e.status) == "number")
162
+ status = e.status;
163
+ }
164
+ expect(status).toBe(401);
165
+ event = new MockRequestEvent("1", getRequest, { client_id: "bob_ABC" });
166
+ event.locals.csrfToken = csrfToken;
167
+ event.locals.sessionId = sessionId;
168
+ event.locals.authType = "cookie";
169
+ event.locals.user = loginEvent.locals.user;
170
+ resp1 = await server.sessionServer?.userClientEndpoints.deleteClientEndpoint.load(event);
171
+ expect(resp1?.ok).toBe(true);
172
+ let postRequest = new Request("http://ex.com/oauth/clients", {
173
+ method: "POST",
174
+ body: "csrfToken=" + csrfToken,
175
+ headers: [
176
+ ["cookie", "CSRFTOKEN=" + csrfCookieValue],
177
+ ["cookie", "SESSIONID=" + sessionCookieValue],
178
+ ["content-type", "application/x-www-form-urlencoded"],
179
+ ]
180
+ });
181
+ event = new MockRequestEvent("1", postRequest, { client_id: "bob_ABC" });
182
+ event.locals.csrfToken = csrfToken;
183
+ event.locals.sessionId = sessionId;
184
+ event.locals.authType = "cookie";
185
+ event.locals.user = loginEvent.locals.user;
186
+ resp1 = await server.sessionServer?.userClientEndpoints.deleteClientEndpoint.actions.default(event);
187
+ expect(resp1?.ok).toBe(true);
188
+ });
189
+ test('SvelteKitUserClientEndpoints.createClient', async () => {
190
+ const { server, resolver, handle } = await makeServer();
191
+ // log in
192
+ let resp = await login(server, resolver, handle);
193
+ let loginEvent = resp.event;
194
+ loginEvent = resp.event;
195
+ const { csrfToken, csrfCookieValue } = await getCsrfToken(server, resolver, handle);
196
+ let sessionCookieValue = loginEvent.cookies.get("SESSIONID");
197
+ let sessionId = server.sessionServer?.sessionManager.getSessionId(sessionCookieValue ?? "");
198
+ let getRequest = new Request("http://ex.com/oauth/clients", {
199
+ method: "GET",
200
+ headers: [
201
+ ["cookie", "CSRFTOKEN=" + csrfCookieValue],
202
+ ["cookie", "SESSIONID=" + sessionCookieValue],
203
+ ["content-type", "application/x-www-form-urlencoded"],
204
+ ]
205
+ });
206
+ let event = new MockRequestEvent("1", getRequest, {});
207
+ event.locals.csrfToken = csrfToken;
208
+ let status = 302;
209
+ let resp1 = {};
210
+ try {
211
+ resp1 = await server.sessionServer?.userClientEndpoints.createClientEndpoint.load(event);
212
+ }
213
+ catch (e) {
214
+ if (e && typeof (e) == "object" && "status" in e && typeof (e.status) == "number")
215
+ status = e.status;
216
+ }
217
+ expect(status).toBe(302);
218
+ event = new MockRequestEvent("1", getRequest, {});
219
+ event.locals.csrfToken = csrfToken;
220
+ event.locals.sessionId = sessionId;
221
+ event.locals.authType = "cookie";
222
+ event.locals.user = loginEvent.locals.user;
223
+ resp1 = await server.sessionServer?.userClientEndpoints.createClientEndpoint.load(event);
224
+ expect(resp1?.ok).toBe(true);
225
+ let postRequest = new Request("http://ex.com/oauth/clients", {
226
+ method: "POST",
227
+ body: "csrfToken=" + csrfToken + "&client_name=newName&confidential=on&redirect_uri=http://uri1.com/redirect&authorizationCode=on",
228
+ headers: [
229
+ ["cookie", "CSRFTOKEN=" + csrfCookieValue],
230
+ ["cookie", "SESSIONID=" + sessionCookieValue],
231
+ ["content-type", "application/x-www-form-urlencoded"],
232
+ ]
233
+ });
234
+ event = new MockRequestEvent("1", postRequest, { client_id: "bob_ABC" });
235
+ event.locals.csrfToken = csrfToken;
236
+ event.locals.sessionId = sessionId;
237
+ event.locals.authType = "cookie";
238
+ event.locals.user = loginEvent.locals.user;
239
+ resp1 = await server.sessionServer?.userClientEndpoints.createClientEndpoint.actions.default(event);
240
+ expect(resp1?.ok).toBe(true);
241
+ expect(resp1?.client?.client_name).toBe("newName");
242
+ expect(resp1?.plaintextSecret).toBeUndefined();
243
+ expect(resp1?.client?.client_secret).not.toContain("pbkdf2:sha256");
244
+ });
@@ -0,0 +1,152 @@
1
+ // Copyright (c) 2026 Matthew Baker. All rights reserved. Licenced under the Apache Licence 2.0. See LICENSE file
2
+ import { MockRequestEvent } from './sveltemocks';
3
+ import { test, expect } from 'vitest';
4
+ import { makeServer, getCsrfToken, login } from './testshared';
5
+ export var passwordResetData;
6
+ test('SvelteKitUserEndpoints.login', async () => {
7
+ const { server, resolver, handle } = await makeServer();
8
+ const { csrfToken, csrfCookieValue } = await getCsrfToken(server, resolver, handle);
9
+ const postRequest = new Request("http://ex.com/test", {
10
+ method: "POST",
11
+ body: "csrfToken=" + csrfToken + "&username=bob&password=bobPass123",
12
+ headers: {
13
+ "cookie": "CSRFTOKEN=" + csrfCookieValue,
14
+ "content-type": "application/x-www-form-urlencoded",
15
+ }
16
+ });
17
+ let event = new MockRequestEvent("1", postRequest, { "param1": "value1" });
18
+ event.locals.csrfToken = csrfToken;
19
+ const ret = await server.sessionServer?.userEndpoints.login(event);
20
+ expect(ret?.user?.username).toBe("bob");
21
+ expect(event.cookies.get("SESSIONID")).toBeDefined();
22
+ });
23
+ test('SvelteKitUserEndpoints.logout', async () => {
24
+ const { server, resolver, handle } = await makeServer();
25
+ const { csrfToken, csrfCookieValue } = await getCsrfToken(server, resolver, handle);
26
+ let postRequest = new Request("http://ex.com/test", {
27
+ method: "POST",
28
+ body: "csrfToken=" + csrfToken + "&username=bob&password=bobPass123",
29
+ headers: {
30
+ "cookie": "CSRFTOKEN=" + csrfCookieValue,
31
+ "content-type": "application/x-www-form-urlencoded",
32
+ }
33
+ });
34
+ let event = new MockRequestEvent("1", postRequest, { "param1": "value1" });
35
+ event.locals.csrfToken = csrfToken;
36
+ let ret = await server.sessionServer?.userEndpoints.login(event);
37
+ expect(ret?.user?.username).toBe("bob");
38
+ expect(event.cookies.get("SESSIONID")).toBeDefined();
39
+ postRequest = new Request("http://ex.com/test", {
40
+ method: "POST",
41
+ body: "csrfToken=" + csrfToken + "&username=bob&password=bobPass123",
42
+ headers: {
43
+ "cookie": "CSRFTOKEN=" + csrfCookieValue,
44
+ "content-type": "application/x-www-form-urlencoded",
45
+ }
46
+ });
47
+ event = new MockRequestEvent("1", postRequest, { "param1": "value1" });
48
+ event.locals.csrfToken = csrfToken;
49
+ ret = await server.sessionServer?.userEndpoints.logout(event);
50
+ expect(ret?.user).toBeUndefined();
51
+ expect(event.cookies.get("SESSIONID")).toBeUndefined();
52
+ });
53
+ test('SvelteKitUserEndpoints.resetPassword', async () => {
54
+ const { server, resolver, handle } = await makeServer();
55
+ // log in
56
+ await login(server, resolver, handle, "alice", "alicePass123");
57
+ const { csrfToken, csrfCookieValue } = await getCsrfToken(server, resolver, handle);
58
+ // @ts-ignore
59
+ server["sessionServer"]["sessionManager"]["tokenEmailer"]["_sendPasswordResetToken"] = async function (token, email, extraData) {
60
+ passwordResetData = { token, extraData };
61
+ };
62
+ // request password reset
63
+ let postRequest = new Request("http://ex.com/passwordreset", {
64
+ method: "POST",
65
+ body: "csrfToken=" + csrfToken + "&email=bob@bob.com",
66
+ headers: {
67
+ "cookie": "CSRFTOKEN=" + csrfCookieValue,
68
+ "content-type": "application/x-www-form-urlencoded",
69
+ }
70
+ });
71
+ let event = new MockRequestEvent("1", postRequest, {});
72
+ event.locals.csrfToken = csrfToken;
73
+ event.cookies.set("CSRFTOKEN", csrfCookieValue, { path: "/" });
74
+ let resp1 = await server.sessionServer?.userEndpoints.requestPasswordReset(event);
75
+ expect(resp1?.ok).toBe(true);
76
+ const token = passwordResetData.token;
77
+ // submit password reset
78
+ postRequest = new Request("http://ex.com/passwordreset/" + token, {
79
+ method: "POST",
80
+ body: "csrfToken=" + csrfToken + "&new_password='ABCabc123'&repeat_password='ABCabc123'",
81
+ headers: {
82
+ "cookie": "CSRFTOKEN=" + csrfCookieValue,
83
+ "content-type": "application/x-www-form-urlencoded",
84
+ }
85
+ });
86
+ event = new MockRequestEvent("1", postRequest, { token: token });
87
+ event.locals.csrfToken = csrfToken;
88
+ event.cookies.set("CSRFTOKEN", csrfCookieValue, { path: "/" });
89
+ resp1 = await server.sessionServer?.userEndpoints.resetPassword(event);
90
+ expect(resp1?.ok).toBe(true);
91
+ });
92
+ test('SvelteKitUserEndpoints.changePassword', async () => {
93
+ const { server, resolver, handle } = await makeServer();
94
+ // log in
95
+ let resp = await login(server, resolver, handle, "bob", "bobPass123");
96
+ let loginEvent = resp.event;
97
+ loginEvent = resp.event;
98
+ const { csrfToken, csrfCookieValue } = await getCsrfToken(server, resolver, handle);
99
+ let sessionCookieValue = loginEvent.cookies.get("SESSIONID");
100
+ let sessionId = server.sessionServer?.sessionManager.getSessionId(sessionCookieValue ?? "");
101
+ // change password
102
+ let postRequest = new Request("http://ex.com/changepassword", {
103
+ method: "POST",
104
+ body: "csrfToken=" + csrfToken + "&old_password=bobPass123&new_password=bobPass12&repeat_password=bobPass12",
105
+ headers: [
106
+ ["cookie", "CSRFTOKEN=" + csrfCookieValue],
107
+ ["cookie", "SESSIONID=" + sessionCookieValue],
108
+ ["content-type", "application/x-www-form-urlencoded"],
109
+ ]
110
+ });
111
+ let event = new MockRequestEvent("1", postRequest, {});
112
+ event.locals.csrfToken = csrfToken;
113
+ event.locals.sessionId = sessionId;
114
+ event.locals.authType = "cookie";
115
+ event.locals.user = loginEvent.locals.user;
116
+ let resp1 = await server.sessionServer?.userEndpoints.changePassword(event);
117
+ expect(resp1?.ok).toBe(true);
118
+ });
119
+ test('SvelteKitUserEndpoints.deleteUser', async () => {
120
+ const { server, resolver, handle, userStorage } = await makeServer();
121
+ // log in
122
+ let resp = await login(server, resolver, handle, "bob", "bobPass123");
123
+ let loginEvent = resp.event;
124
+ loginEvent = resp.event;
125
+ const { csrfToken, csrfCookieValue } = await getCsrfToken(server, resolver, handle);
126
+ let sessionCookieValue = loginEvent.cookies.get("SESSIONID");
127
+ let sessionId = server.sessionServer?.sessionManager.getSessionId(sessionCookieValue ?? "");
128
+ // delete user
129
+ let postRequest = new Request("http://ex.com/deleteuser", {
130
+ method: "POST",
131
+ body: "csrfToken=" + csrfToken,
132
+ headers: [
133
+ ["cookie", "CSRFTOKEN=" + csrfCookieValue],
134
+ ["cookie", "SESSIONID=" + sessionCookieValue],
135
+ ["content-type", "application/x-www-form-urlencoded"],
136
+ ]
137
+ });
138
+ let event = new MockRequestEvent("1", postRequest, {});
139
+ event.locals.csrfToken = csrfToken;
140
+ event.locals.sessionId = sessionId;
141
+ event.locals.authType = "cookie";
142
+ event.locals.user = loginEvent.locals.user;
143
+ let resp1 = await server.sessionServer?.userEndpoints.deleteUser(event);
144
+ expect(resp1?.ok).toBe(true);
145
+ let found = false;
146
+ try {
147
+ await userStorage.getUserByUsername("bob");
148
+ found = true;
149
+ }
150
+ catch (e) { }
151
+ expect(found).toBe(false);
152
+ });
@@ -0,0 +1,36 @@
1
+ // Copyright (c) 2026 Matthew Baker. All rights reserved. Licenced under the Apache Licence 2.0. See LICENSE file
2
+ import { MockRequestEvent, MockCookies } from './sveltemocks';
3
+ import { test, expect } from 'vitest';
4
+ test('SvelteMocks.Request', async () => {
5
+ const request = new Request("http://ex.com/test", { method: "POST", body: "This is the body" });
6
+ expect(request.body).not.toBe(null);
7
+ if (request.body)
8
+ expect(await (new Response(request.body).text())).toBe("This is the body");
9
+ });
10
+ test('SvelteMocks.MockRequestEvent', async () => {
11
+ const request = new Request("http://ex.com/test", { method: "POST", body: "This is the body" });
12
+ const requestEvent = new MockRequestEvent("1", request, { "param1": "value1" });
13
+ expect(requestEvent.route.id).toBe("1");
14
+ expect(requestEvent.params["param1"]).toBe("value1");
15
+ });
16
+ test('SvelteMocks.MockCookies', async () => {
17
+ const cookies = new MockCookies({
18
+ "cookie1": { value: "value1", opts: { maxAge: 120, domain: "http://example1.com" } },
19
+ "cookie2": { value: "value&2", opts: { maxAge: 140, domain: "http://example2.com" } },
20
+ });
21
+ // get cookie
22
+ let value1 = await cookies.get("cookie1");
23
+ expect(value1).toBe("value1");
24
+ let value2 = await cookies.get("cookie2");
25
+ expect(value2).toBe("value&2");
26
+ // get all
27
+ let values = await cookies.getAll();
28
+ expect(values.length).toBe(2);
29
+ // set cookie
30
+ await cookies.set("cookie1", "value3", { maxAge: 120, domain: "http://example3.com", path: "/" });
31
+ value1 = await cookies.get("cookie1");
32
+ expect(value1).toBe("value3");
33
+ await cookies.delete("cookie1", { path: "/" });
34
+ value1 = await cookies.get("cookie1");
35
+ expect(value1).toBe(undefined);
36
+ });
@@ -1,6 +1,16 @@
1
- import { Cookies, RequestEvent, MaybePromise, ResolveOptions } from '@sveltejs/kit';
2
- import { CookieParseOptions, CookieSerializeOptions } from 'cookie';
3
-
1
+ import { type Cookies, type ResolveOptions } from '@sveltejs/kit';
2
+ import { type CookieParseOptions, type CookieSerializeOptions } from 'cookie';
3
+ export interface AppTypes {
4
+ RouteId(): string;
5
+ RouteParams(): Record<string, Record<string, string>>;
6
+ LayoutParams(): Record<string, Record<string, string>>;
7
+ Pathname(): string;
8
+ ResolvedPathname(): string;
9
+ Asset(): string;
10
+ }
11
+ declare type RouteId1 = string;
12
+ export type LayoutParams<T extends RouteId1> = T extends keyof ReturnType<AppTypes['LayoutParams']> ? ReturnType<AppTypes['LayoutParams']>[T] : Record<string, never>;
13
+ export type MaybePromise<T> = T | Promise<T>;
4
14
  export declare class MockCookies implements Cookies {
5
15
  cookies: {
6
16
  [key: string]: {
@@ -29,9 +39,7 @@ export declare class MockCookies implements Cookies {
29
39
  path: string;
30
40
  }): string;
31
41
  }
32
- export declare class MockRequestEvent<Params extends Partial<Record<string, string>> = {
33
- [key: string]: string;
34
- }, RouteId extends string | null = string> implements RequestEvent<Params, RouteId> {
42
+ export declare class MockRequestEvent<Params extends LayoutParams<'/'> = LayoutParams<'/'>, RouteId extends RouteId1 | null = RouteId1 | null> {
35
43
  constructor(id: RouteId, request: Request, params: Params, { isDataRequest, isSubRequest, cookies, baseUrl }?: {
36
44
  isDataRequest?: boolean;
37
45
  isSubRequest?: boolean;
@@ -53,20 +61,26 @@ export declare class MockRequestEvent<Params extends Partial<Record<string, stri
53
61
  route: {
54
62
  id: RouteId;
55
63
  };
56
- headers: {
64
+ headers?: {
57
65
  [key: string]: string;
58
66
  } | undefined;
59
67
  setHeaders(headers: Record<string, string>): void;
60
68
  url: URL;
61
69
  isDataRequest: boolean;
62
70
  isSubRequest: boolean;
71
+ tracing: {
72
+ enabled: boolean;
73
+ root: any;
74
+ current: any;
75
+ };
76
+ isRemoteRequest: boolean;
63
77
  }
64
78
  export interface MockResolveOptions extends ResolveOptions {
65
79
  body?: string;
66
80
  status?: number;
67
81
  statusText?: string;
68
82
  }
69
- type MockResolve = (event: MockRequestEvent, _opts?: ResolveOptions) => MaybePromise<Response>;
83
+ type MockResolve = (event: MockRequestEvent<Record<string, string>, string | null>, _opts?: ResolveOptions | undefined) => MaybePromise<Response>;
70
84
  export declare class MockResolver {
71
85
  body: string | undefined;
72
86
  status: number;
@@ -0,0 +1,114 @@
1
+ // Copyright (c) 2026 Matthew Baker. All rights reserved. Licenced under the Apache Licence 2.0. See LICENSE file
2
+ import {} from '@sveltejs/kit';
3
+ import cookie, {} from 'cookie';
4
+ export class MockCookies {
5
+ cookies;
6
+ constructor(cookies, req) {
7
+ this.cookies = cookies;
8
+ if (req) {
9
+ const reqCookiesString = req.headers.get("cookie");
10
+ if (reqCookiesString) {
11
+ const reqCookies = reqCookiesString.split(";");
12
+ for (let reqCookie of reqCookies) {
13
+ const pair = reqCookie.trim().split("=", 2);
14
+ if (pair.length == 2) {
15
+ const name = decodeURIComponent(pair[0]);
16
+ const value = decodeURIComponent(pair[1]);
17
+ this.cookies[name] = { value: value };
18
+ }
19
+ }
20
+ }
21
+ }
22
+ }
23
+ get(name, opts) {
24
+ // opts is ignored on the assumption
25
+ const decoder = opts?.decode ?? "decodeURIComponent";
26
+ if (name in this.cookies)
27
+ return eval(decoder + "('" + this.cookies[name].value + "')");
28
+ return undefined;
29
+ }
30
+ getAll(opts) {
31
+ const decoder = opts?.decode ?? "decodeURIComponent";
32
+ let ret = [];
33
+ for (let name in this.cookies)
34
+ ret.push({ name: name, value: eval(decoder + "('" + this.cookies[name].value + "')") });
35
+ return ret;
36
+ }
37
+ set(name, value, opts) {
38
+ this.cookies[name] = { value, opts };
39
+ }
40
+ delete(name, _opts) {
41
+ if (name in this.cookies)
42
+ delete this.cookies[name];
43
+ }
44
+ serialize(name, value, opts) {
45
+ return cookie.serialize(name, value, opts);
46
+ }
47
+ }
48
+ export class MockRequestEvent {
49
+ constructor(id, request, params, { isDataRequest = false, isSubRequest = false, cookies = {}, baseUrl = "http://example.com" } = {}) {
50
+ this.cookies = new MockCookies(cookies, request);
51
+ this.fetch = fetch;
52
+ this.locals = { authType: undefined };
53
+ this.params = params;
54
+ this.request = request;
55
+ try {
56
+ this.url = new URL(request.url);
57
+ }
58
+ catch (e) {
59
+ this.url = new URL(request.url, baseUrl);
60
+ }
61
+ this.isDataRequest = isDataRequest;
62
+ this.isSubRequest = isSubRequest;
63
+ this.route = { id: id };
64
+ this.tracing = { enabled: false, root: "", current: "" };
65
+ this.isRemoteRequest = false;
66
+ }
67
+ cookies;
68
+ fetch;
69
+ getClientAddress() {
70
+ throw new Error('Method not implemented.');
71
+ }
72
+ locals;
73
+ params;
74
+ platform;
75
+ request;
76
+ route;
77
+ headers = undefined;
78
+ setHeaders(headers) {
79
+ this.headers = headers;
80
+ }
81
+ url;
82
+ isDataRequest;
83
+ isSubRequest;
84
+ tracing;
85
+ isRemoteRequest;
86
+ }
87
+ export class MockResolver {
88
+ body;
89
+ status;
90
+ statusText;
91
+ constructor(body, status = 200, statusText = "OK") {
92
+ this.body = body;
93
+ this.status = status;
94
+ this.statusText = statusText;
95
+ this.mockResolve = (event, _opts) => {
96
+ let headers = [];
97
+ for (let header in event.headers) {
98
+ headers.push([header, event.headers[header]]);
99
+ }
100
+ let cookies = event.cookies.getAll();
101
+ if (cookies && cookies.length > 0) {
102
+ for (let cookie of cookies) {
103
+ headers.push(["set-cookie", cookie.name + "=" + cookie.value]);
104
+ }
105
+ }
106
+ return new Response(this.body, {
107
+ headers: headers,
108
+ status: this.status ?? 200,
109
+ statusText: this.statusText ?? "OK",
110
+ });
111
+ };
112
+ }
113
+ mockResolve;
114
+ }