@yuneta/gobj-ui 7.25.18 → 7.25.19

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.
@@ -481,6 +481,43 @@ describe("the drawing of a treedb that is not there", () => {
481
481
  });
482
482
  });
483
483
 
484
+ /*
485
+ * Since gobj-ui 7.25.17 the notice translated its detail, and three
486
+ * callers pass a NAME there: a topic called `nodes` that is gone was
487
+ * shown as "Nodos" in an app whose locale has that key, and followed
488
+ * every change of language.
489
+ */
490
+ describe("the name in a notice is a name", () => {
491
+
492
+ test("a topic that is gone is named as it is, with no i18n key", async () => {
493
+ const i18next = (await import("i18next")).default;
494
+ await i18next.init({lng: "es", resources: {es: {translation: {nodes: "Nodos", db: "BD"}}}});
495
+ try {
496
+ const {editor} = build("nn1", "db/nodes");
497
+ expect($in(editor, ".SCHEMA_NOTICE_TEXT").getAttribute("data-i18n"))
498
+ .toBe("that topic is not here any more");
499
+ const $detail = $in(editor, ".SCHEMA_NOTICE_DETAIL");
500
+ expect($detail.textContent).toBe("nodes");
501
+ expect($detail.getAttribute("data-i18n")).toBe(null);
502
+ } finally {
503
+ await i18next.init({lng: "en", resources: {}});
504
+ }
505
+ });
506
+
507
+ test("a treedb that is gone is named as it is, with no i18n key", async () => {
508
+ const i18next = (await import("i18next")).default;
509
+ await i18next.init({lng: "es", resources: {es: {translation: {nodes: "Nodos"}}}});
510
+ try {
511
+ const {editor} = build("nn2", "nodes");
512
+ const $detail = $in(editor, ".SCHEMA_NOTICE_DETAIL");
513
+ expect($detail.textContent).toBe("nodes");
514
+ expect($detail.getAttribute("data-i18n")).toBe(null);
515
+ } finally {
516
+ await i18next.init({lng: "en", resources: {}});
517
+ }
518
+ });
519
+ });
520
+
484
521
  describe("a write given up that was DONE", () => {
485
522
 
486
523
  test("the host is told, and the reload keeps what this session wrote", () => {
@@ -262,6 +262,95 @@ describe("a Save in flight when the backend drops", () => {
262
262
  });
263
263
  });
264
264
 
265
+ /*
266
+ * The success answer of a request, the way C_IEVENT_CLI delivers it: the
267
+ * request's `__md_command__` as the frame, and nothing else of it.
268
+ */
269
+ function answer_ok(request, data)
270
+ {
271
+ return {result: 0, comment: "", data: data, __md_iev__: {
272
+ command_stack: [{command: request.command, kw: request.kw.__md_command__}]
273
+ }};
274
+ }
275
+
276
+ /*
277
+ * Before gobj-ui 7.25.19 a delete answered published nothing (the case
278
+ * was an empty `break`), and `created` compared the command with
279
+ * "create-node" -- which the view never sends: its +New goes out as an
280
+ * update-node with `create_only`, so `created` was always false.
281
+ */
282
+ describe("EV_RECORD_WRITTEN of a create and of a delete", () => {
283
+
284
+ test("a +New answered says created: true", () => {
285
+ const {shell, topics, forms} = build("tc1");
286
+ yui_shell_set_connection_state(shell, true);
287
+ gobj_send_event(topics, "EV_CREATE_RECORD",
288
+ {record: {id: "n1"}, form_write: 1}, forms.users);
289
+
290
+ const request = commands.find((c) => c.command === "update-node");
291
+ expect(request.kw.options.create_only).toBe(true);
292
+ gobj_send_event(topics, "EV_MT_COMMAND_ANSWER",
293
+ answer_ok(request, [{id: "n1", name: "new"}]), remote);
294
+
295
+ expect(written).toEqual([{
296
+ treedb_name: "treedb_test",
297
+ topic_name: "users",
298
+ record: {id: "n1", name: "new"},
299
+ created: true,
300
+ command: "update-node"
301
+ }]);
302
+ expect(answers).toEqual([
303
+ {topic: "users", event: "EV_WRITE_DONE", form_write: 1},
304
+ ]);
305
+ expect(errors()).toEqual([]);
306
+ });
307
+
308
+ test("an edit answered says created: false", () => {
309
+ const {shell, topics, forms} = build("tc2");
310
+ yui_shell_set_connection_state(shell, true);
311
+ save(topics, forms.users, 1);
312
+ const request = commands.find((c) => c.command === "update-node");
313
+ gobj_send_event(topics, "EV_MT_COMMAND_ANSWER",
314
+ answer_ok(request, [{id: "x"}]), remote);
315
+ expect(written.map((w) => w.created)).toEqual([false]);
316
+ });
317
+
318
+ test("a delete answered is published with the node deleted", () => {
319
+ const {shell, topics, forms} = build("tc3");
320
+ yui_shell_set_connection_state(shell, true);
321
+ gobj_send_event(topics, "EV_DELETE_RECORD", {record: {id: "x"}}, forms.roles);
322
+
323
+ const request = commands.find((c) => c.command === "delete-node");
324
+ expect(request).toBeTruthy();
325
+ gobj_send_event(topics, "EV_MT_COMMAND_ANSWER",
326
+ answer_ok(request, [{id: "x", name: "gone"}]), remote);
327
+
328
+ expect(written).toEqual([{
329
+ treedb_name: "treedb_test",
330
+ topic_name: "roles",
331
+ record: {id: "x", name: "gone"},
332
+ created: false,
333
+ command: "delete-node"
334
+ }]);
335
+ /* A delete has no form waiting for its answer. */
336
+ expect(answers).toEqual([]);
337
+ expect(errors()).toEqual([]);
338
+ });
339
+
340
+ test("a delete refused publishes nothing", () => {
341
+ const {shell, topics, forms} = build("tc4");
342
+ yui_shell_set_connection_state(shell, true);
343
+ gobj_send_event(topics, "EV_DELETE_RECORD", {record: {id: "x"}}, forms.roles);
344
+ const request = commands.find((c) => c.command === "delete-node");
345
+ gobj_send_event(topics, "EV_MT_COMMAND_ANSWER", {
346
+ result: -1, comment: "linked", data: null, __md_iev__: {
347
+ command_stack: [{command: "delete-node", kw: request.kw.__md_command__}]
348
+ }
349
+ }, remote);
350
+ expect(written).toEqual([]);
351
+ });
352
+ });
353
+
265
354
  /*
266
355
  * The answer the routing adapter gives a write it had in flight when
267
356
  * its session closed: a failure, settled by the adapter itself.
@@ -0,0 +1,92 @@
1
+ /***********************************************************************
2
+ * uplot_add_serie.test.js
3
+ *
4
+ * C_YUI_UPLOT's EV_ADD_SERIE gives a series the palette's stroke
5
+ * and fill only when the host gave none. It did it through
6
+ * kw_get_str(KW_CREATE), which reads a stroke that is a FUNCTION
7
+ * (uPlot takes one, and a gradient) as a value of the wrong type:
8
+ * since gobj-js 7.25.5, which logs that as C does, every series
9
+ * added with one logged an error.
10
+ *
11
+ * Copyright (c) 2026, ArtGins.
12
+ * All Rights Reserved.
13
+ ***********************************************************************/
14
+ import {describe, test, expect, beforeAll, beforeEach, vi} from "vitest";
15
+ import {install_dom_double} from "../test/dom_double.js";
16
+
17
+ install_dom_double();
18
+
19
+ /* uPlot draws on a canvas the document double does not have: the
20
+ * chart gets a stand-in, and the test writes its own over it. */
21
+ vi.mock("uplot", () => ({
22
+ default: class {
23
+ constructor() {
24
+ this.series = [{}];
25
+ }
26
+ setSize() {}
27
+ addSeries() {}
28
+ destroy() {}
29
+ }
30
+ }));
31
+
32
+ const {
33
+ gobj_start_up, gobj_create_yuno, gobj_create_pure_child, gclass_create,
34
+ gobj_send_event, gobj_write_attr, set_log_callback, SDATA_END,
35
+ } = await import("@yuneta/gobj-js");
36
+ const {register_c_yui_uplot} = await import("./c_yui_uplot.js");
37
+
38
+ const logged = [];
39
+ let yuno = null;
40
+
41
+ beforeAll(() => {
42
+ gobj_start_up(null, null, null, null, null, null, null);
43
+ set_log_callback((level, msg) => {
44
+ logged.push({level: String(level), msg: String(msg)});
45
+ });
46
+ gclass_create("C_TEST_UPLOT_HOST", [], [["ST_IDLE", []]], {}, 0, [SDATA_END()], {}, 0, 0, 0, 0);
47
+ register_c_yui_uplot();
48
+ yuno = gobj_create_yuno("uplot_yuno", "C_TEST_UPLOT_HOST", {});
49
+ });
50
+
51
+ beforeEach(() => {
52
+ logged.length = 0;
53
+ });
54
+
55
+ let seq = 0;
56
+
57
+ /* The chart, with uPlot replaced by what EV_ADD_SERIE asks of it. */
58
+ function build()
59
+ {
60
+ const chart = gobj_create_pure_child(`chart_${++seq}`, "C_YUI_UPLOT", {}, yuno);
61
+ const added = [];
62
+ gobj_write_attr(chart, "uplot", {
63
+ series: [{}],
64
+ addSeries: (kw) => {
65
+ added.push(kw);
66
+ }
67
+ });
68
+ logged.length = 0;
69
+ return {chart, added};
70
+ }
71
+
72
+ describe("EV_ADD_SERIE", () => {
73
+
74
+ test("a series with no colours takes the palette's", () => {
75
+ const {chart, added} = build();
76
+ gobj_send_event(chart, "EV_ADD_SERIE", {id: "a", label: "A"}, chart);
77
+ expect(added.length).toBe(1);
78
+ expect(typeof added[0].stroke).toBe("string");
79
+ expect(added[0].stroke.length).toBeGreaterThan(0);
80
+ expect(logged.filter((l) => l.level === "error")).toEqual([]);
81
+ });
82
+
83
+ test("a stroke and a fill that are functions are kept, and nothing is logged", () => {
84
+ const {chart, added} = build();
85
+ const stroke = () => "red";
86
+ const fill = () => "pink";
87
+ gobj_send_event(chart, "EV_ADD_SERIE", {id: "b", stroke, fill}, chart);
88
+ expect(added[0].stroke).toBe(stroke);
89
+ expect(added[0].fill).toBe(fill);
90
+ expect(logged.filter((l) => l.level === "error")).toEqual([]);
91
+ });
92
+ });