@saltcorn/server 0.9.4-beta.8 → 0.9.4
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/app.js +16 -1
- package/auth/admin.js +19 -3
- package/auth/routes.js +16 -4
- package/auth/testhelp.js +17 -1
- package/load_plugins.js +8 -2
- package/locales/en.json +29 -1
- package/markup/admin.js +22 -18
- package/package.json +10 -9
- package/public/dayjslocales/af.js +1 -0
- package/public/dayjslocales/am.js +1 -0
- package/public/dayjslocales/ar-dz.js +1 -0
- package/public/dayjslocales/ar-iq.js +1 -0
- package/public/dayjslocales/ar-kw.js +1 -0
- package/public/dayjslocales/ar-ly.js +1 -0
- package/public/dayjslocales/ar-ma.js +1 -0
- package/public/dayjslocales/ar-sa.js +1 -0
- package/public/dayjslocales/ar-tn.js +1 -0
- package/public/dayjslocales/ar.js +1 -0
- package/public/dayjslocales/az.js +1 -0
- package/public/dayjslocales/be.js +1 -0
- package/public/dayjslocales/bg.js +1 -0
- package/public/dayjslocales/bi.js +1 -0
- package/public/dayjslocales/bm.js +1 -0
- package/public/dayjslocales/bn-bd.js +1 -0
- package/public/dayjslocales/bn.js +1 -0
- package/public/dayjslocales/bo.js +1 -0
- package/public/dayjslocales/br.js +1 -0
- package/public/dayjslocales/bs.js +1 -0
- package/public/dayjslocales/ca.js +1 -0
- package/public/dayjslocales/cs.js +1 -0
- package/public/dayjslocales/cv.js +1 -0
- package/public/dayjslocales/cy.js +1 -0
- package/public/dayjslocales/da.js +1 -0
- package/public/dayjslocales/de-at.js +1 -0
- package/public/dayjslocales/de-ch.js +1 -0
- package/public/dayjslocales/de.js +1 -0
- package/public/dayjslocales/dv.js +1 -0
- package/public/dayjslocales/el.js +1 -0
- package/public/dayjslocales/en-au.js +1 -0
- package/public/dayjslocales/en-ca.js +1 -0
- package/public/dayjslocales/en-gb.js +1 -0
- package/public/dayjslocales/en-ie.js +1 -0
- package/public/dayjslocales/en-il.js +1 -0
- package/public/dayjslocales/en-in.js +1 -0
- package/public/dayjslocales/en-nz.js +1 -0
- package/public/dayjslocales/en-sg.js +1 -0
- package/public/dayjslocales/en-tt.js +1 -0
- package/public/dayjslocales/en.js +1 -0
- package/public/dayjslocales/eo.js +1 -0
- package/public/dayjslocales/es-do.js +1 -0
- package/public/dayjslocales/es-mx.js +1 -0
- package/public/dayjslocales/es-pr.js +1 -0
- package/public/dayjslocales/es-us.js +1 -0
- package/public/dayjslocales/es.js +1 -0
- package/public/dayjslocales/et.js +1 -0
- package/public/dayjslocales/eu.js +1 -0
- package/public/dayjslocales/fa.js +1 -0
- package/public/dayjslocales/fi.js +1 -0
- package/public/dayjslocales/fo.js +1 -0
- package/public/dayjslocales/fr-ca.js +1 -0
- package/public/dayjslocales/fr-ch.js +1 -0
- package/public/dayjslocales/fr.js +1 -0
- package/public/dayjslocales/fy.js +1 -0
- package/public/dayjslocales/ga.js +1 -0
- package/public/dayjslocales/gd.js +1 -0
- package/public/dayjslocales/gl.js +1 -0
- package/public/dayjslocales/gom-latn.js +1 -0
- package/public/dayjslocales/gu.js +1 -0
- package/public/dayjslocales/he.js +1 -0
- package/public/dayjslocales/hi.js +1 -0
- package/public/dayjslocales/hr.js +1 -0
- package/public/dayjslocales/ht.js +1 -0
- package/public/dayjslocales/hu.js +1 -0
- package/public/dayjslocales/hy-am.js +1 -0
- package/public/dayjslocales/id.js +1 -0
- package/public/dayjslocales/is.js +1 -0
- package/public/dayjslocales/it-ch.js +1 -0
- package/public/dayjslocales/it.js +1 -0
- package/public/dayjslocales/ja.js +1 -0
- package/public/dayjslocales/jv.js +1 -0
- package/public/dayjslocales/ka.js +1 -0
- package/public/dayjslocales/kk.js +1 -0
- package/public/dayjslocales/km.js +1 -0
- package/public/dayjslocales/kn.js +1 -0
- package/public/dayjslocales/ko.js +1 -0
- package/public/dayjslocales/ku.js +1 -0
- package/public/dayjslocales/ky.js +1 -0
- package/public/dayjslocales/lb.js +1 -0
- package/public/dayjslocales/lo.js +1 -0
- package/public/dayjslocales/lt.js +1 -0
- package/public/dayjslocales/lv.js +1 -0
- package/public/dayjslocales/me.js +1 -0
- package/public/dayjslocales/mi.js +1 -0
- package/public/dayjslocales/mk.js +1 -0
- package/public/dayjslocales/ml.js +1 -0
- package/public/dayjslocales/mn.js +1 -0
- package/public/dayjslocales/mr.js +1 -0
- package/public/dayjslocales/ms-my.js +1 -0
- package/public/dayjslocales/ms.js +1 -0
- package/public/dayjslocales/mt.js +1 -0
- package/public/dayjslocales/my.js +1 -0
- package/public/dayjslocales/nb.js +1 -0
- package/public/dayjslocales/ne.js +1 -0
- package/public/dayjslocales/nl-be.js +1 -0
- package/public/dayjslocales/nl.js +1 -0
- package/public/dayjslocales/nn.js +1 -0
- package/public/dayjslocales/oc-lnc.js +1 -0
- package/public/dayjslocales/pa-in.js +1 -0
- package/public/dayjslocales/pl.js +1 -0
- package/public/dayjslocales/pt-br.js +1 -0
- package/public/dayjslocales/pt.js +1 -0
- package/public/dayjslocales/rn.js +1 -0
- package/public/dayjslocales/ro.js +1 -0
- package/public/dayjslocales/ru.js +1 -0
- package/public/dayjslocales/rw.js +1 -0
- package/public/dayjslocales/sd.js +1 -0
- package/public/dayjslocales/se.js +1 -0
- package/public/dayjslocales/si.js +1 -0
- package/public/dayjslocales/sk.js +1 -0
- package/public/dayjslocales/sl.js +1 -0
- package/public/dayjslocales/sq.js +1 -0
- package/public/dayjslocales/sr-cyrl.js +1 -0
- package/public/dayjslocales/sr.js +1 -0
- package/public/dayjslocales/ss.js +1 -0
- package/public/dayjslocales/sv-fi.js +1 -0
- package/public/dayjslocales/sv.js +1 -0
- package/public/dayjslocales/sw.js +1 -0
- package/public/dayjslocales/ta.js +1 -0
- package/public/dayjslocales/te.js +1 -0
- package/public/dayjslocales/tet.js +1 -0
- package/public/dayjslocales/tg.js +1 -0
- package/public/dayjslocales/th.js +1 -0
- package/public/dayjslocales/tk.js +1 -0
- package/public/dayjslocales/tl-ph.js +1 -0
- package/public/dayjslocales/tlh.js +1 -0
- package/public/dayjslocales/tr.js +1 -0
- package/public/dayjslocales/tzl.js +1 -0
- package/public/dayjslocales/tzm-latn.js +1 -0
- package/public/dayjslocales/tzm.js +1 -0
- package/public/dayjslocales/ug-cn.js +1 -0
- package/public/dayjslocales/uk.js +1 -0
- package/public/dayjslocales/ur.js +1 -0
- package/public/dayjslocales/uz-latn.js +1 -0
- package/public/dayjslocales/uz.js +1 -0
- package/public/dayjslocales/vi.js +1 -0
- package/public/dayjslocales/x-pseudo.js +1 -0
- package/public/dayjslocales/yo.js +1 -0
- package/public/dayjslocales/zh-cn.js +1 -0
- package/public/dayjslocales/zh-hk.js +1 -0
- package/public/dayjslocales/zh-tw.js +1 -0
- package/public/dayjslocales/zh.js +1 -0
- package/public/gridedit.js +2 -2
- package/public/log_viewer_utils.js +156 -0
- package/public/saltcorn-builder.css +43 -2
- package/public/saltcorn-common.js +39 -29
- package/public/saltcorn.js +29 -8
- package/public/tabulator_bootstrap5.min.css +1 -0
- package/restart_watcher.js +1 -0
- package/routes/actions.js +175 -18
- package/routes/admin.js +83 -9
- package/routes/common_lists.js +344 -152
- package/routes/fields.js +18 -3
- package/routes/homepage.js +2 -1
- package/routes/page.js +30 -13
- package/routes/page_groupedit.js +104 -83
- package/routes/pageedit.js +23 -7
- package/routes/tables.js +51 -5
- package/routes/tag_entries.js +18 -5
- package/routes/tags.js +65 -12
- package/routes/utils.js +23 -2
- package/routes/view.js +12 -1
- package/routes/viewedit.js +46 -3
- package/serve.js +177 -10
- package/tests/admin.test.js +17 -11
- package/tests/api.test.js +27 -0
- package/tests/fields.test.js +132 -5
- package/tests/help.test.js +37 -0
- package/tests/page_group.test.js +1 -0
- package/tests/plugins.test.js +0 -12
- package/tests/table.test.js +1 -5
- package/tests/view.test.js +127 -15
- package/tests/viewedit.test.js +52 -8
- package/wrapper.js +9 -2
- package/public/relation_helpers.js +0 -351
package/tests/admin.test.js
CHANGED
|
@@ -382,13 +382,13 @@ describe("actions", () => {
|
|
|
382
382
|
.send("table_id=2")
|
|
383
383
|
.send("name=mynewaction")
|
|
384
384
|
.send("when_trigger=Insert")
|
|
385
|
-
.expect(toRedirect("/actions/configure/
|
|
385
|
+
.expect(toRedirect("/actions/configure/3"));
|
|
386
386
|
});
|
|
387
387
|
it("show edit", async () => {
|
|
388
388
|
const app = await getApp({ disableCsrf: true });
|
|
389
389
|
const loginCookie = await getAdminLoginCookie();
|
|
390
390
|
await request(app)
|
|
391
|
-
.get("/actions/edit/
|
|
391
|
+
.get("/actions/edit/3")
|
|
392
392
|
.set("Cookie", loginCookie)
|
|
393
393
|
.expect(toInclude("Edit trigger"))
|
|
394
394
|
.expect(toInclude("run_js_code"));
|
|
@@ -397,7 +397,7 @@ describe("actions", () => {
|
|
|
397
397
|
const app = await getApp({ disableCsrf: true });
|
|
398
398
|
const loginCookie = await getAdminLoginCookie();
|
|
399
399
|
await request(app)
|
|
400
|
-
.get("/actions/configure/
|
|
400
|
+
.get("/actions/configure/3")
|
|
401
401
|
.set("Cookie", loginCookie)
|
|
402
402
|
.expect(toInclude("Configure trigger"))
|
|
403
403
|
.expect(toInclude("Code"));
|
|
@@ -406,7 +406,7 @@ describe("actions", () => {
|
|
|
406
406
|
const app = await getApp({ disableCsrf: true });
|
|
407
407
|
const loginCookie = await getAdminLoginCookie();
|
|
408
408
|
await request(app)
|
|
409
|
-
.post("/actions/configure/
|
|
409
|
+
.post("/actions/configure/3")
|
|
410
410
|
.set("Cookie", loginCookie)
|
|
411
411
|
.send("code=console.log(12345678)")
|
|
412
412
|
.expect(toRedirect("/actions/"));
|
|
@@ -415,7 +415,7 @@ describe("actions", () => {
|
|
|
415
415
|
const app = await getApp({ disableCsrf: true });
|
|
416
416
|
const loginCookie = await getAdminLoginCookie();
|
|
417
417
|
await request(app)
|
|
418
|
-
.get("/actions/testrun/
|
|
418
|
+
.get("/actions/testrun/3")
|
|
419
419
|
.set("Cookie", loginCookie)
|
|
420
420
|
.expect(toInclude("12345678"));
|
|
421
421
|
});
|
|
@@ -423,7 +423,7 @@ describe("actions", () => {
|
|
|
423
423
|
const app = await getApp({ disableCsrf: true });
|
|
424
424
|
const loginCookie = await getAdminLoginCookie();
|
|
425
425
|
await request(app)
|
|
426
|
-
.post("/actions/configure/
|
|
426
|
+
.post("/actions/configure/3")
|
|
427
427
|
.set("Cookie", loginCookie)
|
|
428
428
|
.send("code=1")
|
|
429
429
|
.expect(toRedirect("/actions/"));
|
|
@@ -432,7 +432,7 @@ describe("actions", () => {
|
|
|
432
432
|
const app = await getApp({ disableCsrf: true });
|
|
433
433
|
const loginCookie = await getAdminLoginCookie();
|
|
434
434
|
await request(app)
|
|
435
|
-
.get("/actions/testrun/
|
|
435
|
+
.get("/actions/testrun/2")
|
|
436
436
|
.set("Cookie", loginCookie)
|
|
437
437
|
.expect(toRedirect("/actions/"));
|
|
438
438
|
});
|
|
@@ -446,9 +446,9 @@ describe("actions", () => {
|
|
|
446
446
|
.send("action=run_js_code")
|
|
447
447
|
.send("when_trigger=API+call")
|
|
448
448
|
.send("min_role=1")
|
|
449
|
-
.expect(toRedirect("/actions/configure/
|
|
449
|
+
.expect(toRedirect("/actions/configure/4"));
|
|
450
450
|
await request(app)
|
|
451
|
-
.post("/actions/configure/
|
|
451
|
+
.post("/actions/configure/4")
|
|
452
452
|
.set("Cookie", loginCookie)
|
|
453
453
|
.send("code=return 27")
|
|
454
454
|
.expect(toRedirect("/actions/"));
|
|
@@ -463,7 +463,7 @@ describe("actions", () => {
|
|
|
463
463
|
const app = await getApp({ disableCsrf: true });
|
|
464
464
|
const loginCookie = await getAdminLoginCookie();
|
|
465
465
|
await request(app)
|
|
466
|
-
.post("/actions/delete/
|
|
466
|
+
.post("/actions/delete/3")
|
|
467
467
|
.set("Cookie", loginCookie)
|
|
468
468
|
.expect(toRedirect("/actions/"));
|
|
469
469
|
});
|
|
@@ -555,7 +555,7 @@ describe("diagram", () => {
|
|
|
555
555
|
});
|
|
556
556
|
|
|
557
557
|
/**
|
|
558
|
-
*
|
|
558
|
+
* Tags tests
|
|
559
559
|
*/
|
|
560
560
|
describe("tags", () => {
|
|
561
561
|
itShouldRedirectUnauthToLogin("/tag");
|
|
@@ -604,6 +604,12 @@ describe("tags", () => {
|
|
|
604
604
|
.expect(toRedirect("/tag"));
|
|
605
605
|
});
|
|
606
606
|
});
|
|
607
|
+
|
|
608
|
+
describe("server logs viewer", () => {
|
|
609
|
+
itShouldRedirectUnauthToLogin("/admin/dev/logs_viewer");
|
|
610
|
+
itShouldIncludeTextForAdmin("/admin/dev/logs_viewer", "Server logs");
|
|
611
|
+
});
|
|
612
|
+
|
|
607
613
|
/**
|
|
608
614
|
* Clear all tests
|
|
609
615
|
*/
|
package/tests/api.test.js
CHANGED
|
@@ -161,6 +161,33 @@ describe("API read", () => {
|
|
|
161
161
|
succeedJsonWith((rows) => rows.length == 2 && +rows[0]._versions === 0)
|
|
162
162
|
);
|
|
163
163
|
});
|
|
164
|
+
it("should get distinct authors for public", async () => {
|
|
165
|
+
const app = await getApp({ disableCsrf: true });
|
|
166
|
+
await request(app)
|
|
167
|
+
.get("/api/books/distinct/author")
|
|
168
|
+
.expect(
|
|
169
|
+
succeedJsonWith((vals) => {
|
|
170
|
+
return vals.length == 2 && vals.includes("Herman Melville");
|
|
171
|
+
})
|
|
172
|
+
);
|
|
173
|
+
});
|
|
174
|
+
it("should not allow public access to distinct patients", async () => {
|
|
175
|
+
const app = await getApp({ disableCsrf: true });
|
|
176
|
+
await request(app).get("/api/patients/distinct/name").expect(notAuthorized);
|
|
177
|
+
});
|
|
178
|
+
it("should allow staff access to distinct patients", async () => {
|
|
179
|
+
const loginCookie = await getStaffLoginCookie();
|
|
180
|
+
|
|
181
|
+
const app = await getApp({ disableCsrf: true });
|
|
182
|
+
await request(app)
|
|
183
|
+
.get("/api/patients/distinct/name")
|
|
184
|
+
.set("Cookie", loginCookie)
|
|
185
|
+
.expect(
|
|
186
|
+
succeedJsonWith(
|
|
187
|
+
(rows) => rows.length == 2 && rows.includes("Kirk Douglas")
|
|
188
|
+
)
|
|
189
|
+
);
|
|
190
|
+
});
|
|
164
191
|
});
|
|
165
192
|
describe("API post", () => {
|
|
166
193
|
it("should post books", async () => {
|
package/tests/fields.test.js
CHANGED
|
@@ -8,6 +8,7 @@ const {
|
|
|
8
8
|
getAdminLoginCookie,
|
|
9
9
|
itShouldRedirectUnauthToLogin,
|
|
10
10
|
toInclude,
|
|
11
|
+
toBeTrue,
|
|
11
12
|
toNotInclude,
|
|
12
13
|
toRedirect,
|
|
13
14
|
resetToFixtures,
|
|
@@ -364,9 +365,12 @@ describe("Field Endpoints", () => {
|
|
|
364
365
|
await request(app)
|
|
365
366
|
.post("/field/show-calculated/books/pagesp1/show")
|
|
366
367
|
.set("Cookie", loginCookie)
|
|
367
|
-
.
|
|
368
|
+
.send({
|
|
369
|
+
id: 1,
|
|
370
|
+
})
|
|
371
|
+
.expect(toBeTrue((r) => +r.text > 500 && +r.text < 1500));
|
|
368
372
|
});
|
|
369
|
-
it("should show calculated with single joinfield", async () => {
|
|
373
|
+
it("should show calculated field with single joinfield", async () => {
|
|
370
374
|
const loginCookie = await getAdminLoginCookie();
|
|
371
375
|
const table = Table.findOne({ name: "patients" });
|
|
372
376
|
await Field.create({
|
|
@@ -382,9 +386,12 @@ describe("Field Endpoints", () => {
|
|
|
382
386
|
await request(app)
|
|
383
387
|
.post("/field/show-calculated/patients/pagesp1/show")
|
|
384
388
|
.set("Cookie", loginCookie)
|
|
385
|
-
.
|
|
389
|
+
.send({
|
|
390
|
+
id: 1,
|
|
391
|
+
})
|
|
392
|
+
.expect(toBeTrue((r) => +r.text > 2));
|
|
386
393
|
});
|
|
387
|
-
it("should show calculated with double joinfield", async () => {
|
|
394
|
+
it("should show calculated field with double joinfield", async () => {
|
|
388
395
|
const loginCookie = await getAdminLoginCookie();
|
|
389
396
|
const table = Table.findOne({ name: "readings" });
|
|
390
397
|
await Field.create({
|
|
@@ -400,7 +407,127 @@ describe("Field Endpoints", () => {
|
|
|
400
407
|
await request(app)
|
|
401
408
|
.post("/field/show-calculated/readings/pagesp1/show")
|
|
402
409
|
.set("Cookie", loginCookie)
|
|
403
|
-
.
|
|
410
|
+
.send({
|
|
411
|
+
id: 1,
|
|
412
|
+
})
|
|
413
|
+
.expect(toBeTrue((r) => +r.text > 2));
|
|
414
|
+
});
|
|
415
|
+
it("should show-calculated on join field value", async () => {
|
|
416
|
+
const loginCookie = await getAdminLoginCookie();
|
|
417
|
+
|
|
418
|
+
const app = await getApp({ disableCsrf: true });
|
|
419
|
+
|
|
420
|
+
await request(app)
|
|
421
|
+
.post("/field/show-calculated/books/publisher.name/as_text")
|
|
422
|
+
.set("Cookie", loginCookie)
|
|
423
|
+
.send({
|
|
424
|
+
publisher: 1,
|
|
425
|
+
})
|
|
426
|
+
.expect(toBeTrue((r) => r.text === "AK Press"));
|
|
427
|
+
});
|
|
428
|
+
it("should show-calculated on join field value", async () => {
|
|
429
|
+
const loginCookie = await getAdminLoginCookie();
|
|
430
|
+
|
|
431
|
+
const app = await getApp({ disableCsrf: true });
|
|
432
|
+
|
|
433
|
+
await request(app)
|
|
434
|
+
.post("/field/show-calculated/books/publisher.name/code")
|
|
435
|
+
.set("Cookie", loginCookie)
|
|
436
|
+
.send({
|
|
437
|
+
publisher: 1,
|
|
438
|
+
})
|
|
439
|
+
.expect(toBeTrue((r) => r.text === "<pre><code>AK Press</code></pre>"));
|
|
440
|
+
});
|
|
441
|
+
it("should show-calculated on join field value", async () => {
|
|
442
|
+
const loginCookie = await getAdminLoginCookie();
|
|
443
|
+
|
|
444
|
+
const app = await getApp({ disableCsrf: true });
|
|
445
|
+
|
|
446
|
+
await request(app)
|
|
447
|
+
.post("/field/show-calculated/books/publisher.name/code")
|
|
448
|
+
.set("Cookie", loginCookie)
|
|
449
|
+
.send({
|
|
450
|
+
publisher: 1,
|
|
451
|
+
})
|
|
452
|
+
.expect(toBeTrue((r) => r.text === "<pre><code>AK Press</code></pre>"));
|
|
453
|
+
});
|
|
454
|
+
it("should show-calculated on join field value", async () => {
|
|
455
|
+
const loginCookie = await getAdminLoginCookie();
|
|
456
|
+
|
|
457
|
+
const app = await getApp({ disableCsrf: true });
|
|
458
|
+
|
|
459
|
+
await request(app)
|
|
460
|
+
.post(
|
|
461
|
+
"/field/show-calculated/books/publisher.name/show_with_html?code=pub%3A%7B%7Bit.toLowerCase()%7D%7D"
|
|
462
|
+
)
|
|
463
|
+
.set("Cookie", loginCookie)
|
|
464
|
+
.send({
|
|
465
|
+
publisher: 1,
|
|
466
|
+
})
|
|
467
|
+
.expect(toBeTrue((r) => r.text === "pub:ak press"));
|
|
468
|
+
});
|
|
469
|
+
it("should show-calculated on double-join field value", async () => {
|
|
470
|
+
const loginCookie = await getAdminLoginCookie();
|
|
471
|
+
|
|
472
|
+
const app = await getApp({ disableCsrf: true });
|
|
473
|
+
|
|
474
|
+
await request(app)
|
|
475
|
+
.post("/field/show-calculated/patients/favbook.publisher.name/as_text")
|
|
476
|
+
.set("Cookie", loginCookie)
|
|
477
|
+
.send({
|
|
478
|
+
favbook: 2,
|
|
479
|
+
})
|
|
480
|
+
.expect(toBeTrue((r) => r.text === "AK Press"));
|
|
481
|
+
});
|
|
482
|
+
it("should not show unauth show-calculated on double-join field value", async () => {
|
|
483
|
+
const app = await getApp({ disableCsrf: true });
|
|
484
|
+
|
|
485
|
+
await request(app)
|
|
486
|
+
.post("/field/show-calculated/patients/favbook.publisher.name/as_text")
|
|
487
|
+
|
|
488
|
+
.send({
|
|
489
|
+
favbook: 2,
|
|
490
|
+
})
|
|
491
|
+
.expect(401);
|
|
492
|
+
});
|
|
493
|
+
it("should preview field", async () => {
|
|
494
|
+
const loginCookie = await getAdminLoginCookie();
|
|
495
|
+
|
|
496
|
+
const app = await getApp({ disableCsrf: true });
|
|
497
|
+
|
|
498
|
+
await request(app)
|
|
499
|
+
.post("/field/preview/books/author/code")
|
|
500
|
+
.set("Cookie", loginCookie)
|
|
501
|
+
.send({})
|
|
502
|
+
.expect(
|
|
503
|
+
toBeTrue((r) => r.text === "<pre><code>Herman Melville</code></pre>")
|
|
504
|
+
);
|
|
505
|
+
});
|
|
506
|
+
it("should preview joinfield", async () => {
|
|
507
|
+
const loginCookie = await getAdminLoginCookie();
|
|
508
|
+
|
|
509
|
+
const app = await getApp({ disableCsrf: true });
|
|
510
|
+
|
|
511
|
+
await request(app)
|
|
512
|
+
.post("/field/preview/books/publisher.name/code")
|
|
513
|
+
.set("Cookie", loginCookie)
|
|
514
|
+
.send({})
|
|
515
|
+
.expect(toBeTrue((r) => r.text === "<pre><code>AK Press</code></pre>"));
|
|
516
|
+
});
|
|
517
|
+
it("should preview joinfield with cfg", async () => {
|
|
518
|
+
const loginCookie = await getAdminLoginCookie();
|
|
519
|
+
|
|
520
|
+
const app = await getApp({ disableCsrf: true });
|
|
521
|
+
|
|
522
|
+
await request(app)
|
|
523
|
+
.post("/field/preview/books/publisher.name/show_with_html")
|
|
524
|
+
.set("Cookie", loginCookie)
|
|
525
|
+
.send({
|
|
526
|
+
configuration: {
|
|
527
|
+
code: "pub:{{it.toLowerCase()}}",
|
|
528
|
+
},
|
|
529
|
+
})
|
|
530
|
+
.expect(toBeTrue((r) => r.text === "pub:ak press"));
|
|
404
531
|
});
|
|
405
532
|
});
|
|
406
533
|
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
const request = require("supertest");
|
|
2
|
+
const getApp = require("../app");
|
|
3
|
+
const {
|
|
4
|
+
toRedirect,
|
|
5
|
+
getAdminLoginCookie,
|
|
6
|
+
getStaffLoginCookie,
|
|
7
|
+
itShouldRedirectUnauthToLogin,
|
|
8
|
+
toInclude,
|
|
9
|
+
toNotInclude,
|
|
10
|
+
resetToFixtures,
|
|
11
|
+
succeedJsonWith,
|
|
12
|
+
} = require("../auth/testhelp");
|
|
13
|
+
const db = require("@saltcorn/data/db");
|
|
14
|
+
const View = require("@saltcorn/data/models/view");
|
|
15
|
+
const Table = require("@saltcorn/data/models/table");
|
|
16
|
+
|
|
17
|
+
beforeAll(async () => {
|
|
18
|
+
await resetToFixtures();
|
|
19
|
+
});
|
|
20
|
+
afterAll(db.close);
|
|
21
|
+
|
|
22
|
+
jest.setTimeout(30000);
|
|
23
|
+
|
|
24
|
+
describe("Help topics", () => {
|
|
25
|
+
itShouldRedirectUnauthToLogin("/admin/help/View%20patterns");
|
|
26
|
+
|
|
27
|
+
it("should show view patterns help", async () => {
|
|
28
|
+
const loginCookie = await getAdminLoginCookie();
|
|
29
|
+
|
|
30
|
+
const app = await getApp({ disableCsrf: true });
|
|
31
|
+
await request(app)
|
|
32
|
+
.get("/admin/help/View patterns")
|
|
33
|
+
.set("Cookie", loginCookie)
|
|
34
|
+
.expect(toInclude("<title>Help: View patterns</title>"))
|
|
35
|
+
.expect(toInclude("The view pattern is a fundamental concept"));
|
|
36
|
+
});
|
|
37
|
+
});
|
package/tests/page_group.test.js
CHANGED
package/tests/plugins.test.js
CHANGED
|
@@ -280,19 +280,7 @@ describe("Pack clash detection", () => {
|
|
|
280
280
|
.set("Cookie", loginCookie)
|
|
281
281
|
.expect(toRedirect("/"));
|
|
282
282
|
});
|
|
283
|
-
it("should install issues", async () => {
|
|
284
|
-
const loginCookie = await getAdminLoginCookie();
|
|
285
283
|
|
|
286
|
-
const app = await getApp({ disableCsrf: true });
|
|
287
|
-
await request(app)
|
|
288
|
-
.post("/packs/install-named/Blog")
|
|
289
|
-
.set("Cookie", loginCookie)
|
|
290
|
-
.expect(toRedirect("/plugins"));
|
|
291
|
-
await request(app)
|
|
292
|
-
.get("/plugins")
|
|
293
|
-
.set("Cookie", loginCookie)
|
|
294
|
-
.expect(toInclude("Tables already exist: comments"));
|
|
295
|
-
});
|
|
296
284
|
it("should reset again", async () => {
|
|
297
285
|
await resetToFixtures();
|
|
298
286
|
});
|
package/tests/table.test.js
CHANGED
|
@@ -254,11 +254,7 @@ Gordon Kane, 218`;
|
|
|
254
254
|
await request(app)
|
|
255
255
|
.get("/table/")
|
|
256
256
|
.set("Cookie", loginCookie)
|
|
257
|
-
.expect(
|
|
258
|
-
toInclude(
|
|
259
|
-
"cannot drop table books because other objects depend on it"
|
|
260
|
-
)
|
|
261
|
-
);
|
|
257
|
+
.expect(toInclude("has views. Delete these first"));
|
|
262
258
|
});
|
|
263
259
|
});
|
|
264
260
|
describe("deletion to table with row ownership", () => {
|
package/tests/view.test.js
CHANGED
|
@@ -37,6 +37,18 @@ describe("view list endpoint", () => {
|
|
|
37
37
|
describe("nonexisting view", () => {
|
|
38
38
|
itShouldRedirectUnauthToLogin("/view/patlist", "/");
|
|
39
39
|
});
|
|
40
|
+
describe("preview view", () => {
|
|
41
|
+
it("should show previewview to auth", async () => {
|
|
42
|
+
const loginCookie = await getAdminLoginCookie();
|
|
43
|
+
|
|
44
|
+
const app = await getApp({ disableCsrf: true });
|
|
45
|
+
await request(app)
|
|
46
|
+
.post("/view/authorlist/preview")
|
|
47
|
+
.set("Cookie", loginCookie)
|
|
48
|
+
.expect(toInclude("Tolstoy"))
|
|
49
|
+
.expect(toNotInclude(">728<"));
|
|
50
|
+
});
|
|
51
|
+
});
|
|
40
52
|
describe("view patients list endpoint", () => {
|
|
41
53
|
itShouldRedirectUnauthToLogin("/view/patientlist");
|
|
42
54
|
|
|
@@ -419,6 +431,10 @@ describe("update matching rows", () => {
|
|
|
419
431
|
await field.update({ is_unique: false });
|
|
420
432
|
});
|
|
421
433
|
|
|
434
|
+
afterAll(async () => {
|
|
435
|
+
await resetToFixtures();
|
|
436
|
+
});
|
|
437
|
+
|
|
422
438
|
it("update matching books normal", async () => {
|
|
423
439
|
const table = Table.findOne({ name: "books" });
|
|
424
440
|
await updateMatchingRows({
|
|
@@ -755,7 +771,7 @@ describe("relation path to query and state", () => {
|
|
|
755
771
|
.expect(toNotInclude("album B"));
|
|
756
772
|
});
|
|
757
773
|
|
|
758
|
-
it("
|
|
774
|
+
it("OneToOneShow", async () => {
|
|
759
775
|
const app = await getApp({ disableCsrf: true });
|
|
760
776
|
const loginCookie = await getAdminLoginCookie();
|
|
761
777
|
await request(app)
|
|
@@ -805,7 +821,7 @@ describe("relation path to query and state", () => {
|
|
|
805
821
|
.expect(toInclude(`value="artist B"`));
|
|
806
822
|
});
|
|
807
823
|
|
|
808
|
-
it("Parent", async () => {
|
|
824
|
+
it("Parent one layer", async () => {
|
|
809
825
|
const app = await getApp({ disableCsrf: true });
|
|
810
826
|
const loginCookie = await getAdminLoginCookie();
|
|
811
827
|
await request(app)
|
|
@@ -833,6 +849,28 @@ describe("relation path to query and state", () => {
|
|
|
833
849
|
.expect(toInclude("No row selected"));
|
|
834
850
|
});
|
|
835
851
|
|
|
852
|
+
it("Parent two layers", async () => {
|
|
853
|
+
const app = await getApp({ disableCsrf: true });
|
|
854
|
+
const loginCookie = await getAdminLoginCookie();
|
|
855
|
+
await request(app)
|
|
856
|
+
.get(`/view/show_patient_with_publisher?id=2`)
|
|
857
|
+
.set("Cookie", loginCookie)
|
|
858
|
+
// view link
|
|
859
|
+
.expect(toInclude("/view/show_publisher?.patients.favbook.publisher=2"))
|
|
860
|
+
// embedded show
|
|
861
|
+
.expect(toInclude("Michael Douglas"))
|
|
862
|
+
.expect(toInclude("AK Press"));
|
|
863
|
+
|
|
864
|
+
await request(app)
|
|
865
|
+
.get(`/view/show_patient_with_publisher?id=1`)
|
|
866
|
+
.set("Cookie", loginCookie)
|
|
867
|
+
// view link
|
|
868
|
+
.expect(toInclude("/view/show_publisher?.patients.favbook.publisher=1"))
|
|
869
|
+
// embedded show
|
|
870
|
+
.expect(toInclude("Kirk Douglas"))
|
|
871
|
+
.expect(toInclude("No row selected"));
|
|
872
|
+
});
|
|
873
|
+
|
|
836
874
|
it("RelationPath", async () => {
|
|
837
875
|
const app = await getApp({ disableCsrf: true });
|
|
838
876
|
const loginCookie = await getAdminLoginCookie();
|
|
@@ -873,11 +911,23 @@ describe("edit-in-edit with relation path and legacy", () => {
|
|
|
873
911
|
const app = await getApp({ disableCsrf: true });
|
|
874
912
|
const loginCookie = await getAdminLoginCookie();
|
|
875
913
|
await request(app)
|
|
876
|
-
.get("/view/
|
|
914
|
+
.get("/view/edit_department_with_edit_in_edit_relation_path?id=1")
|
|
877
915
|
.set("Cookie", loginCookie)
|
|
878
916
|
.expect(toInclude("add_repeater"));
|
|
879
|
-
|
|
880
|
-
|
|
917
|
+
await request(app)
|
|
918
|
+
.post("/view/edit_department_with_edit_in_edit_relation_path?id=1")
|
|
919
|
+
.set("Cookie", loginCookie)
|
|
920
|
+
.send({
|
|
921
|
+
department_0: "1",
|
|
922
|
+
department_1: "1",
|
|
923
|
+
id: "1",
|
|
924
|
+
id_0: "1",
|
|
925
|
+
id_1: "2",
|
|
926
|
+
name: "my_department",
|
|
927
|
+
name_0: "manager",
|
|
928
|
+
name_1: "my_employee",
|
|
929
|
+
})
|
|
930
|
+
.expect(toRedirect("/"));
|
|
881
931
|
});
|
|
882
932
|
|
|
883
933
|
it("edit-in-edit with relation path two layer", async () => {
|
|
@@ -887,10 +937,21 @@ describe("edit-in-edit with relation path and legacy", () => {
|
|
|
887
937
|
.get("/view/edit_cover_with_edit_artist_on_album_rel_path?id=1")
|
|
888
938
|
.set("Cookie", loginCookie)
|
|
889
939
|
.expect(toInclude("add_repeater"));
|
|
890
|
-
|
|
891
|
-
|
|
940
|
+
await request(app)
|
|
941
|
+
.post("/view/edit_cover_with_edit_artist_on_album_rel_path?id=1")
|
|
942
|
+
.set("Cookie", loginCookie)
|
|
943
|
+
.send({
|
|
944
|
+
album_0: "1",
|
|
945
|
+
album_1: "1",
|
|
946
|
+
artist_0: "1",
|
|
947
|
+
artist_1: "2",
|
|
948
|
+
id: "1",
|
|
949
|
+
id_0: "1",
|
|
950
|
+
id_1: "3",
|
|
951
|
+
name: "green cover",
|
|
952
|
+
})
|
|
953
|
+
.expect(toRedirect("/"));
|
|
892
954
|
});
|
|
893
|
-
|
|
894
955
|
it("edit-in-edit legacy one layer", async () => {
|
|
895
956
|
const app = await getApp({ disableCsrf: true });
|
|
896
957
|
const loginCookie = await getAdminLoginCookie();
|
|
@@ -898,8 +959,20 @@ describe("edit-in-edit with relation path and legacy", () => {
|
|
|
898
959
|
.get("/view/edit_department_with_edit_in_edit_legacy?id=1")
|
|
899
960
|
.set("Cookie", loginCookie)
|
|
900
961
|
.expect(toInclude("add_repeater"));
|
|
901
|
-
|
|
902
|
-
|
|
962
|
+
await request(app)
|
|
963
|
+
.post("/view/edit_department_with_edit_in_edit_legacy?id=1")
|
|
964
|
+
.set("Cookie", loginCookie)
|
|
965
|
+
.send({
|
|
966
|
+
department_0: "1",
|
|
967
|
+
department_1: "1",
|
|
968
|
+
id: "1",
|
|
969
|
+
id_0: "1",
|
|
970
|
+
id_1: "2",
|
|
971
|
+
name: "my_department",
|
|
972
|
+
name_0: "manager",
|
|
973
|
+
name_1: "my_employee",
|
|
974
|
+
})
|
|
975
|
+
.expect(toRedirect("/"));
|
|
903
976
|
});
|
|
904
977
|
|
|
905
978
|
it("edit-in-edit with relation path two layer", async () => {
|
|
@@ -909,8 +982,20 @@ describe("edit-in-edit with relation path and legacy", () => {
|
|
|
909
982
|
.get("/view/edit_cover_with_edit_artist_on_album_rel_path?id=1")
|
|
910
983
|
.set("Cookie", loginCookie)
|
|
911
984
|
.expect(toInclude("add_repeater"));
|
|
912
|
-
|
|
913
|
-
|
|
985
|
+
await request(app)
|
|
986
|
+
.post("/view/edit_cover_with_edit_artist_on_album_rel_path?id=1")
|
|
987
|
+
.set("Cookie", loginCookie)
|
|
988
|
+
.send({
|
|
989
|
+
album_0: "1",
|
|
990
|
+
album_1: "1",
|
|
991
|
+
artist_0: "1",
|
|
992
|
+
artist_1: "2",
|
|
993
|
+
id: "1",
|
|
994
|
+
id_0: "1",
|
|
995
|
+
id_1: "3",
|
|
996
|
+
name: "green cover",
|
|
997
|
+
})
|
|
998
|
+
.expect(toRedirect("/"));
|
|
914
999
|
});
|
|
915
1000
|
|
|
916
1001
|
it("edit-in-edit legacy two layer", async () => {
|
|
@@ -920,8 +1005,20 @@ describe("edit-in-edit with relation path and legacy", () => {
|
|
|
920
1005
|
.get("/view/edit_cover_with_edit_artist_on_album_legacy?id=1")
|
|
921
1006
|
.set("Cookie", loginCookie)
|
|
922
1007
|
.expect(toInclude("add_repeater"));
|
|
923
|
-
|
|
924
|
-
|
|
1008
|
+
await request(app)
|
|
1009
|
+
.post("/view/edit_cover_with_edit_artist_on_album_legacy?id=1")
|
|
1010
|
+
.set("Cookie", loginCookie)
|
|
1011
|
+
.send({
|
|
1012
|
+
album_0: "1",
|
|
1013
|
+
album_1: "1",
|
|
1014
|
+
artist_0: "1",
|
|
1015
|
+
artist_1: "2",
|
|
1016
|
+
id: "1",
|
|
1017
|
+
id_0: "1",
|
|
1018
|
+
id_1: "3",
|
|
1019
|
+
name: "green cover",
|
|
1020
|
+
})
|
|
1021
|
+
.expect(toRedirect("/"));
|
|
925
1022
|
});
|
|
926
1023
|
});
|
|
927
1024
|
|
|
@@ -982,6 +1079,21 @@ describe("legacy relations with relation path", () => {
|
|
|
982
1079
|
await request(app)
|
|
983
1080
|
.get("/view/authoredit_with_show?id=1")
|
|
984
1081
|
.set("Cookie", loginCookie)
|
|
985
|
-
.expect(toInclude(
|
|
1082
|
+
.expect(toInclude("Herman Melville"));
|
|
1083
|
+
});
|
|
1084
|
+
|
|
1085
|
+
it("edit-view with independent list", async () => {
|
|
1086
|
+
const app = await getApp({ disableCsrf: true });
|
|
1087
|
+
const loginCookie = await getAdminLoginCookie();
|
|
1088
|
+
await request(app)
|
|
1089
|
+
.get("/view/authoredit_with_independent_list")
|
|
1090
|
+
.set("Cookie", loginCookie)
|
|
1091
|
+
.expect(toInclude("Herman Melville"))
|
|
1092
|
+
.expect(toInclude("Delete"));
|
|
1093
|
+
await request(app)
|
|
1094
|
+
.get("/view/authoredit_with_independent_list?id=1")
|
|
1095
|
+
.set("Cookie", loginCookie)
|
|
1096
|
+
.expect(toInclude("Herman Melville"))
|
|
1097
|
+
.expect(toInclude("Delete"));
|
|
986
1098
|
});
|
|
987
1099
|
});
|
package/tests/viewedit.test.js
CHANGED
|
@@ -78,6 +78,37 @@ describe("viewedit edit endpoint", () => {
|
|
|
78
78
|
});
|
|
79
79
|
|
|
80
80
|
describe("viewedit new List", () => {
|
|
81
|
+
const columns = [
|
|
82
|
+
{ type: "Field", field_name: "author" },
|
|
83
|
+
{ type: "Field", field_name: "pages" },
|
|
84
|
+
];
|
|
85
|
+
const layout = {
|
|
86
|
+
besides: [
|
|
87
|
+
{
|
|
88
|
+
contents: {
|
|
89
|
+
type: "field",
|
|
90
|
+
fieldview: "as_text",
|
|
91
|
+
field_name: "author",
|
|
92
|
+
configuration: {},
|
|
93
|
+
},
|
|
94
|
+
alignment: "Default",
|
|
95
|
+
header_label: "Author",
|
|
96
|
+
col_width_units: "px",
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
contents: {
|
|
100
|
+
type: "field",
|
|
101
|
+
fieldview: "show",
|
|
102
|
+
field_name: "pages",
|
|
103
|
+
configuration: {},
|
|
104
|
+
},
|
|
105
|
+
alignment: "Default",
|
|
106
|
+
header_label: "Pages",
|
|
107
|
+
col_width_units: "px",
|
|
108
|
+
},
|
|
109
|
+
],
|
|
110
|
+
list_columns: true,
|
|
111
|
+
};
|
|
81
112
|
itShouldRedirectUnauthToLogin("/viewedit/new");
|
|
82
113
|
|
|
83
114
|
it("show new view", async () => {
|
|
@@ -117,11 +148,8 @@ describe("viewedit new List", () => {
|
|
|
117
148
|
.post("/viewedit/config/mybooklist")
|
|
118
149
|
.send("contextEnc=" + ctx)
|
|
119
150
|
.send("stepName=Columns")
|
|
120
|
-
.send("
|
|
121
|
-
.send("
|
|
122
|
-
.send("type_1=Field")
|
|
123
|
-
.send("field_name_1=pages")
|
|
124
|
-
.send("create_view_display=Link")
|
|
151
|
+
.send("columns=" + encodeURIComponent(JSON.stringify(columns)))
|
|
152
|
+
.send("layout=" + encodeURIComponent(JSON.stringify(layout)))
|
|
125
153
|
.set("Cookie", loginCookie)
|
|
126
154
|
.expect(toInclude("Default state"));
|
|
127
155
|
});
|
|
@@ -205,6 +233,23 @@ describe("viewedit new List", () => {
|
|
|
205
233
|
});
|
|
206
234
|
|
|
207
235
|
describe("viewedit new List with one field", () => {
|
|
236
|
+
const columns = [{ type: "Field", field_name: "author", state_field: "on" }];
|
|
237
|
+
const layout = {
|
|
238
|
+
besides: [
|
|
239
|
+
{
|
|
240
|
+
contents: {
|
|
241
|
+
type: "field",
|
|
242
|
+
fieldview: "as_text",
|
|
243
|
+
field_name: "author",
|
|
244
|
+
configuration: {},
|
|
245
|
+
},
|
|
246
|
+
alignment: "Default",
|
|
247
|
+
header_label: "Author",
|
|
248
|
+
col_width_units: "px",
|
|
249
|
+
},
|
|
250
|
+
],
|
|
251
|
+
list_columns: true,
|
|
252
|
+
};
|
|
208
253
|
it("submit new view", async () => {
|
|
209
254
|
const loginCookie = await getAdminLoginCookie();
|
|
210
255
|
|
|
@@ -234,9 +279,8 @@ describe("viewedit new List with one field", () => {
|
|
|
234
279
|
.post("/viewedit/config/mybooklist1")
|
|
235
280
|
.send("contextEnc=" + ctx)
|
|
236
281
|
.send("stepName=Columns")
|
|
237
|
-
.send("
|
|
238
|
-
.send("
|
|
239
|
-
.send("create_view_display=Link")
|
|
282
|
+
.send("columns=" + encodeURIComponent(JSON.stringify(columns)))
|
|
283
|
+
.send("layout=" + encodeURIComponent(JSON.stringify(layout)))
|
|
240
284
|
.set("Cookie", loginCookie)
|
|
241
285
|
.expect(toInclude("Default state"));
|
|
242
286
|
});
|