@webda/graphql 4.0.0-beta.1 → 4.0.0-beta.2
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/lib/graphql.d.ts +6 -3
- package/lib/graphql.d.ts.map +1 -0
- package/lib/graphql.js +32 -32
- package/lib/graphql.js.map +1 -1
- package/lib/graphql.spec.d.ts +2 -0
- package/lib/graphql.spec.d.ts.map +1 -0
- package/lib/graphql.spec.js +669 -0
- package/lib/graphql.spec.js.map +1 -0
- package/lib/types/any.d.ts +1 -0
- package/lib/types/any.d.ts.map +1 -0
- package/lib/types/date.d.ts +1 -0
- package/lib/types/date.d.ts.map +1 -0
- package/lib/types/long.d.ts +1 -0
- package/lib/types/long.d.ts.map +1 -0
- package/package.json +15 -14
- package/webda.module.json +4 -6
|
@@ -0,0 +1,669 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { suite, test } from "@testdeck/mocha";
|
|
8
|
+
import { FileBinary, HttpContext, SecureCookie, Service, WebdaError, getCommonJS } from "@webda/core";
|
|
9
|
+
import { WebdaTest } from "@webda/core/lib/test.js";
|
|
10
|
+
import { ServerStatus, WebdaServer } from "@webda/shell";
|
|
11
|
+
import { WebdaSampleApplication } from "@webda/shell/lib/index.spec.js";
|
|
12
|
+
import * as assert from "assert";
|
|
13
|
+
import { Kind } from "graphql";
|
|
14
|
+
import { createClient } from "graphql-ws";
|
|
15
|
+
import * as path from "path";
|
|
16
|
+
import WebSocket from "ws";
|
|
17
|
+
import { GraphQLService } from "./graphql.js";
|
|
18
|
+
import { AnyScalarType } from "./types/any.js";
|
|
19
|
+
import { DateScalar } from "./types/date.js";
|
|
20
|
+
import { GraphQLLong } from "./types/long.js";
|
|
21
|
+
const { __dirname } = getCommonJS(import.meta.url);
|
|
22
|
+
class MyWebSocket extends WebSocket {
|
|
23
|
+
constructor(address, protocols) {
|
|
24
|
+
super(address, protocols, {
|
|
25
|
+
headers: MyWebSocket.headers
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
MyWebSocket.headers = {};
|
|
30
|
+
class FakeService extends Service {
|
|
31
|
+
getClientEvents() {
|
|
32
|
+
return ["test", "test2"];
|
|
33
|
+
}
|
|
34
|
+
authorizeClientEvent(_event, _context) {
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
let GraphQLServiceTest = class GraphQLServiceTest extends WebdaTest {
|
|
39
|
+
async before() {
|
|
40
|
+
await super.before();
|
|
41
|
+
await this.registerService(new FileBinary(this.webda, "filebinary", { folder: "./test/binaries", models: { "*": ["*"] } }));
|
|
42
|
+
this.service = await this.registerService(new GraphQLService(this.webda, "graphql")).resolve().init();
|
|
43
|
+
}
|
|
44
|
+
getTestConfiguration() {
|
|
45
|
+
return path.resolve(`${__dirname}/../../../sample-app/`);
|
|
46
|
+
}
|
|
47
|
+
async createLocalGraphObjects() {
|
|
48
|
+
const Teacher = this.webda.getModel("Teacher");
|
|
49
|
+
const Company = this.webda.getModel("Company");
|
|
50
|
+
const User = this.webda.getModel("User");
|
|
51
|
+
let i = 1;
|
|
52
|
+
// 2 Teachers
|
|
53
|
+
await Teacher.create({ name: "test" });
|
|
54
|
+
await Teacher.create({ name: "test2" });
|
|
55
|
+
// 2 Companies
|
|
56
|
+
const companies = [await Company.create({ name: "company 1" }), await Company.create({ name: "company 2" })];
|
|
57
|
+
const users = [];
|
|
58
|
+
for (const conpany of companies) {
|
|
59
|
+
users.push(await User.create({
|
|
60
|
+
name: `User ${i++}`,
|
|
61
|
+
_company: conpany.uuid
|
|
62
|
+
}));
|
|
63
|
+
}
|
|
64
|
+
return { companies, users };
|
|
65
|
+
}
|
|
66
|
+
async query() {
|
|
67
|
+
const { users } = await this.createLocalGraphObjects();
|
|
68
|
+
let q = `{ Teachers(query:"") { results { name, _lastUpdate, uuid } }, Teacher(uuid:"test") { name } }`;
|
|
69
|
+
let result = await this.http({
|
|
70
|
+
method: "POST",
|
|
71
|
+
url: "/graphql",
|
|
72
|
+
body: `{"query": "${q.replace(/"/g, '\\"')}"}`,
|
|
73
|
+
headers: {
|
|
74
|
+
"content-type": "application/json; charset=utf-8"
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
assert.strictEqual(result.data.Teachers.results.length, 0);
|
|
78
|
+
assert.strictEqual(result.errors[0].message, "Object not found");
|
|
79
|
+
const context = await this.newContext();
|
|
80
|
+
context.getSession().login("test", "test");
|
|
81
|
+
result = await this.http({
|
|
82
|
+
method: "POST",
|
|
83
|
+
url: "/graphql",
|
|
84
|
+
body: `{"query": "${q.replace(/"/g, '\\"')}"}`,
|
|
85
|
+
headers: {
|
|
86
|
+
"content-type": "application/json; charset=utf-8"
|
|
87
|
+
},
|
|
88
|
+
context
|
|
89
|
+
});
|
|
90
|
+
assert.strictEqual(result.data.Teachers.results.length, 2);
|
|
91
|
+
const uuid = result.data.Teachers.results[0].uuid;
|
|
92
|
+
q = `{ Teacher(uuid:"${uuid}") { name } }`;
|
|
93
|
+
result = await this.http({
|
|
94
|
+
method: "POST",
|
|
95
|
+
url: "/graphql",
|
|
96
|
+
body: `{"query": "${q.replace(/"/g, '\\"')}"}`,
|
|
97
|
+
headers: {
|
|
98
|
+
"content-type": "application/json; charset=utf-8"
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
assert.strictEqual(result.errors[0].message, "Permission denied");
|
|
102
|
+
context.getSession().login("test", "test");
|
|
103
|
+
q = `{ Teacher(uuid:"${uuid}") { name } }`;
|
|
104
|
+
result = await this.http({
|
|
105
|
+
method: "POST",
|
|
106
|
+
url: "/graphql",
|
|
107
|
+
body: `{"query": "${q.replace(/"/g, '\\"')}"}`,
|
|
108
|
+
headers: {
|
|
109
|
+
"content-type": "application/json; charset=utf-8"
|
|
110
|
+
},
|
|
111
|
+
context
|
|
112
|
+
});
|
|
113
|
+
assert.strictEqual(result.errors, undefined);
|
|
114
|
+
assert.strictEqual(result.data.Teacher.name, "test");
|
|
115
|
+
q = `{ Companies { results { name, users { results { name } } } } }`;
|
|
116
|
+
result = await this.http({
|
|
117
|
+
method: "POST",
|
|
118
|
+
url: "/graphql",
|
|
119
|
+
body: `{"query": "${q.replace(/"/g, '\\"')}"}`,
|
|
120
|
+
headers: {
|
|
121
|
+
"content-type": "application/json; charset=utf-8"
|
|
122
|
+
},
|
|
123
|
+
context
|
|
124
|
+
});
|
|
125
|
+
assert.strictEqual(result.errors, undefined);
|
|
126
|
+
context.getSession().login(users[1].uuid, users[1].uuid);
|
|
127
|
+
q = `{ Me { name, computers { results { name } } } }`;
|
|
128
|
+
result = await this.http({
|
|
129
|
+
method: "POST",
|
|
130
|
+
url: "/graphql",
|
|
131
|
+
body: `{"query": "${q.replace(/"/g, '\\"')}"}`,
|
|
132
|
+
headers: {
|
|
133
|
+
"content-type": "application/json; charset=utf-8"
|
|
134
|
+
},
|
|
135
|
+
context
|
|
136
|
+
});
|
|
137
|
+
assert.notStrictEqual(result.data.Me.computers, undefined);
|
|
138
|
+
}
|
|
139
|
+
async coreGraph() {
|
|
140
|
+
await this.createGraphObjects();
|
|
141
|
+
const context = await this.newContext();
|
|
142
|
+
context.getSession().login("test", "test");
|
|
143
|
+
let q = `{ Courses { results { uuid, name, teacher { name, uuid }, classroom { name, uuid }, students { email } } } }`;
|
|
144
|
+
let result = await this.http({
|
|
145
|
+
method: "POST",
|
|
146
|
+
url: "/graphql",
|
|
147
|
+
body: `{"query": "${q.replace(/"/g, '\\"')}"}`,
|
|
148
|
+
headers: {
|
|
149
|
+
"content-type": "application/json; charset=utf-8"
|
|
150
|
+
},
|
|
151
|
+
context
|
|
152
|
+
});
|
|
153
|
+
// Expect some errors for Too many operations
|
|
154
|
+
assert.strictEqual(result.errors.filter(err => err.message === "Too many operations").length, 14);
|
|
155
|
+
this.service.getParameters().maxOperationsPerRequest = 30;
|
|
156
|
+
result = await this.http({
|
|
157
|
+
method: "POST",
|
|
158
|
+
url: "/graphql",
|
|
159
|
+
body: `{"query": "${q.replace(/"/g, '\\"')}"}`,
|
|
160
|
+
headers: {
|
|
161
|
+
"content-type": "application/json; charset=utf-8"
|
|
162
|
+
},
|
|
163
|
+
context
|
|
164
|
+
});
|
|
165
|
+
assert.strictEqual(context.getExtension("graphql").count, 24);
|
|
166
|
+
q = `{ Courses { results { uuid, students(filter:"email LIKE '%4%'") { email } } } }`;
|
|
167
|
+
result = await this.http({
|
|
168
|
+
method: "POST",
|
|
169
|
+
url: "/graphql",
|
|
170
|
+
body: `{"query": "${q.replace(/"/g, '\\"')}"}`,
|
|
171
|
+
headers: {
|
|
172
|
+
"content-type": "application/json; charset=utf-8"
|
|
173
|
+
},
|
|
174
|
+
context
|
|
175
|
+
});
|
|
176
|
+
assert.strictEqual(result.data.Courses.results.map(c => c.students).filter(i => i.length > 0).length, 8);
|
|
177
|
+
q = `{ Courses { results { uuid, students(filter:"order > 7 AND email LIKE '%webda.io'") { email } } } }`;
|
|
178
|
+
result = await this.http({
|
|
179
|
+
method: "POST",
|
|
180
|
+
url: "/graphql",
|
|
181
|
+
body: `{"query": "${q.replace(/"/g, '\\"')}"}`,
|
|
182
|
+
headers: {
|
|
183
|
+
"content-type": "application/json; charset=utf-8"
|
|
184
|
+
},
|
|
185
|
+
context
|
|
186
|
+
});
|
|
187
|
+
assert.strictEqual(result.data.Courses.results.map(c => c.students).filter(i => i !== null && i.length > 0).length, 4);
|
|
188
|
+
const course = result.data.Courses.results[0];
|
|
189
|
+
q = `{ Course(uuid: "${course.uuid}") { classroom { uuid, name, courses { uuid }, hardwares { results { uuid, classroom { uuid } } } } } }`;
|
|
190
|
+
result = await this.http({
|
|
191
|
+
method: "POST",
|
|
192
|
+
url: "/graphql",
|
|
193
|
+
body: `{"query": "${q.replace(/"/g, '\\"')}"}`,
|
|
194
|
+
headers: {
|
|
195
|
+
"content-type": "application/json; charset=utf-8"
|
|
196
|
+
},
|
|
197
|
+
context
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
async graphiql() {
|
|
201
|
+
this.service.getParameters().exposeGraphiQL = true;
|
|
202
|
+
let body = await this.http({
|
|
203
|
+
url: "/graphql",
|
|
204
|
+
headers: {
|
|
205
|
+
"content-type": "application/json; charset=utf-8"
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
assert.ok(body.includes("graphiql.min.js"), "Should contain graphiql");
|
|
209
|
+
// Ensure {{URL}} is replaced
|
|
210
|
+
assert.ok(body.includes("http://test.webda.io/graphql"), "Should contain graphiql");
|
|
211
|
+
body = await this.http({
|
|
212
|
+
url: "/graphql",
|
|
213
|
+
headers: {
|
|
214
|
+
"content-type": "application/json; charset=utf-8",
|
|
215
|
+
"X-GraphiQL-Schema": "true"
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
assert.ok(body.includes("type Query"), "Should contain schema");
|
|
219
|
+
assert.ok(body.match(/type Query {[\w\W]*Teacher\(uuid: String\): Teacher[\w\W]*Me: User[\w\W]*}/gm), "Should contain schema");
|
|
220
|
+
// Check schema is retrieved
|
|
221
|
+
this.service.getParameters().exposeGraphiQL = false;
|
|
222
|
+
// Check for Companies and Company
|
|
223
|
+
await assert.rejects(() => this.http({
|
|
224
|
+
url: "/graphql",
|
|
225
|
+
headers: {
|
|
226
|
+
"content-type": "application/json; charset=utf-8"
|
|
227
|
+
}
|
|
228
|
+
}), WebdaError.NotFound);
|
|
229
|
+
}
|
|
230
|
+
async mutations() {
|
|
231
|
+
const context = await this.newContext();
|
|
232
|
+
// Test successfull creation and update
|
|
233
|
+
context.getSession().login("test", "test");
|
|
234
|
+
const Classroom = this.webda.getModel("Classroom");
|
|
235
|
+
let result = await this.http({
|
|
236
|
+
method: "POST",
|
|
237
|
+
url: "/graphql",
|
|
238
|
+
body: `{"query":"mutation createClassroom($classroom:ClassroomInput) { createClassroom(Classroom:$classroom) { name uuid }}","variables":{"classroom":{"name":"test","uuid":"test"}},"operationName":"createClassroom"}`,
|
|
239
|
+
headers: {
|
|
240
|
+
"content-type": "application/json; charset=utf-8"
|
|
241
|
+
},
|
|
242
|
+
context
|
|
243
|
+
});
|
|
244
|
+
assert.ok(await Classroom.ref("test").exists());
|
|
245
|
+
result = await this.http({
|
|
246
|
+
method: "POST",
|
|
247
|
+
url: "/graphql",
|
|
248
|
+
body: `{"query":"mutation updateClassroom($classroom:ClassroomInput) { updateClassroom(Classroom:$classroom, uuid:\\"test\\") { name _lastUpdate }}","variables":{"classroom":{"name":"test2"}},"operationName":"updateClassroom"}`,
|
|
249
|
+
headers: {
|
|
250
|
+
"content-type": "application/json; charset=utf-8"
|
|
251
|
+
},
|
|
252
|
+
context
|
|
253
|
+
});
|
|
254
|
+
assert.strictEqual((await Classroom.ref("test").get()).name, "test2");
|
|
255
|
+
// test2 user should not be able to do anything on Classroom
|
|
256
|
+
context.getSession().login("test2", "test2");
|
|
257
|
+
result = await this.http({
|
|
258
|
+
method: "POST",
|
|
259
|
+
url: "/graphql",
|
|
260
|
+
body: `{"query":"mutation createClassroom($classroom:ClassroomInput) { createClassroom(Classroom:$classroom) { name uuid }}","variables":{"classroom":{"name":"test2","uuid":"test2"}},"operationName":"createClassroom"}`,
|
|
261
|
+
headers: {
|
|
262
|
+
"content-type": "application/json; charset=utf-8"
|
|
263
|
+
},
|
|
264
|
+
context
|
|
265
|
+
});
|
|
266
|
+
assert.ok(!(await this.webda.getModel("Course").ref("test2").exists()));
|
|
267
|
+
result = await this.http({
|
|
268
|
+
method: "POST",
|
|
269
|
+
url: "/graphql",
|
|
270
|
+
body: `{"query":"mutation updateClassroom($classroom:ClassroomInput) { updateClassroom(Classroom:$classroom, uuid:\\"test\\") { name _lastUpdate }}","variables":{"classroom":{"name":"test3"}},"operationName":"updateClassroom"}`,
|
|
271
|
+
headers: {
|
|
272
|
+
"content-type": "application/json; charset=utf-8"
|
|
273
|
+
},
|
|
274
|
+
context
|
|
275
|
+
});
|
|
276
|
+
assert.strictEqual((await Classroom.ref("test").get()).name, "test2");
|
|
277
|
+
result = await this.http({
|
|
278
|
+
method: "POST",
|
|
279
|
+
url: "/graphql",
|
|
280
|
+
body: `{"query":"mutation deleteClassroom($uuid:String) { deleteClassroom(uuid:$uuid) { success }}","variables":{"uuid":"test"},"operationName":"deleteClassroom"}`,
|
|
281
|
+
headers: {
|
|
282
|
+
"content-type": "application/json; charset=utf-8"
|
|
283
|
+
},
|
|
284
|
+
context
|
|
285
|
+
});
|
|
286
|
+
assert.ok(await Classroom.ref("test").exists());
|
|
287
|
+
// Finally delete the test object
|
|
288
|
+
context.getSession().login("test", "test");
|
|
289
|
+
result = await this.http({
|
|
290
|
+
method: "POST",
|
|
291
|
+
url: "/graphql",
|
|
292
|
+
body: `{"query":"mutation deleteClassroom($uuid:String) { deleteClassroom(uuid:$uuid) { success }}","variables":{"uuid":"test"},"operationName":"deleteClassroom"}`,
|
|
293
|
+
headers: {
|
|
294
|
+
"content-type": "application/json; charset=utf-8"
|
|
295
|
+
},
|
|
296
|
+
context
|
|
297
|
+
});
|
|
298
|
+
assert.ok(!(await Classroom.ref("test").exists()));
|
|
299
|
+
}
|
|
300
|
+
async cov() {
|
|
301
|
+
this.service.app.addModel("WebdaDemo/User2", {
|
|
302
|
+
getSchema: () => undefined,
|
|
303
|
+
Expose: {
|
|
304
|
+
restrict: {},
|
|
305
|
+
root: true
|
|
306
|
+
},
|
|
307
|
+
getIdentifier: () => "WebdaDemo/User2",
|
|
308
|
+
getClientEvents: () => []
|
|
309
|
+
});
|
|
310
|
+
this.service.app.addModel("WebdaDemo/User3", {
|
|
311
|
+
getSchema: () => undefined,
|
|
312
|
+
Expose: {
|
|
313
|
+
restrict: {},
|
|
314
|
+
root: true
|
|
315
|
+
},
|
|
316
|
+
getIdentifier: () => "User3",
|
|
317
|
+
getClientEvents: () => []
|
|
318
|
+
});
|
|
319
|
+
this.service.app.addModel("WebdaDemo/Cov", {
|
|
320
|
+
getSchema: () => ({
|
|
321
|
+
type: "object",
|
|
322
|
+
properties: {
|
|
323
|
+
name: {
|
|
324
|
+
type: "object",
|
|
325
|
+
properties: {
|
|
326
|
+
name: {
|
|
327
|
+
type: "null"
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}),
|
|
333
|
+
getUuidField: () => "uuid",
|
|
334
|
+
Expose: {
|
|
335
|
+
restrict: {},
|
|
336
|
+
root: true
|
|
337
|
+
},
|
|
338
|
+
getClientEvents: () => [],
|
|
339
|
+
getIdentifier: () => "WebdaDemo/Cov"
|
|
340
|
+
});
|
|
341
|
+
this.service.app.addModel("WebdaDemo/Cov2", {
|
|
342
|
+
getSchema: () => ({
|
|
343
|
+
type: "object",
|
|
344
|
+
properties: {
|
|
345
|
+
name: {
|
|
346
|
+
type: "array",
|
|
347
|
+
items: {
|
|
348
|
+
$ref: "#/definitions/plop"
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
},
|
|
352
|
+
definitions: {
|
|
353
|
+
plop: {
|
|
354
|
+
type: "string"
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
}),
|
|
358
|
+
getUuidField: () => "uuid",
|
|
359
|
+
Expose: {
|
|
360
|
+
restrict: {},
|
|
361
|
+
root: true
|
|
362
|
+
},
|
|
363
|
+
getClientEvents: () => [],
|
|
364
|
+
getIdentifier: () => "WebdaDemo/Cov2"
|
|
365
|
+
});
|
|
366
|
+
this.service.getParameters().userModel = "User2";
|
|
367
|
+
this.service.getParameters()["excludedModels"].push("User3");
|
|
368
|
+
await this.service.resolve().init();
|
|
369
|
+
// Just for hitting the default GraphQLString
|
|
370
|
+
this.service.getGraphQLSchemaFromSchema({ type: "array", items: { type: "null" } }, "plop");
|
|
371
|
+
}
|
|
372
|
+
};
|
|
373
|
+
__decorate([
|
|
374
|
+
test
|
|
375
|
+
], GraphQLServiceTest.prototype, "query", null);
|
|
376
|
+
__decorate([
|
|
377
|
+
test
|
|
378
|
+
], GraphQLServiceTest.prototype, "coreGraph", null);
|
|
379
|
+
__decorate([
|
|
380
|
+
test
|
|
381
|
+
], GraphQLServiceTest.prototype, "graphiql", null);
|
|
382
|
+
__decorate([
|
|
383
|
+
test
|
|
384
|
+
], GraphQLServiceTest.prototype, "mutations", null);
|
|
385
|
+
__decorate([
|
|
386
|
+
test
|
|
387
|
+
], GraphQLServiceTest.prototype, "cov", null);
|
|
388
|
+
GraphQLServiceTest = __decorate([
|
|
389
|
+
suite
|
|
390
|
+
], GraphQLServiceTest);
|
|
391
|
+
let GraphQLSubscriptionTest = class GraphQLSubscriptionTest {
|
|
392
|
+
async subscriptions() {
|
|
393
|
+
let fake;
|
|
394
|
+
await WebdaSampleApplication.load();
|
|
395
|
+
WebdaSampleApplication.getConfiguration().services.graphql = {
|
|
396
|
+
type: "GraphQLService",
|
|
397
|
+
exposeMe: true
|
|
398
|
+
};
|
|
399
|
+
WebdaSampleApplication.getConfiguration().services.fake = {
|
|
400
|
+
type: "FakeService"
|
|
401
|
+
};
|
|
402
|
+
WebdaSampleApplication.addService("FakeService", FakeService);
|
|
403
|
+
const server = new WebdaServer(WebdaSampleApplication);
|
|
404
|
+
const Course = server.getModel("Course");
|
|
405
|
+
const User = server.getModel("WebdaDemo/User");
|
|
406
|
+
try {
|
|
407
|
+
await server.init();
|
|
408
|
+
fake = server.getService("fake");
|
|
409
|
+
await Course.store().__clean();
|
|
410
|
+
await Course.ref("test").getOrCreate({
|
|
411
|
+
name: "test"
|
|
412
|
+
});
|
|
413
|
+
server.serve(28080);
|
|
414
|
+
await server.waitForStatus(ServerStatus.Started);
|
|
415
|
+
const client = createClient({
|
|
416
|
+
url: "ws://localhost:28080/graphql",
|
|
417
|
+
webSocketImpl: MyWebSocket
|
|
418
|
+
});
|
|
419
|
+
// subscription for change
|
|
420
|
+
console.log("Starting subscription on Course(test)");
|
|
421
|
+
await (async () => {
|
|
422
|
+
const subscription = client.iterate({
|
|
423
|
+
query: `subscription { Course(uuid:"test") { name uuid } }`
|
|
424
|
+
});
|
|
425
|
+
for await (const event of subscription) {
|
|
426
|
+
const obj = event.data?.Course;
|
|
427
|
+
if (obj === null) {
|
|
428
|
+
break;
|
|
429
|
+
}
|
|
430
|
+
else if (obj.name === "test2") {
|
|
431
|
+
Course.ref("test").delete();
|
|
432
|
+
}
|
|
433
|
+
else {
|
|
434
|
+
Course.ref("test").patch({ name: "test2" });
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
})();
|
|
438
|
+
// subscription for change on non-existing
|
|
439
|
+
console.log("Starting subscription on Course(test2)", await Course.ref("test2").get());
|
|
440
|
+
await (async () => {
|
|
441
|
+
const subscription = client.iterate({
|
|
442
|
+
query: `subscription { Course(uuid:"test2") { name uuid } }`
|
|
443
|
+
});
|
|
444
|
+
for await (const event of subscription) {
|
|
445
|
+
}
|
|
446
|
+
})();
|
|
447
|
+
// subscription for new object
|
|
448
|
+
console.log("Starting subscription on Courses()");
|
|
449
|
+
await Course.ref("test").getOrCreate({
|
|
450
|
+
name: "test",
|
|
451
|
+
value: 10
|
|
452
|
+
});
|
|
453
|
+
await Course.ref("test2").getOrCreate({
|
|
454
|
+
name: "test2",
|
|
455
|
+
value: 10
|
|
456
|
+
});
|
|
457
|
+
let i = 0;
|
|
458
|
+
await (async () => {
|
|
459
|
+
const subscription = client.iterate({
|
|
460
|
+
query: `subscription { Courses(query:"value=10") { results { name uuid } continuationToken } }`
|
|
461
|
+
});
|
|
462
|
+
// Test several use case
|
|
463
|
+
for await (const evt of subscription) {
|
|
464
|
+
const event = evt;
|
|
465
|
+
i++;
|
|
466
|
+
if (i === 1) {
|
|
467
|
+
// Update test2
|
|
468
|
+
await Course.ref("test2").patch({ name: "test2b" });
|
|
469
|
+
}
|
|
470
|
+
else if (i === 2) {
|
|
471
|
+
// Create test3
|
|
472
|
+
assert.strictEqual(event.data?.Courses.results[1].name, "test2b");
|
|
473
|
+
await Course.ref("test3").getOrCreate({ name: "test3", value: 10 });
|
|
474
|
+
// This one should not trigger anything
|
|
475
|
+
await Course.ref("test4").getOrCreate({ name: "test4", value: 1 });
|
|
476
|
+
}
|
|
477
|
+
else if (i === 3) {
|
|
478
|
+
// Delete test
|
|
479
|
+
assert.strictEqual(event.data?.Courses.results.length, 3);
|
|
480
|
+
await Course.ref("test").delete();
|
|
481
|
+
}
|
|
482
|
+
else if (i === 4) {
|
|
483
|
+
// Finishing the test
|
|
484
|
+
assert.deepStrictEqual(event.data?.Courses.results.map(c => c.name), ["test2b", "test3"]);
|
|
485
|
+
break;
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
})();
|
|
489
|
+
// subscription for me
|
|
490
|
+
console.log("Starting subscription on Me w/o auth");
|
|
491
|
+
await (async () => {
|
|
492
|
+
const subscription = client.iterate({
|
|
493
|
+
query: `subscription { Me { name } }`
|
|
494
|
+
});
|
|
495
|
+
for await (const event of subscription) {
|
|
496
|
+
if (event) {
|
|
497
|
+
break;
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
})();
|
|
501
|
+
console.log("Starting subscription on MeEvents w/o auth");
|
|
502
|
+
await assert.rejects(async () => {
|
|
503
|
+
const subscription = client.iterate({
|
|
504
|
+
query: `subscription { MeEvents { logout } }`
|
|
505
|
+
});
|
|
506
|
+
for await (const event of subscription) {
|
|
507
|
+
if (event.errors) {
|
|
508
|
+
throw event.errors[0];
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
}, (err) => err.message === "Permission denied");
|
|
512
|
+
// Close client
|
|
513
|
+
await client.dispose();
|
|
514
|
+
// Test with a cookie
|
|
515
|
+
User.ref("test").create({ name: "plop" });
|
|
516
|
+
const ctx = await server.newWebContext(new HttpContext("test.webda.io", "GET", "/graphql"));
|
|
517
|
+
await SecureCookie.save("webda", ctx, { userId: "test" });
|
|
518
|
+
// Test with a cookie
|
|
519
|
+
MyWebSocket.headers.Cookie = `webda=${ctx._cookie["webda"].value}`;
|
|
520
|
+
const client2 = createClient({
|
|
521
|
+
url: "ws://localhost:28080/graphql",
|
|
522
|
+
webSocketImpl: MyWebSocket
|
|
523
|
+
});
|
|
524
|
+
i = 0;
|
|
525
|
+
console.log("Starting subscription on Me with auth");
|
|
526
|
+
await (async () => {
|
|
527
|
+
const subscription = client2.iterate({
|
|
528
|
+
query: `subscription { Me { name } }`
|
|
529
|
+
});
|
|
530
|
+
for await (const evt of subscription) {
|
|
531
|
+
const event = evt;
|
|
532
|
+
i++;
|
|
533
|
+
if (i === 1) {
|
|
534
|
+
assert.strictEqual(event.data?.Me.name, "plop");
|
|
535
|
+
await User.ref("test").patch({ name: "plop2" });
|
|
536
|
+
}
|
|
537
|
+
else if (i === 2) {
|
|
538
|
+
assert.strictEqual(event.data?.Me.name, "plop2");
|
|
539
|
+
break;
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
})();
|
|
543
|
+
console.log("Starting subscription aggregation");
|
|
544
|
+
i = 0;
|
|
545
|
+
await (async () => {
|
|
546
|
+
const subscription = client2.iterate({
|
|
547
|
+
// Courses(query:"value=10") { name uuid } CoursesEvents(events:["test2"]) { } CourseEvents(uuid:"test", events:["plop"]) { }
|
|
548
|
+
query: `subscription { Aggregate { Me { name } Courses(query:"value=10") { results { name uuid } } Course(uuid:"test2") { uuid name } CourseEvents(uuid:"test3") { test test4 } CoursesEvents { test2 } MeEvents { logout } } }`
|
|
549
|
+
});
|
|
550
|
+
for await (const evt of subscription) {
|
|
551
|
+
const event = evt;
|
|
552
|
+
i++;
|
|
553
|
+
if (i === 1) {
|
|
554
|
+
assert.strictEqual(event.data?.Aggregate.Me.name, "plop2");
|
|
555
|
+
// Update test2
|
|
556
|
+
await Course.ref("test2").patch({ name: "test2c" });
|
|
557
|
+
}
|
|
558
|
+
else if (i === 2) {
|
|
559
|
+
// no-op
|
|
560
|
+
}
|
|
561
|
+
else if (i === 3) {
|
|
562
|
+
await User.store().emitSync("logout", { test2: "test2", object_id: "test" });
|
|
563
|
+
}
|
|
564
|
+
else if (i === 4) {
|
|
565
|
+
assert.ok(event.data?.Aggregate.Courses.results[0].name === "test2c" &&
|
|
566
|
+
event.data?.Aggregate.Course.name === "test2c");
|
|
567
|
+
assert.strictEqual(event.data?.Aggregate.MeEvents.logout?.test2, "test2");
|
|
568
|
+
Course.store().emitSync("test", { object_id: "test3", type: "test1" });
|
|
569
|
+
}
|
|
570
|
+
else if (i === 5) {
|
|
571
|
+
assert.deepStrictEqual(event.data.Aggregate.CourseEvents.test, {
|
|
572
|
+
object_id: "test3",
|
|
573
|
+
type: "test1"
|
|
574
|
+
});
|
|
575
|
+
Course.store().emitSync("test4", { object_id: "test3", type: "test4" });
|
|
576
|
+
}
|
|
577
|
+
else if (i === 6) {
|
|
578
|
+
assert.deepStrictEqual(event.data.Aggregate.CourseEvents.test4, {
|
|
579
|
+
object_id: "test3",
|
|
580
|
+
type: "test4"
|
|
581
|
+
});
|
|
582
|
+
break;
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
})();
|
|
586
|
+
console.log("Starting subscription aggregation with wrong permission");
|
|
587
|
+
i = 0;
|
|
588
|
+
await assert.rejects(async () => {
|
|
589
|
+
const subscription = client2.iterate({
|
|
590
|
+
query: `subscription { CourseEvents(uuid:"test") { test3 } }`
|
|
591
|
+
});
|
|
592
|
+
for await (const evt of subscription) {
|
|
593
|
+
if (evt.errors) {
|
|
594
|
+
throw evt.errors[0];
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
}, (err) => err.message === "Permission denied");
|
|
598
|
+
/* TODO Reenable
|
|
599
|
+
console.log("Starting subscription service");
|
|
600
|
+
i = 0;
|
|
601
|
+
await (async () => {
|
|
602
|
+
const subscription = client2.iterate({
|
|
603
|
+
// Courses(query:"value=10") { name uuid } CoursesEvents(events:["test2"]) { } CourseEvents(uuid:"test", events:["plop"]) { }
|
|
604
|
+
query: `subscription { fakeEvents { test } }`
|
|
605
|
+
});
|
|
606
|
+
for await (const evt of subscription) {
|
|
607
|
+
const event: any = evt;
|
|
608
|
+
i++;
|
|
609
|
+
if (i === 1) {
|
|
610
|
+
fake.emit("test", { test: "test" });
|
|
611
|
+
} else if (i === 2) {
|
|
612
|
+
// no-op
|
|
613
|
+
break;
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
})();
|
|
617
|
+
*/
|
|
618
|
+
}
|
|
619
|
+
finally {
|
|
620
|
+
await Course.store().__clean();
|
|
621
|
+
await server.stop();
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
};
|
|
625
|
+
__decorate([
|
|
626
|
+
test
|
|
627
|
+
], GraphQLSubscriptionTest.prototype, "subscriptions", null);
|
|
628
|
+
GraphQLSubscriptionTest = __decorate([
|
|
629
|
+
suite
|
|
630
|
+
], GraphQLSubscriptionTest);
|
|
631
|
+
let TypesTest = class TypesTest {
|
|
632
|
+
any() {
|
|
633
|
+
const obj = { test: 1 };
|
|
634
|
+
AnyScalarType.parseValue(obj);
|
|
635
|
+
AnyScalarType.parseValue(JSON.stringify(obj));
|
|
636
|
+
AnyScalarType.parseLiteral({ kind: Kind.STRING, value: JSON.stringify(obj) });
|
|
637
|
+
assert.throws(() => AnyScalarType.parseLiteral({ kind: Kind.OBJECT }), /Not sure what to do with OBJECT for ObjectScalarType/);
|
|
638
|
+
assert.strictEqual(AnyScalarType.parseLiteral({ kind: Kind.BOOLEAN }), null);
|
|
639
|
+
}
|
|
640
|
+
long() {
|
|
641
|
+
GraphQLLong.parseValue("12344444");
|
|
642
|
+
assert.throws(() => GraphQLLong.parseValue(""));
|
|
643
|
+
assert.throws(() => GraphQLLong.parseValue("123456789012345678901234567890"), /Long cannot represent/);
|
|
644
|
+
assert.strictEqual(GraphQLLong.parseLiteral({ kind: Kind.BOOLEAN }), null);
|
|
645
|
+
assert.strictEqual(GraphQLLong.parseLiteral({ kind: Kind.INT, value: "−9007199254740992" }), null);
|
|
646
|
+
assert.strictEqual(GraphQLLong.parseLiteral({ kind: Kind.INT, value: "9007199254740992" }), null);
|
|
647
|
+
assert.strictEqual(GraphQLLong.parseLiteral({ kind: Kind.INT, value: "12345" }), 12345);
|
|
648
|
+
}
|
|
649
|
+
date() {
|
|
650
|
+
assert.ok(DateScalar.parseValue("2020-01-01T00:00:00.000Z") instanceof Date);
|
|
651
|
+
assert.throws(() => DateScalar.parseValue(12), /GraphQL Date Scalar parser expected a `string`/);
|
|
652
|
+
assert.throws(() => DateScalar.serialize("test"), /GraphQL Date Scalar serializer expected a `Date` object/);
|
|
653
|
+
assert.ok(DateScalar.parseLiteral({ kind: Kind.STRING, value: "2020-01-01T00:00:00.000Z" }) instanceof Date);
|
|
654
|
+
assert.strictEqual(DateScalar.parseLiteral({ kind: Kind.INT, value: "2020-01-01T00:00:00.000Z" }), null);
|
|
655
|
+
}
|
|
656
|
+
};
|
|
657
|
+
__decorate([
|
|
658
|
+
test
|
|
659
|
+
], TypesTest.prototype, "any", null);
|
|
660
|
+
__decorate([
|
|
661
|
+
test
|
|
662
|
+
], TypesTest.prototype, "long", null);
|
|
663
|
+
__decorate([
|
|
664
|
+
test
|
|
665
|
+
], TypesTest.prototype, "date", null);
|
|
666
|
+
TypesTest = __decorate([
|
|
667
|
+
suite
|
|
668
|
+
], TypesTest);
|
|
669
|
+
//# sourceMappingURL=graphql.spec.js.map
|