@proteinjs/db-ui 1.9.4 → 1.10.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 (44) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/generated/index.js +1 -1
  3. package/dist/generated/index.js.map +1 -1
  4. package/dist/index.d.ts +2 -0
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +2 -0
  7. package/dist/index.js.map +1 -1
  8. package/dist/src/form/RecordForm.d.ts.map +1 -1
  9. package/dist/src/form/RecordForm.js +98 -19
  10. package/dist/src/form/RecordForm.js.map +1 -1
  11. package/dist/src/form/customizations/MigrationRecordFormCustomization.d.ts +5 -0
  12. package/dist/src/form/customizations/MigrationRecordFormCustomization.d.ts.map +1 -1
  13. package/dist/src/form/customizations/MigrationRecordFormCustomization.js +72 -0
  14. package/dist/src/form/customizations/MigrationRecordFormCustomization.js.map +1 -1
  15. package/dist/src/table/RecordTable.d.ts.map +1 -1
  16. package/dist/src/table/RecordTable.js +7 -1
  17. package/dist/src/table/RecordTable.js.map +1 -1
  18. package/dist/src/tableDisplayName.d.ts +9 -0
  19. package/dist/src/tableDisplayName.d.ts.map +1 -0
  20. package/dist/src/tableDisplayName.js +31 -0
  21. package/dist/src/tableDisplayName.js.map +1 -0
  22. package/dist/test/recordFormInteractions.test.d.ts +5 -0
  23. package/dist/test/recordFormInteractions.test.d.ts.map +1 -0
  24. package/dist/test/recordFormInteractions.test.js +370 -0
  25. package/dist/test/recordFormInteractions.test.js.map +1 -0
  26. package/dist/test/recordTableDelete.test.d.ts +5 -0
  27. package/dist/test/recordTableDelete.test.d.ts.map +1 -0
  28. package/dist/test/recordTableDelete.test.js +254 -0
  29. package/dist/test/recordTableDelete.test.js.map +1 -0
  30. package/dist/test/tableDisplayName.test.d.ts +2 -0
  31. package/dist/test/tableDisplayName.test.d.ts.map +1 -0
  32. package/dist/test/tableDisplayName.test.js +50 -0
  33. package/dist/test/tableDisplayName.test.js.map +1 -0
  34. package/generated/index.ts +1 -1
  35. package/index.ts +2 -0
  36. package/jest.config.js +8 -1
  37. package/package.json +5 -4
  38. package/src/form/RecordForm.tsx +109 -22
  39. package/src/form/customizations/MigrationRecordFormCustomization.tsx +53 -1
  40. package/src/table/RecordTable.tsx +9 -1
  41. package/src/tableDisplayName.ts +28 -0
  42. package/test/recordFormInteractions.test.tsx +259 -0
  43. package/test/recordTableDelete.test.tsx +144 -0
  44. package/test/tableDisplayName.test.ts +40 -0
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.tableDisplayName = void 0;
7
+ var string_1 = __importDefault(require("string"));
8
+ /**
9
+ * Human title for a table's record collection: the humanized table name with its last word
10
+ * pluralized — 'user' → 'Users', 'access_grant' → 'Access grants'. `Table` carries no display
11
+ * metadata, so the name is derived; the pluralization is deliberately boring (s/es/ies) and
12
+ * predictable rather than a full inflection library.
13
+ */
14
+ function tableDisplayName(table) {
15
+ var humanized = (0, string_1.default)(table.name).humanize().s;
16
+ var words = humanized.split(' ');
17
+ words[words.length - 1] = pluralize(words[words.length - 1]);
18
+ return words.join(' ');
19
+ }
20
+ exports.tableDisplayName = tableDisplayName;
21
+ function pluralize(word) {
22
+ var lower = word.toLowerCase();
23
+ if (/(s|x|z|ch|sh)$/.test(lower)) {
24
+ return "".concat(word, "es");
25
+ }
26
+ if (/[^aeiou]y$/.test(lower)) {
27
+ return "".concat(word.slice(0, -1), "ies");
28
+ }
29
+ return "".concat(word, "s");
30
+ }
31
+ //# sourceMappingURL=tableDisplayName.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tableDisplayName.js","sourceRoot":"","sources":["../../src/tableDisplayName.ts"],"names":[],"mappings":";;;;;;AAAA,kDAAuB;AAGvB;;;;;GAKG;AACH,SAAgB,gBAAgB,CAAC,KAAiB;IAChD,IAAM,SAAS,GAAG,IAAA,gBAAC,EAAC,KAAK,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;IAC7C,IAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACnC,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;IAC7D,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACzB,CAAC;AALD,4CAKC;AAED,SAAS,SAAS,CAAC,IAAY;IAC7B,IAAM,KAAK,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IACjC,IAAI,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;QAChC,OAAO,UAAG,IAAI,OAAI,CAAC;KACpB;IAED,IAAI,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;QAC5B,OAAO,UAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAK,CAAC;KAClC;IAED,OAAO,UAAG,IAAI,MAAG,CAAC;AACpB,CAAC"}
@@ -0,0 +1,5 @@
1
+ import '../generated';
2
+ declare global {
3
+ var IS_REACT_ACT_ENVIRONMENT: boolean;
4
+ }
5
+ //# sourceMappingURL=recordFormInteractions.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recordFormInteractions.test.d.ts","sourceRoot":"","sources":["../../test/recordFormInteractions.test.tsx"],"names":[],"mappings":"AAkCA,OAAO,cAAc,CAAC;AAetB,OAAO,CAAC,MAAM,CAAC;IAEb,IAAI,wBAAwB,EAAE,OAAO,CAAC;CACvC"}
@@ -0,0 +1,370 @@
1
+ "use strict";
2
+ var __extends = (this && this.__extends) || (function () {
3
+ var extendStatics = function (d, b) {
4
+ extendStatics = Object.setPrototypeOf ||
5
+ ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
6
+ function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
7
+ return extendStatics(d, b);
8
+ };
9
+ return function (d, b) {
10
+ if (typeof b !== "function" && b !== null)
11
+ throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
12
+ extendStatics(d, b);
13
+ function __() { this.constructor = d; }
14
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
15
+ };
16
+ })();
17
+ var __assign = (this && this.__assign) || function () {
18
+ __assign = Object.assign || function(t) {
19
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
20
+ s = arguments[i];
21
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
22
+ t[p] = s[p];
23
+ }
24
+ return t;
25
+ };
26
+ return __assign.apply(this, arguments);
27
+ };
28
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
29
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
30
+ return new (P || (P = Promise))(function (resolve, reject) {
31
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
32
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
33
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
34
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
35
+ });
36
+ };
37
+ var __generator = (this && this.__generator) || function (thisArg, body) {
38
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
39
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
40
+ function verb(n) { return function (v) { return step([n, v]); }; }
41
+ function step(op) {
42
+ if (f) throw new TypeError("Generator is already executing.");
43
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
44
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
45
+ if (y = 0, t) op = [op[0] & 2, t.value];
46
+ switch (op[0]) {
47
+ case 0: case 1: t = op; break;
48
+ case 4: _.label++; return { value: op[1], done: false };
49
+ case 5: _.label++; y = op[1]; op = [0]; continue;
50
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
51
+ default:
52
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
53
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
54
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
55
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
56
+ if (t[2]) _.ops.pop();
57
+ _.trys.pop(); continue;
58
+ }
59
+ op = body.call(thisArg, _);
60
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
61
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
62
+ }
63
+ };
64
+ var __importDefault = (this && this.__importDefault) || function (mod) {
65
+ return (mod && mod.__esModule) ? mod : { "default": mod };
66
+ };
67
+ Object.defineProperty(exports, "__esModule", { value: true });
68
+ /**
69
+ * @jest-environment jsdom
70
+ *
71
+ * RecordForm functional gaps (task #53 part 2):
72
+ * - item 2: Delete routes through the confirmation dialog — the service delete only runs after
73
+ * the user confirms (the immediate-delete repro), and cancel is a no-op.
74
+ * - item 3: readonly fields (id/created/updated) are readOnly, not disabled — copyable.
75
+ * - item 7: field controls tell the truth about column types — booleans render as checkboxes,
76
+ * dates as native date inputs, reference columns say what they expect ('comma-separated ids').
77
+ * - save-path truth: the update payload carries real values — a boolean stays a boolean, a
78
+ * DateColumn becomes a Date — and readonly display strings are never written back into the
79
+ * record (pre-fix, `created` round-tripped through its display string, which
80
+ * DateTimeColumn.serialize turns into null on every save).
81
+ */
82
+ var react_1 = __importDefault(require("react"));
83
+ var moment_1 = __importDefault(require("moment"));
84
+ var client_1 = require("react-dom/client");
85
+ var test_utils_1 = require("react-dom/test-utils");
86
+ var react_router_dom_1 = require("react-router-dom");
87
+ var db_1 = require("@proteinjs/db");
88
+ // Load the package's reflection source graph: RecordForm resolves RecordFormCustomizations
89
+ // through SourceRepository, which only knows the type once the generated index has merged it.
90
+ require("../generated");
91
+ var RecordForm_1 = require("../src/form/RecordForm");
92
+ var mockDbService = {
93
+ get: jest.fn(),
94
+ insert: jest.fn(function (table, record) { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
95
+ return [2 /*return*/, record];
96
+ }); }); }),
97
+ update: jest.fn(function (table, record) { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
98
+ return [2 /*return*/, record];
99
+ }); }); }),
100
+ delete: jest.fn(function () { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
101
+ return [2 /*return*/, 1];
102
+ }); }); }),
103
+ };
104
+ jest.mock('@proteinjs/db', function () { return (__assign(__assign({}, jest.requireActual('@proteinjs/db')), { getDbService: function () { return mockDbService; } })); });
105
+ globalThis.IS_REACT_ACT_ENVIRONMENT = true;
106
+ var TaskTable = /** @class */ (function (_super) {
107
+ __extends(TaskTable, _super);
108
+ function TaskTable() {
109
+ var _this = _super !== null && _super.apply(this, arguments) || this;
110
+ _this.name = 'admin_test_task';
111
+ _this.columns = (0, db_1.withRecordColumns)({
112
+ title: new db_1.StringColumn('title'),
113
+ active: new db_1.BooleanColumn('active'),
114
+ dueDate: new db_1.DateColumn('due_date'),
115
+ archivedAt: new db_1.DateTimeColumn('archived_at'),
116
+ owner: new db_1.ReferenceColumn('owner', 'user', false),
117
+ // ObjectColumn descendants (incl. ReferenceArrayColumn) are ui.hidden by default; surface it
118
+ tags: new db_1.ReferenceArrayColumn('tags', 'tag', false, { ui: { hidden: false } }),
119
+ });
120
+ return _this;
121
+ }
122
+ return TaskTable;
123
+ }(db_1.Table));
124
+ var created = (0, moment_1.default)('2026-01-02T03:04:05.000Z');
125
+ var updated = (0, moment_1.default)('2026-02-03T04:05:06.000Z');
126
+ var archivedAt = (0, moment_1.default)('2026-03-04T05:06:07.000Z');
127
+ function loadedRecord() {
128
+ return {
129
+ id: 'task-1',
130
+ title: 'Write tests',
131
+ active: true,
132
+ dueDate: (0, moment_1.default)('2026-08-10', 'YYYY-MM-DD').toDate(),
133
+ archivedAt: archivedAt,
134
+ owner: new db_1.Reference('user', 'user-9'),
135
+ tags: new db_1.ReferenceArray('tag', ['tag-1', 'tag-2']),
136
+ created: created,
137
+ updated: updated,
138
+ };
139
+ }
140
+ describe('RecordForm', function () {
141
+ var container;
142
+ var root;
143
+ beforeEach(function () {
144
+ jest.clearAllMocks();
145
+ container = document.createElement('div');
146
+ document.body.appendChild(container);
147
+ root = (0, client_1.createRoot)(container);
148
+ });
149
+ afterEach(function () {
150
+ (0, test_utils_1.act)(function () {
151
+ root.unmount();
152
+ });
153
+ container.remove();
154
+ });
155
+ var mount = function (record) { return __awaiter(void 0, void 0, void 0, function () {
156
+ return __generator(this, function (_a) {
157
+ switch (_a.label) {
158
+ case 0: return [4 /*yield*/, (0, test_utils_1.act)(function () { return __awaiter(void 0, void 0, void 0, function () {
159
+ return __generator(this, function (_a) {
160
+ root.render(react_1.default.createElement(react_router_dom_1.MemoryRouter, null,
161
+ react_1.default.createElement(RecordForm_1.RecordForm, { table: new TaskTable(), record: record })));
162
+ return [2 /*return*/];
163
+ });
164
+ }); })];
165
+ case 1:
166
+ _a.sent();
167
+ // Let Form.onLoad (async componentDidMount work) settle
168
+ return [4 /*yield*/, (0, test_utils_1.act)(function () { return __awaiter(void 0, void 0, void 0, function () {
169
+ return __generator(this, function (_a) {
170
+ switch (_a.label) {
171
+ case 0: return [4 /*yield*/, Promise.resolve()];
172
+ case 1:
173
+ _a.sent();
174
+ return [2 /*return*/];
175
+ }
176
+ });
177
+ }); })];
178
+ case 2:
179
+ // Let Form.onLoad (async componentDidMount work) settle
180
+ _a.sent();
181
+ return [2 /*return*/];
182
+ }
183
+ });
184
+ }); };
185
+ var findButton = function (name) {
186
+ var button = Array.from(document.querySelectorAll('button')).find(function (b) { return b.textContent === name; });
187
+ if (!button) {
188
+ throw new Error("Button not rendered: ".concat(name));
189
+ }
190
+ return button;
191
+ };
192
+ var click = function (element) { return __awaiter(void 0, void 0, void 0, function () {
193
+ return __generator(this, function (_a) {
194
+ switch (_a.label) {
195
+ case 0: return [4 /*yield*/, (0, test_utils_1.act)(function () { return __awaiter(void 0, void 0, void 0, function () {
196
+ return __generator(this, function (_a) {
197
+ element.dispatchEvent(new MouseEvent('click', { bubbles: true }));
198
+ return [2 /*return*/];
199
+ });
200
+ }); })];
201
+ case 1:
202
+ _a.sent();
203
+ return [2 /*return*/];
204
+ }
205
+ });
206
+ }); };
207
+ var inputByLabel = function (labelText) {
208
+ var _a;
209
+ var label = Array.from(document.querySelectorAll('label')).find(function (l) { var _a; return (_a = l.textContent) === null || _a === void 0 ? void 0 : _a.startsWith(labelText); });
210
+ if (!label) {
211
+ throw new Error("No field labeled: ".concat(labelText));
212
+ }
213
+ var control = label.getAttribute('for')
214
+ ? document.getElementById(label.getAttribute('for'))
215
+ : (_a = label.parentElement) === null || _a === void 0 ? void 0 : _a.querySelector('input');
216
+ if (!control) {
217
+ throw new Error("No input for label: ".concat(labelText));
218
+ }
219
+ return control;
220
+ };
221
+ var dialog = function () { return document.querySelector('[role="dialog"]'); };
222
+ describe('type-truthful field controls (item 7)', function () {
223
+ it('renders booleans as a checked checkbox, dates as a native date input, and readonly timestamps as copyable text', function () { return __awaiter(void 0, void 0, void 0, function () {
224
+ var active, dueDate, _i, _a, labelText, input;
225
+ return __generator(this, function (_b) {
226
+ switch (_b.label) {
227
+ case 0: return [4 /*yield*/, mount(loadedRecord())];
228
+ case 1:
229
+ _b.sent();
230
+ active = inputByLabel('Active');
231
+ expect(active.type).toBe('checkbox');
232
+ expect(active.checked).toBe(true);
233
+ dueDate = inputByLabel('Due date');
234
+ expect(dueDate.type).toBe('date');
235
+ expect(dueDate.value).toBe('2026-08-10');
236
+ // Readonly fields render as text, readOnly-not-disabled (item 3): copyable
237
+ // (`id` itself is ui.hidden at the column layer and never renders)
238
+ for (_i = 0, _a = ['Created', 'Updated', 'Archived at']; _i < _a.length; _i++) {
239
+ labelText = _a[_i];
240
+ input = inputByLabel(labelText);
241
+ expect(input.type).toBe('text');
242
+ expect(input.readOnly).toBe(true);
243
+ expect(input.disabled).toBe(false);
244
+ }
245
+ return [2 /*return*/];
246
+ }
247
+ });
248
+ }); });
249
+ it('stops pretending on reference columns: helper text names the expected ids', function () { return __awaiter(void 0, void 0, void 0, function () {
250
+ return __generator(this, function (_a) {
251
+ switch (_a.label) {
252
+ case 0: return [4 /*yield*/, mount(loadedRecord())];
253
+ case 1:
254
+ _a.sent();
255
+ expect(document.body.textContent).toContain('user record id');
256
+ expect(document.body.textContent).toContain('Comma-separated tag record ids');
257
+ expect(inputByLabel('Owner').value).toBe('user-9');
258
+ expect(inputByLabel('Tags').value).toBe('tag-1, tag-2');
259
+ return [2 /*return*/];
260
+ }
261
+ });
262
+ }); });
263
+ it('renders a datetime-local input for editable DateTimeColumns on new records', function () { return __awaiter(void 0, void 0, void 0, function () {
264
+ return __generator(this, function (_a) {
265
+ switch (_a.label) {
266
+ case 0: return [4 /*yield*/, mount(undefined)];
267
+ case 1:
268
+ _a.sent();
269
+ expect(inputByLabel('Archived at').type).toBe('datetime-local');
270
+ expect(inputByLabel('Active').type).toBe('checkbox');
271
+ expect(inputByLabel('Active').checked).toBe(false);
272
+ return [2 /*return*/];
273
+ }
274
+ });
275
+ }); });
276
+ });
277
+ describe('delete confirmation (item 2)', function () {
278
+ it('does not delete on click; the service call runs only after the dialog confirms', function () { return __awaiter(void 0, void 0, void 0, function () {
279
+ var confirm;
280
+ return __generator(this, function (_a) {
281
+ switch (_a.label) {
282
+ case 0: return [4 /*yield*/, mount(loadedRecord())];
283
+ case 1:
284
+ _a.sent();
285
+ return [4 /*yield*/, click(findButton('Delete'))];
286
+ case 2:
287
+ _a.sent();
288
+ expect(mockDbService.delete).not.toHaveBeenCalled();
289
+ expect(dialog()).not.toBeNull();
290
+ expect(dialog().textContent).toContain('Delete Admin test task?');
291
+ confirm = Array.from(dialog().querySelectorAll('button')).find(function (b) { return b.textContent === 'Delete'; });
292
+ return [4 /*yield*/, click(confirm)];
293
+ case 3:
294
+ _a.sent();
295
+ expect(mockDbService.delete).toHaveBeenCalledTimes(1);
296
+ expect(mockDbService.delete.mock.calls[0][1]).toEqual({ id: 'task-1' });
297
+ return [2 /*return*/];
298
+ }
299
+ });
300
+ }); });
301
+ it('cancel is a no-op', function () { return __awaiter(void 0, void 0, void 0, function () {
302
+ var cancel;
303
+ return __generator(this, function (_a) {
304
+ switch (_a.label) {
305
+ case 0: return [4 /*yield*/, mount(loadedRecord())];
306
+ case 1:
307
+ _a.sent();
308
+ return [4 /*yield*/, click(findButton('Delete'))];
309
+ case 2:
310
+ _a.sent();
311
+ cancel = Array.from(dialog().querySelectorAll('button')).find(function (b) { return b.textContent === 'Cancel'; });
312
+ return [4 /*yield*/, click(cancel)];
313
+ case 3:
314
+ _a.sent();
315
+ expect(mockDbService.delete).not.toHaveBeenCalled();
316
+ expect(dialog()).toBeNull();
317
+ return [2 /*return*/];
318
+ }
319
+ });
320
+ }); });
321
+ });
322
+ describe('save-path truth', function () {
323
+ it('sends real values: booleans stay booleans, dates become Dates, and readonly fields never round-trip through display strings', function () { return __awaiter(void 0, void 0, void 0, function () {
324
+ var payload;
325
+ return __generator(this, function (_a) {
326
+ switch (_a.label) {
327
+ case 0: return [4 /*yield*/, mount(loadedRecord())];
328
+ case 1:
329
+ _a.sent();
330
+ return [4 /*yield*/, click(findButton('Save'))];
331
+ case 2:
332
+ _a.sent();
333
+ expect(mockDbService.update).toHaveBeenCalledTimes(1);
334
+ payload = mockDbService.update.mock.calls[0][1];
335
+ expect(payload.active).toBe(true);
336
+ expect(payload.dueDate).toBeInstanceOf(Date);
337
+ expect((0, moment_1.default)(payload.dueDate).format('YYYY-MM-DD')).toBe('2026-08-10');
338
+ // Pre-fix, these were the human display strings ('Fri, Jan 2nd 26, ...'); `created` then
339
+ // serialized to null on every save. They must remain the loaded moments.
340
+ expect(moment_1.default.isMoment(payload.created)).toBe(true);
341
+ expect(payload.created.valueOf()).toBe(created.valueOf());
342
+ expect(moment_1.default.isMoment(payload.archivedAt)).toBe(true);
343
+ expect(payload.archivedAt.valueOf()).toBe(archivedAt.valueOf());
344
+ expect(payload.id).toBe('task-1');
345
+ return [2 /*return*/];
346
+ }
347
+ });
348
+ }); });
349
+ it('an unchecked checkbox saves boolean false, not a string', function () { return __awaiter(void 0, void 0, void 0, function () {
350
+ var payload;
351
+ return __generator(this, function (_a) {
352
+ switch (_a.label) {
353
+ case 0: return [4 /*yield*/, mount(loadedRecord())];
354
+ case 1:
355
+ _a.sent();
356
+ return [4 /*yield*/, click(inputByLabel('Active'))];
357
+ case 2:
358
+ _a.sent();
359
+ return [4 /*yield*/, click(findButton('Save'))];
360
+ case 3:
361
+ _a.sent();
362
+ payload = mockDbService.update.mock.calls[0][1];
363
+ expect(payload.active).toBe(false);
364
+ return [2 /*return*/];
365
+ }
366
+ });
367
+ }); });
368
+ });
369
+ });
370
+ //# sourceMappingURL=recordFormInteractions.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recordFormInteractions.test.js","sourceRoot":"","sources":["../../test/recordFormInteractions.test.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ declare global {
2
+ var IS_REACT_ACT_ENVIRONMENT: boolean;
3
+ }
4
+ export {};
5
+ //# sourceMappingURL=recordTableDelete.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recordTableDelete.test.d.ts","sourceRoot":"","sources":["../../test/recordTableDelete.test.tsx"],"names":[],"mappings":"AA0BA,OAAO,CAAC,MAAM,CAAC;IAEb,IAAI,wBAAwB,EAAE,OAAO,CAAC;CACvC"}