@dxos/react-ui-table 0.8.4-main.fd6878d → 0.8.4-staging.60fe92afc8
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/LICENSE +102 -5
- package/dist/lib/browser/chunk-4KOQTPFC.mjs +1702 -0
- package/dist/lib/browser/chunk-4KOQTPFC.mjs.map +7 -0
- package/dist/lib/browser/chunk-62PYOJPY.mjs +67 -0
- package/dist/lib/browser/chunk-62PYOJPY.mjs.map +7 -0
- package/dist/lib/browser/chunk-J5LGTIGS.mjs +10 -0
- package/dist/lib/browser/chunk-J5LGTIGS.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +1151 -1175
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/testing/index.mjs +37 -45
- package/dist/lib/browser/testing/index.mjs.map +3 -3
- package/dist/lib/browser/translations.mjs +36 -0
- package/dist/lib/browser/translations.mjs.map +7 -0
- package/dist/lib/browser/types/index.mjs +4 -3
- package/dist/lib/node-esm/chunk-7LMOZUTS.mjs +68 -0
- package/dist/lib/node-esm/chunk-7LMOZUTS.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-HSLMI22Q.mjs +11 -0
- package/dist/lib/node-esm/chunk-HSLMI22Q.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-KOSV2J5N.mjs +1704 -0
- package/dist/lib/node-esm/chunk-KOSV2J5N.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +1151 -1175
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/testing/index.mjs +37 -45
- package/dist/lib/node-esm/testing/index.mjs.map +3 -3
- package/dist/lib/node-esm/translations.mjs +37 -0
- package/dist/lib/node-esm/translations.mjs.map +7 -0
- package/dist/lib/node-esm/types/index.mjs +4 -3
- package/dist/types/src/components/Table/ColumnActionsMenu.d.ts +1 -2
- package/dist/types/src/components/Table/ColumnActionsMenu.d.ts.map +1 -1
- package/dist/types/src/components/Table/ColumnSettings.d.ts +2 -2
- package/dist/types/src/components/Table/ColumnSettings.d.ts.map +1 -1
- package/dist/types/src/components/Table/DynamicTable.d.ts +6 -7
- package/dist/types/src/components/Table/DynamicTable.d.ts.map +1 -1
- package/dist/types/src/components/Table/DynamicTable.stories.d.ts +36 -3
- package/dist/types/src/components/Table/DynamicTable.stories.d.ts.map +1 -1
- package/dist/types/src/components/Table/Relations.stories.d.ts +112 -5
- package/dist/types/src/components/Table/Relations.stories.d.ts.map +1 -1
- package/dist/types/src/components/Table/RowActionsMenu.d.ts.map +1 -1
- package/dist/types/src/components/Table/Table.d.ts +21 -19
- package/dist/types/src/components/Table/Table.d.ts.map +1 -1
- package/dist/types/src/components/Table/Table.stories.d.ts +115 -5
- package/dist/types/src/components/Table/Table.stories.d.ts.map +1 -1
- package/dist/types/src/components/Table/TableContent.d.ts +18 -0
- package/dist/types/src/components/Table/TableContent.d.ts.map +1 -0
- package/dist/types/src/components/Table/TableToolbar.d.ts +21 -0
- package/dist/types/src/components/Table/TableToolbar.d.ts.map +1 -0
- package/dist/types/src/components/TableCellEditor/CellValidationMessage.d.ts +1 -1
- package/dist/types/src/components/TableCellEditor/CellValidationMessage.d.ts.map +1 -1
- package/dist/types/src/components/TableCellEditor/FormCellEditor.d.ts +12 -9
- package/dist/types/src/components/TableCellEditor/FormCellEditor.d.ts.map +1 -1
- package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts +7 -14
- package/dist/types/src/components/TableCellEditor/TableCellEditor.d.ts.map +1 -1
- package/dist/types/src/components/TableCellEditor/TableCellEditor.stories.d.ts +38 -5
- package/dist/types/src/components/TableCellEditor/TableCellEditor.stories.d.ts.map +1 -1
- package/dist/types/src/components/TableCellEditor/index.d.ts +1 -0
- package/dist/types/src/components/TableCellEditor/index.d.ts.map +1 -1
- package/dist/types/src/components/index.d.ts +0 -1
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/components/testing.d.ts +23 -16
- package/dist/types/src/components/testing.d.ts.map +1 -1
- package/dist/types/src/hooks/index.d.ts +2 -1
- package/dist/types/src/hooks/index.d.ts.map +1 -1
- package/dist/types/src/hooks/useAddRow.d.ts +6 -6
- package/dist/types/src/hooks/useAddRow.d.ts.map +1 -1
- package/dist/types/src/hooks/useProjectionModel.d.ts +6 -0
- package/dist/types/src/hooks/useProjectionModel.d.ts.map +1 -0
- package/dist/types/src/hooks/useTableModel.d.ts +9 -9
- package/dist/types/src/hooks/useTableModel.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +0 -2
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/model/modal-controller.d.ts +5 -8
- package/dist/types/src/model/modal-controller.d.ts.map +1 -1
- package/dist/types/src/model/selection-model.d.ts +18 -9
- package/dist/types/src/model/selection-model.d.ts.map +1 -1
- package/dist/types/src/model/table-model.d.ts +111 -30
- package/dist/types/src/model/table-model.d.ts.map +1 -1
- package/dist/types/src/model/table-presentation.d.ts +4 -2
- package/dist/types/src/model/table-presentation.d.ts.map +1 -1
- package/dist/types/src/playwright/TableManager.d.ts +2 -1
- package/dist/types/src/playwright/TableManager.d.ts.map +1 -1
- package/dist/types/src/playwright/playwright.config.d.ts.map +1 -1
- package/dist/types/src/testing/useTestTableModel.d.ts +18 -34
- package/dist/types/src/testing/useTestTableModel.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +21 -23
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types/Table.d.ts +32 -0
- package/dist/types/src/types/Table.d.ts.map +1 -0
- package/dist/types/src/types/index.d.ts +1 -1
- package/dist/types/src/types/index.d.ts.map +1 -1
- package/dist/types/src/util/dynamic-table.d.ts +14 -12
- package/dist/types/src/util/dynamic-table.d.ts.map +1 -1
- package/dist/types/src/util/dynamic-table.test.d.ts +2 -0
- package/dist/types/src/util/dynamic-table.test.d.ts.map +1 -0
- package/dist/types/src/util/index.d.ts +2 -1
- package/dist/types/src/util/index.d.ts.map +1 -1
- package/dist/types/src/util/query-ast.d.ts +7 -0
- package/dist/types/src/util/query-ast.d.ts.map +1 -0
- package/dist/types/src/util/schema.d.ts +1 -1
- package/dist/types/src/util/schema.d.ts.map +1 -1
- package/dist/types/src/util/signals.d.ts.map +1 -1
- package/dist/types/src/util/sort.d.ts +12 -0
- package/dist/types/src/util/sort.d.ts.map +1 -0
- package/dist/types/src/util/table-buttons.d.ts +20 -20
- package/dist/types/src/util/table-buttons.d.ts.map +1 -1
- package/dist/types/src/util/table-controls.d.ts +4 -4
- package/dist/types/src/util/table-controls.d.ts.map +1 -1
- package/dist/types/src/util/tag.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +68 -77
- package/src/components/Table/ColumnActionsMenu.tsx +17 -12
- package/src/components/Table/ColumnSettings.tsx +8 -9
- package/src/components/Table/DynamicTable.stories.tsx +41 -38
- package/src/components/Table/DynamicTable.tsx +32 -36
- package/src/components/Table/Relations.stories.tsx +219 -61
- package/src/components/Table/RowActionsMenu.tsx +27 -17
- package/src/components/Table/Table.stories.tsx +217 -141
- package/src/components/Table/Table.tsx +46 -391
- package/src/components/Table/TableContent.tsx +426 -0
- package/src/components/Table/TableToolbar.tsx +111 -0
- package/src/components/TableCellEditor/CellValidationMessage.tsx +5 -6
- package/src/components/TableCellEditor/FormCellEditor.tsx +136 -41
- package/src/components/TableCellEditor/TableCellEditor.stories.tsx +39 -73
- package/src/components/TableCellEditor/TableCellEditor.tsx +81 -223
- package/src/components/TableCellEditor/index.ts +1 -0
- package/src/components/index.ts +0 -1
- package/src/components/testing.ts +42 -21
- package/src/hooks/index.ts +2 -1
- package/src/hooks/useAddRow.ts +14 -14
- package/src/hooks/useProjectionModel.ts +38 -0
- package/src/hooks/useTableModel.ts +36 -34
- package/src/index.ts +0 -4
- package/src/model/modal-controller.ts +23 -40
- package/src/model/selection-model.ts +75 -44
- package/src/model/table-model.test.ts +86 -56
- package/src/model/table-model.ts +464 -182
- package/src/model/table-presentation.test.ts +64 -59
- package/src/model/table-presentation.ts +107 -83
- package/src/playwright/TableManager.ts +13 -6
- package/src/playwright/playwright.config.ts +1 -1
- package/src/playwright/smoke.spec.ts +92 -46
- package/src/testing/useTestTableModel.ts +51 -42
- package/src/translations.ts +20 -22
- package/src/types/Table.ts +80 -0
- package/src/types/index.ts +1 -1
- package/src/util/dynamic-table.test.ts +63 -0
- package/src/util/dynamic-table.ts +53 -39
- package/src/util/index.ts +2 -1
- package/src/util/query-ast.ts +22 -0
- package/src/util/schema.ts +4 -4
- package/src/util/sort.ts +90 -0
- package/src/util/table-buttons.ts +3 -3
- package/src/util/table-controls.ts +2 -2
- package/dist/lib/browser/chunk-L2LSB6KV.mjs +0 -18
- package/dist/lib/browser/chunk-L2LSB6KV.mjs.map +0 -7
- package/dist/lib/browser/chunk-ZAOSIG3L.mjs +0 -1814
- package/dist/lib/browser/chunk-ZAOSIG3L.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-NXZ4CJYX.mjs +0 -20
- package/dist/lib/node-esm/chunk-NXZ4CJYX.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-ZOFFI3JJ.mjs +0 -1815
- package/dist/lib/node-esm/chunk-ZOFFI3JJ.mjs.map +0 -7
- package/dist/types/src/components/Table/CreateRefPanel.d.ts +0 -9
- package/dist/types/src/components/Table/CreateRefPanel.d.ts.map +0 -1
- package/dist/types/src/components/TableCellEditor/extension.d.ts +0 -13
- package/dist/types/src/components/TableCellEditor/extension.d.ts.map +0 -1
- package/dist/types/src/components/TableToolbar/TableToolbar.d.ts +0 -21
- package/dist/types/src/components/TableToolbar/TableToolbar.d.ts.map +0 -1
- package/dist/types/src/components/TableToolbar/index.d.ts +0 -2
- package/dist/types/src/components/TableToolbar/index.d.ts.map +0 -1
- package/dist/types/src/model/table-sorting.d.ts +0 -53
- package/dist/types/src/model/table-sorting.d.ts.map +0 -1
- package/dist/types/src/types/schema.d.ts +0 -8
- package/dist/types/src/types/schema.d.ts.map +0 -1
- package/dist/types/src/util/table.d.ts +0 -12
- package/dist/types/src/util/table.d.ts.map +0 -1
- package/src/components/Table/CreateRefPanel.tsx +0 -86
- package/src/components/TableCellEditor/extension.ts +0 -61
- package/src/components/TableToolbar/TableToolbar.tsx +0 -102
- package/src/components/TableToolbar/index.ts +0 -5
- package/src/model/table-sorting.ts +0 -216
- package/src/types/schema.ts +0 -16
- package/src/util/table.ts +0 -53
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import { expect, test } from '@playwright/test';
|
|
6
6
|
|
|
7
7
|
import { type DxGrid } from '@dxos/lit-grid';
|
|
8
|
+
import { random } from '@dxos/random';
|
|
8
9
|
import { setupPage, storybookUrl } from '@dxos/test-utils/playwright';
|
|
9
10
|
|
|
10
11
|
import { TableManager } from './TableManager';
|
|
@@ -12,10 +13,11 @@ import { TableManager } from './TableManager';
|
|
|
12
13
|
const storyUrl = storybookUrl('ui-react-ui-table-table--default', 9004);
|
|
13
14
|
const relationsStoryUrl = storybookUrl('ui-react-ui-table-relations--default', 9004);
|
|
14
15
|
|
|
15
|
-
// NOTE(ZaymonFC): This test suite relies on the
|
|
16
|
+
// NOTE(ZaymonFC): This test suite relies on the random seed being set to 0 in the story.
|
|
16
17
|
test.describe('Table', () => {
|
|
17
18
|
test('Loads', async ({ browser, browserName }) => {
|
|
18
19
|
test.skip(browserName === 'webkit');
|
|
20
|
+
test.skip(browserName === 'firefox');
|
|
19
21
|
const { page } = await setupPage(browser, { url: storyUrl });
|
|
20
22
|
const table = new TableManager(page);
|
|
21
23
|
|
|
@@ -25,6 +27,7 @@ test.describe('Table', () => {
|
|
|
25
27
|
|
|
26
28
|
test('sort', async ({ browser, browserName }) => {
|
|
27
29
|
test.skip(browserName === 'webkit');
|
|
30
|
+
test.skip(browserName === 'firefox');
|
|
28
31
|
const { page } = await setupPage(browser, { url: storyUrl });
|
|
29
32
|
const table = new TableManager(page);
|
|
30
33
|
|
|
@@ -41,6 +44,7 @@ test.describe('Table', () => {
|
|
|
41
44
|
|
|
42
45
|
test('selection', async ({ browser, browserName }) => {
|
|
43
46
|
test.skip(browserName === 'webkit');
|
|
47
|
+
test.skip(browserName === 'firefox');
|
|
44
48
|
const { page } = await setupPage(browser, { url: storyUrl });
|
|
45
49
|
const table = new TableManager(page);
|
|
46
50
|
|
|
@@ -62,10 +66,12 @@ test.describe('Table', () => {
|
|
|
62
66
|
|
|
63
67
|
test('delete row', async ({ browser, browserName }) => {
|
|
64
68
|
test.skip(browserName === 'webkit');
|
|
69
|
+
test.skip(browserName === 'firefox');
|
|
65
70
|
const { page } = await setupPage(browser, { url: storyUrl });
|
|
66
71
|
const table = new TableManager(page);
|
|
67
72
|
|
|
68
73
|
await table.grid.ready();
|
|
74
|
+
await expect(page.getByRole('gridcell', { name: 'Sapiente.' })).toHaveCount(1);
|
|
69
75
|
await table.deleteRow(0);
|
|
70
76
|
await expect(page.getByRole('gridcell', { name: 'Sapiente.' })).toHaveCount(0);
|
|
71
77
|
await page.close();
|
|
@@ -73,6 +79,7 @@ test.describe('Table', () => {
|
|
|
73
79
|
|
|
74
80
|
test('delete row--select all', async ({ browser, browserName }) => {
|
|
75
81
|
test.skip(browserName === 'webkit');
|
|
82
|
+
test.skip(browserName === 'firefox');
|
|
76
83
|
const { page } = await setupPage(browser, { url: storyUrl });
|
|
77
84
|
const table = new TableManager(page);
|
|
78
85
|
|
|
@@ -82,7 +89,7 @@ test.describe('Table', () => {
|
|
|
82
89
|
// Delete action affects all selected rows.
|
|
83
90
|
await table.deleteRow(0);
|
|
84
91
|
|
|
85
|
-
await expect(page.getByRole('gridcell', { name: '
|
|
92
|
+
await expect(page.getByRole('gridcell', { name: 'Aut.' })).toHaveCount(0);
|
|
86
93
|
await expect(page.getByRole('gridcell', { name: 'Beatae.' })).toHaveCount(0);
|
|
87
94
|
await expect(table.grid.cellsWithinPlane('grid')).toHaveCount(0);
|
|
88
95
|
await page.close();
|
|
@@ -90,6 +97,7 @@ test.describe('Table', () => {
|
|
|
90
97
|
|
|
91
98
|
test('delete column', async ({ browser, browserName }) => {
|
|
92
99
|
test.skip(browserName === 'webkit');
|
|
100
|
+
test.skip(browserName === 'firefox');
|
|
93
101
|
const { page } = await setupPage(browser, { url: storyUrl });
|
|
94
102
|
const table = new TableManager(page);
|
|
95
103
|
|
|
@@ -113,59 +121,39 @@ test.describe('Table', () => {
|
|
|
113
121
|
await page.close();
|
|
114
122
|
});
|
|
115
123
|
|
|
116
|
-
|
|
117
|
-
test('add column', async ({ browser, browserName }) => {
|
|
124
|
+
test('add column without changing format', async ({ browser, browserName }) => {
|
|
118
125
|
test.skip(browserName === 'webkit');
|
|
126
|
+
test.skip(browserName === 'firefox');
|
|
119
127
|
const { page } = await setupPage(browser, { url: storyUrl });
|
|
120
128
|
const table = new TableManager(page);
|
|
121
129
|
|
|
122
130
|
await table.grid.ready();
|
|
123
|
-
const newColumnLabel = '
|
|
131
|
+
const newColumnLabel = 'DEFAULT FORMAT COL';
|
|
124
132
|
|
|
125
|
-
await table.addColumn({ label: newColumnLabel
|
|
133
|
+
await table.addColumn({ label: newColumnLabel });
|
|
126
134
|
|
|
127
135
|
await expect(page.getByRole('gridcell', { name: newColumnLabel })).toBeVisible();
|
|
128
136
|
await page.close();
|
|
129
137
|
});
|
|
130
138
|
|
|
131
|
-
test('
|
|
139
|
+
test('add column with format', async ({ browser, browserName }) => {
|
|
132
140
|
test.skip(browserName === 'webkit');
|
|
141
|
+
test.skip(browserName === 'firefox');
|
|
133
142
|
const { page } = await setupPage(browser, { url: storyUrl });
|
|
134
143
|
const table = new TableManager(page);
|
|
135
144
|
|
|
136
145
|
await table.grid.ready();
|
|
146
|
+
const newColumnLabel = 'TEST LABEL';
|
|
137
147
|
|
|
138
|
-
|
|
139
|
-
// Scroll over to the manager column.
|
|
140
|
-
await table.grid.panByWheel(10000, 0);
|
|
141
|
-
|
|
142
|
-
await table.grid.cell(4, 0, 'grid').click();
|
|
143
|
-
// TODO(wittjosiah): Surprisingly long delay needed here.
|
|
144
|
-
await page.keyboard.press('A', { delay: 1_000 });
|
|
145
|
-
await page.keyboard.press('u', { delay: 1_000 });
|
|
146
|
-
await page.getByRole('option', { name: 'Aut.' }).click();
|
|
147
|
-
|
|
148
|
-
// Assert that the value is shown in the cell.
|
|
149
|
-
await expect(page.getByRole('gridcell', { name: 'Aut.' }).first()).toBeVisible();
|
|
150
|
-
|
|
151
|
-
// Create new object.
|
|
152
|
-
await table.grid.cell(4, 1, 'grid').click();
|
|
153
|
-
// TODO(wittjosiah): Surprisingly long delay needed here.
|
|
154
|
-
await page.keyboard.type('t', { delay: 1_000 });
|
|
155
|
-
await page.keyboard.type('e', { delay: 1_000 });
|
|
156
|
-
await page.keyboard.type('s', { delay: 1_000 });
|
|
157
|
-
await page.keyboard.type('t', { delay: 1_000 });
|
|
158
|
-
await page.getByText('Create new object', { exact: false }).click();
|
|
159
|
-
await page.getByTestId('save-button').click();
|
|
160
|
-
|
|
161
|
-
// Scroll to the left.
|
|
162
|
-
await page.getByRole('gridcell', { name: 'test' }).first().click();
|
|
148
|
+
await table.addColumn({ label: newColumnLabel, format: 'Number' });
|
|
163
149
|
|
|
150
|
+
await expect(page.getByRole('gridcell', { name: newColumnLabel })).toBeVisible();
|
|
164
151
|
await page.close();
|
|
165
152
|
});
|
|
166
153
|
|
|
167
|
-
test('test toggles', async ({ browser, browserName }) => {
|
|
154
|
+
test.skip('test toggles', async ({ browser, browserName }) => {
|
|
168
155
|
test.skip(browserName === 'webkit');
|
|
156
|
+
test.skip(browserName === 'firefox');
|
|
169
157
|
const { page } = await setupPage(browser, { url: storyUrl });
|
|
170
158
|
const table = new TableManager(page);
|
|
171
159
|
|
|
@@ -180,14 +168,45 @@ test.describe('Table', () => {
|
|
|
180
168
|
// Assert the first two switch checkboxes are checked.
|
|
181
169
|
await expect(page.getByTestId('table-switch').first()).toBeChecked();
|
|
182
170
|
await expect(page.getByTestId('table-switch').nth(1)).toBeChecked();
|
|
183
|
-
await expect(table.grid.cell(0, 0, 'grid')).toHaveText('
|
|
171
|
+
await expect(table.grid.cell(0, 0, 'grid')).toHaveText('Aut.');
|
|
184
172
|
await expect(table.grid.cell(0, 1, 'grid')).toHaveText('Beatae.');
|
|
185
173
|
|
|
186
174
|
await page.close();
|
|
187
175
|
});
|
|
188
176
|
|
|
189
|
-
test('
|
|
177
|
+
test('add row and edit cell', async ({ browser, browserName }) => {
|
|
190
178
|
test.skip(browserName === 'webkit');
|
|
179
|
+
test.skip(browserName === 'firefox');
|
|
180
|
+
const { page } = await setupPage(browser, { url: storyUrl });
|
|
181
|
+
const table = new TableManager(page);
|
|
182
|
+
|
|
183
|
+
await table.grid.ready();
|
|
184
|
+
|
|
185
|
+
// Click the CTA row at the bottom to add a new row.
|
|
186
|
+
await table.grid.cell(0, 0, 'frozenRowsEnd').click();
|
|
187
|
+
|
|
188
|
+
// All schema fields are optional so the row is added directly to the grid (not as a draft).
|
|
189
|
+
const newCell = table.grid.cell(0, 10, 'grid');
|
|
190
|
+
await newCell.waitFor({ state: 'visible' });
|
|
191
|
+
|
|
192
|
+
// Focus should already be on the new row; engage edit mode.
|
|
193
|
+
await page.keyboard.press('Enter');
|
|
194
|
+
await page.getByTestId('grid.cell-editor').waitFor({ state: 'visible' });
|
|
195
|
+
|
|
196
|
+
// Type text and confirm.
|
|
197
|
+
const cellContent = 'New row content';
|
|
198
|
+
await page.keyboard.type(cellContent);
|
|
199
|
+
await page.keyboard.press('Enter');
|
|
200
|
+
|
|
201
|
+
// Assert the cell content is saved.
|
|
202
|
+
await expect(newCell).toHaveText(cellContent);
|
|
203
|
+
await page.close();
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
// TODO(wittjosiah): Remove? Conflicts with story play function which is run as a unit test anyways.
|
|
207
|
+
test.skip('extant relations work as expected', async ({ browser, browserName }) => {
|
|
208
|
+
test.skip(browserName === 'webkit');
|
|
209
|
+
test.skip(browserName === 'firefox');
|
|
191
210
|
const { page } = await setupPage(browser, { url: relationsStoryUrl });
|
|
192
211
|
|
|
193
212
|
// Wait for the page to load
|
|
@@ -198,18 +217,22 @@ test.describe('Table', () => {
|
|
|
198
217
|
const dxGrid = page.locator('dx-grid').nth(1);
|
|
199
218
|
await dxGrid.waitFor({ state: 'visible' });
|
|
200
219
|
|
|
201
|
-
// Scroll to the last column (column
|
|
220
|
+
// Scroll to the last column (column 4)
|
|
202
221
|
await dxGrid.evaluate(async (dxGridElement: DxGrid) => {
|
|
203
|
-
dxGridElement.scrollToColumn(
|
|
222
|
+
dxGridElement.scrollToColumn(4);
|
|
204
223
|
});
|
|
205
224
|
|
|
206
|
-
// Click on the cell at aria-rowindex=0 aria-colindex=
|
|
207
|
-
const targetCell = dxGrid.locator('[data-dx-grid-plane="grid"] [aria-rowindex="0"][aria-colindex="
|
|
225
|
+
// Click on the cell at aria-rowindex=0 aria-colindex=4 to focus it
|
|
226
|
+
const targetCell = dxGrid.locator('[data-dx-grid-plane="grid"] [aria-rowindex="0"][aria-colindex="4"]');
|
|
208
227
|
await targetCell.click();
|
|
209
228
|
|
|
210
229
|
// Click again to engage edit mode
|
|
211
230
|
await page.keyboard.press('Enter');
|
|
212
|
-
|
|
231
|
+
|
|
232
|
+
// Click on the combobox to open options
|
|
233
|
+
await page.getByRole('combobox').click();
|
|
234
|
+
await page.pause();
|
|
235
|
+
await page.getByPlaceholder('Search…').focus();
|
|
213
236
|
|
|
214
237
|
// Type the first few letters of an org name.
|
|
215
238
|
const orgName =
|
|
@@ -226,14 +249,19 @@ test.describe('Table', () => {
|
|
|
226
249
|
// Type the enter key
|
|
227
250
|
await page.keyboard.press('Enter');
|
|
228
251
|
|
|
252
|
+
// Save the result
|
|
253
|
+
await page.getByTestId('save-button').click();
|
|
254
|
+
|
|
229
255
|
// Assert that the cell element has the org name
|
|
230
256
|
await expect(targetCell).toHaveText(orgName);
|
|
231
257
|
|
|
232
258
|
await page.close();
|
|
233
259
|
});
|
|
234
260
|
|
|
235
|
-
|
|
261
|
+
// TODO(wittjosiah): Remove? Conflicts with story play function which is run as a unit test anyways.
|
|
262
|
+
test.skip('new relations work as expected', async ({ browser, browserName }) => {
|
|
236
263
|
test.skip(browserName === 'webkit');
|
|
264
|
+
test.skip(browserName === 'firefox');
|
|
237
265
|
const { page } = await setupPage(browser, { url: relationsStoryUrl });
|
|
238
266
|
|
|
239
267
|
// Wait for the page to load
|
|
@@ -244,18 +272,21 @@ test.describe('Table', () => {
|
|
|
244
272
|
const dxGrid = page.locator('dx-grid').nth(1);
|
|
245
273
|
await dxGrid.waitFor({ state: 'visible' });
|
|
246
274
|
|
|
247
|
-
// Scroll to the last column (column
|
|
275
|
+
// Scroll to the last column (column 4)
|
|
248
276
|
await dxGrid.evaluate(async (dxGridElement: DxGrid) => {
|
|
249
|
-
dxGridElement.scrollToColumn(
|
|
277
|
+
dxGridElement.scrollToColumn(4);
|
|
250
278
|
});
|
|
251
279
|
|
|
252
280
|
// Click on the cell at aria-rowindex=0 aria-colindex=8 to focus it
|
|
253
|
-
const targetCell = dxGrid.locator('[data-dx-grid-plane="grid"] [aria-rowindex="0"][aria-colindex="
|
|
281
|
+
const targetCell = dxGrid.locator('[data-dx-grid-plane="grid"] [aria-rowindex="0"][aria-colindex="4"]');
|
|
254
282
|
await targetCell.click();
|
|
255
283
|
|
|
256
284
|
// Click again to engage edit mode
|
|
257
285
|
await page.keyboard.press('Enter');
|
|
258
|
-
|
|
286
|
+
|
|
287
|
+
// Click on the combobox to open options
|
|
288
|
+
await page.getByRole('combobox').click();
|
|
289
|
+
await page.getByPlaceholder('Search…').focus();
|
|
259
290
|
|
|
260
291
|
// Type the first few letters of an org name.
|
|
261
292
|
const orgName = 'Sally';
|
|
@@ -266,13 +297,28 @@ test.describe('Table', () => {
|
|
|
266
297
|
|
|
267
298
|
// Type the enter key
|
|
268
299
|
await page.keyboard.press('Enter');
|
|
300
|
+
await page.pause();
|
|
269
301
|
|
|
270
302
|
// Click the save button in the popover
|
|
271
|
-
await page.getByTestId('save-button').click();
|
|
303
|
+
await page.getByTestId('create-referenced-object-form').getByTestId('save-button').click();
|
|
272
304
|
|
|
273
305
|
// Assert that the cell element has the org name
|
|
274
306
|
await expect(targetCell).toHaveText(orgName);
|
|
275
307
|
|
|
308
|
+
// Make a change to a non-ref cell to check that populated refs don’t cause problems with snapshots or schemas.
|
|
309
|
+
await dxGrid.evaluate(async (dxGridElement: DxGrid) => {
|
|
310
|
+
dxGridElement.scrollToColumn(6);
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
const nonRefContent = random.lorem.words(3);
|
|
314
|
+
const nonRefCell = dxGrid.locator('[data-dx-grid-plane="grid"] [aria-rowindex="0"][aria-colindex="6"]');
|
|
315
|
+
await nonRefCell.click();
|
|
316
|
+
await page.keyboard.press('Enter');
|
|
317
|
+
await page.getByTestId('grid.cell-editor').waitFor({ state: 'visible' });
|
|
318
|
+
await page.keyboard.type(nonRefContent, { delay: 500 });
|
|
319
|
+
await page.keyboard.press('Enter');
|
|
320
|
+
await expect(nonRefCell).toHaveText(nonRefContent);
|
|
321
|
+
|
|
276
322
|
await page.close();
|
|
277
323
|
});
|
|
278
324
|
});
|
|
@@ -2,51 +2,62 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { RegistryContext } from '@effect-atom/atom-react';
|
|
6
|
+
import { type RefObject, useCallback, useContext, useMemo, useRef } from 'react';
|
|
6
7
|
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import { DataType, ProjectionModel } from '@dxos/schema';
|
|
8
|
+
import { type Database, Filter, Type } from '@dxos/echo';
|
|
9
|
+
import { random } from '@dxos/random';
|
|
10
|
+
import { useQuery, useType } from '@dxos/react-client/echo';
|
|
11
|
+
import { useClientStory } from '@dxos/react-client/testing';
|
|
12
|
+
import { useGlobalFilteredObjects } from '@dxos/react-ui-search';
|
|
13
|
+
import { type ProjectionModel, getTypeURIFromQuery } from '@dxos/schema';
|
|
14
14
|
|
|
15
15
|
import { type TableController } from '../components';
|
|
16
|
-
import { useAddRow, useTableModel } from '../hooks';
|
|
17
|
-
import { TablePresentation } from '../model';
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
import { useAddRow, useProjectionModel, useTableModel } from '../hooks';
|
|
17
|
+
import { type TableModel, TablePresentation } from '../model';
|
|
18
|
+
import { Table } from '../types';
|
|
19
|
+
|
|
20
|
+
random.seed(0); // NOTE(ZaymonFC): Required for smoke tests.
|
|
21
|
+
|
|
22
|
+
export type TestTableModel<T extends Type.AnyObj = Type.AnyObj> = {
|
|
23
|
+
schema: T | undefined;
|
|
24
|
+
table: Table.Table | undefined;
|
|
25
|
+
projection: ProjectionModel | undefined;
|
|
26
|
+
tableRef: RefObject<TableController | null>;
|
|
27
|
+
model: TableModel | undefined;
|
|
28
|
+
presentation: TablePresentation | undefined;
|
|
29
|
+
db: Database.Database | undefined;
|
|
30
|
+
handleInsertRow: () => void;
|
|
31
|
+
handleSaveView: () => void;
|
|
32
|
+
handleDeleteRows: (rowIndex: number, objects: any[]) => void;
|
|
33
|
+
handleDeleteColumn: (fieldId: string) => void;
|
|
34
|
+
};
|
|
20
35
|
|
|
21
36
|
/**
|
|
22
37
|
* Custom hook to create and manage a test table model for storybook demonstrations.
|
|
23
38
|
* Provides table data, schema, and handlers for table operations.
|
|
24
39
|
*/
|
|
25
|
-
export const useTestTableModel = () => {
|
|
26
|
-
const
|
|
27
|
-
const { space } =
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
const
|
|
31
|
-
const
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
const projection =
|
|
35
|
-
if (schema && view?.projection) {
|
|
36
|
-
return new ProjectionModel(toJsonSchema(schema), view.projection);
|
|
37
|
-
}
|
|
38
|
-
}, [schema, view?.projection]);
|
|
40
|
+
export const useTestTableModel = <T extends Type.AnyObj = Type.AnyObj>(): TestTableModel<T> => {
|
|
41
|
+
const registry = useContext(RegistryContext);
|
|
42
|
+
const { space } = useClientStory();
|
|
43
|
+
const db = space?.db;
|
|
44
|
+
|
|
45
|
+
const tables = useQuery(space?.db, Filter.type(Table.Table));
|
|
46
|
+
const table = tables.at(0);
|
|
47
|
+
const typeUri = table?.view.target?.query ? getTypeURIFromQuery(table.view.target.query.ast) : undefined;
|
|
48
|
+
const schema = useType<T>(space?.db, typeUri);
|
|
49
|
+
const projection = useProjectionModel(schema, table, registry);
|
|
39
50
|
|
|
40
51
|
const features = useMemo(
|
|
41
52
|
() => ({
|
|
42
53
|
selection: { enabled: true, mode: 'multiple' as const },
|
|
43
54
|
dataEditable: true,
|
|
44
|
-
schemaEditable: schema &&
|
|
55
|
+
schemaEditable: schema != null && Type.getDatabase(schema) != null,
|
|
45
56
|
}),
|
|
46
57
|
[schema],
|
|
47
58
|
);
|
|
48
59
|
|
|
49
|
-
const objects = useQuery(
|
|
60
|
+
const objects = useQuery(db, schema ? Filter.type(schema) : Filter.nothing());
|
|
50
61
|
const filteredObjects = useGlobalFilteredObjects(objects);
|
|
51
62
|
|
|
52
63
|
const tableRef = useRef<TableController>(null);
|
|
@@ -58,15 +69,15 @@ export const useTestTableModel = () => {
|
|
|
58
69
|
tableRef.current?.update?.();
|
|
59
70
|
}, []);
|
|
60
71
|
|
|
61
|
-
const addRow = useAddRow({
|
|
72
|
+
const addRow = useAddRow({ db, schema });
|
|
62
73
|
|
|
63
74
|
const handleDeleteRows = useCallback(
|
|
64
75
|
(_: number, objects: any[]) => {
|
|
65
76
|
for (const object of objects) {
|
|
66
|
-
|
|
77
|
+
db?.remove(object);
|
|
67
78
|
}
|
|
68
79
|
},
|
|
69
|
-
[
|
|
80
|
+
[db],
|
|
70
81
|
);
|
|
71
82
|
|
|
72
83
|
const handleDeleteColumn = useCallback(
|
|
@@ -79,22 +90,21 @@ export const useTestTableModel = () => {
|
|
|
79
90
|
);
|
|
80
91
|
|
|
81
92
|
const model = useTableModel({
|
|
82
|
-
|
|
83
|
-
schema: jsonSchema,
|
|
93
|
+
object: table,
|
|
84
94
|
projection,
|
|
85
95
|
features,
|
|
86
96
|
rows: filteredObjects,
|
|
87
97
|
onInsertRow: addRow,
|
|
88
98
|
onDeleteRows: handleDeleteRows,
|
|
89
|
-
|
|
99
|
+
onColumnDelete: handleDeleteColumn,
|
|
90
100
|
onCellUpdate: handleCellUpdate,
|
|
91
101
|
onRowOrderChange: handleRowOrderChange,
|
|
92
102
|
});
|
|
93
103
|
|
|
94
104
|
const handleInsertRow = useCallback(() => {
|
|
95
|
-
model?.insertRow();
|
|
96
|
-
tableRef.current?.
|
|
97
|
-
}, [model
|
|
105
|
+
const insertResult = model?.insertRow();
|
|
106
|
+
tableRef.current?.handleInsertRowResult?.(insertResult);
|
|
107
|
+
}, [model]);
|
|
98
108
|
|
|
99
109
|
const handleSaveView = useCallback(() => {
|
|
100
110
|
model?.saveView();
|
|
@@ -102,19 +112,18 @@ export const useTestTableModel = () => {
|
|
|
102
112
|
|
|
103
113
|
const presentation = useMemo(() => {
|
|
104
114
|
if (model) {
|
|
105
|
-
return new TablePresentation(model);
|
|
115
|
+
return new TablePresentation(registry, model);
|
|
106
116
|
}
|
|
107
|
-
}, [model]);
|
|
117
|
+
}, [registry, model]);
|
|
108
118
|
|
|
109
119
|
return {
|
|
110
120
|
schema,
|
|
111
|
-
|
|
121
|
+
table,
|
|
112
122
|
projection,
|
|
113
123
|
tableRef,
|
|
114
124
|
model,
|
|
115
125
|
presentation,
|
|
116
|
-
|
|
117
|
-
client,
|
|
126
|
+
db,
|
|
118
127
|
handleInsertRow,
|
|
119
128
|
handleSaveView,
|
|
120
129
|
handleDeleteRows,
|
package/src/translations.ts
CHANGED
|
@@ -4,33 +4,31 @@
|
|
|
4
4
|
|
|
5
5
|
import { type Resource } from '@dxos/react-ui';
|
|
6
6
|
|
|
7
|
-
export const translationKey = 'react-ui-table';
|
|
7
|
+
export const translationKey = '@dxos/react-ui-table';
|
|
8
8
|
|
|
9
9
|
export const translations = [
|
|
10
10
|
{
|
|
11
11
|
'en-US': {
|
|
12
12
|
[translationKey]: {
|
|
13
|
-
'object
|
|
14
|
-
'create
|
|
15
|
-
'table
|
|
16
|
-
'settings
|
|
17
|
-
'table
|
|
18
|
-
'
|
|
19
|
-
'
|
|
20
|
-
'
|
|
21
|
-
'
|
|
22
|
-
'
|
|
23
|
-
'column
|
|
24
|
-
'column
|
|
25
|
-
'column
|
|
26
|
-
'
|
|
27
|
-
'
|
|
28
|
-
'
|
|
29
|
-
'
|
|
30
|
-
'
|
|
31
|
-
'
|
|
32
|
-
'create new object label': 'Create new object “{{text}}”',
|
|
33
|
-
'save view label': 'Save changes to view',
|
|
13
|
+
'object.placeholder': 'New table',
|
|
14
|
+
'create-object.label': 'Create table',
|
|
15
|
+
'table-name.placeholder': 'Table name',
|
|
16
|
+
'settings.title': 'Table settings',
|
|
17
|
+
'table-schema.label': 'Type',
|
|
18
|
+
'continue.label': 'Continue',
|
|
19
|
+
'create-stack-section.label': 'Create table',
|
|
20
|
+
'add-row.label': 'Add row',
|
|
21
|
+
'column-action-sort-descending.menu': 'Sort Descending',
|
|
22
|
+
'column-action-sort-ascending.menu': 'Sort Ascending',
|
|
23
|
+
'column-action-clear-sorting.menu': 'Clear Sorting',
|
|
24
|
+
'column-action-settings.menu': 'Column Settings',
|
|
25
|
+
'column-action-delete.menu': 'Delete Column',
|
|
26
|
+
'delete-row.label': 'Delete row',
|
|
27
|
+
'bulk-delete-row.label': 'Delete selected rows',
|
|
28
|
+
'column-deleted.label': 'Column deleted',
|
|
29
|
+
'new-column-button.label': 'Create column',
|
|
30
|
+
'create-new-object.label': 'Create new object “{{text}}”',
|
|
31
|
+
'save-view.label': 'Save changes to view',
|
|
34
32
|
},
|
|
35
33
|
},
|
|
36
34
|
},
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import * as Match from 'effect/Match';
|
|
6
|
+
import * as Schema from 'effect/Schema';
|
|
7
|
+
import * as SchemaAST from 'effect/SchemaAST';
|
|
8
|
+
|
|
9
|
+
// QueryAST is referenced indirectly through `Type.InstanceType<typeof TableSchema>`
|
|
10
|
+
// (Ref.Ref(View.View) → View.View → QueryAST.Query) in the emitted .d.ts; the
|
|
11
|
+
// namespace import keeps the inferred types portable.
|
|
12
|
+
// eslint-disable-next-line unused-imports/no-unused-imports
|
|
13
|
+
import { DXN, Annotation, JsonSchema, Obj, QueryAST, Ref, Type, View } from '@dxos/echo';
|
|
14
|
+
import { FormInputAnnotation, LabelAnnotation } from '@dxos/echo/Annotation';
|
|
15
|
+
import { type JsonSchema as JsonSchemaType } from '@dxos/echo/JsonSchema';
|
|
16
|
+
import { SchemaEx } from '@dxos/effect';
|
|
17
|
+
import { ViewAnnotation } from '@dxos/schema';
|
|
18
|
+
|
|
19
|
+
const TableSchema = Schema.Struct({
|
|
20
|
+
name: Schema.String.pipe(Schema.optional),
|
|
21
|
+
|
|
22
|
+
view: Ref.Ref(View.View).pipe(FormInputAnnotation.set(false)),
|
|
23
|
+
|
|
24
|
+
sizes: Schema.Record({
|
|
25
|
+
// TODO(wittjosiah): Should be JsonPath.
|
|
26
|
+
key: Schema.String,
|
|
27
|
+
value: Schema.Number,
|
|
28
|
+
}).pipe(Schema.mutable, FormInputAnnotation.set(false)),
|
|
29
|
+
}).pipe(
|
|
30
|
+
LabelAnnotation.set(['name']),
|
|
31
|
+
ViewAnnotation.set(['view']),
|
|
32
|
+
Annotation.IconAnnotation.set({ icon: 'ph--table--regular', hue: 'green' }),
|
|
33
|
+
Type.makeObject(DXN.make('org.dxos.type.table', '0.1.0')),
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
// TODO(wittjosiah): Try to clean up this type inference.
|
|
37
|
+
export interface Table extends Type.InstanceType<typeof TableSchema> {}
|
|
38
|
+
export const Table = TableSchema;
|
|
39
|
+
|
|
40
|
+
type MakeProps = {
|
|
41
|
+
name?: string;
|
|
42
|
+
sizes?: Record<string, number>;
|
|
43
|
+
view: View.View;
|
|
44
|
+
/** Required to auto-size columns. */
|
|
45
|
+
jsonSchema?: JsonSchemaType;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Make a table as a view of a data set.
|
|
50
|
+
*/
|
|
51
|
+
export const make = ({ name, sizes = {}, view, jsonSchema }: MakeProps): Table => {
|
|
52
|
+
const table = Obj.make(Table, { name, view: Ref.make(view), sizes } as Obj.MakeProps<typeof Table>);
|
|
53
|
+
|
|
54
|
+
// Preset sizes.
|
|
55
|
+
if (jsonSchema) {
|
|
56
|
+
const schema = JsonSchema.toEffectSchema(jsonSchema);
|
|
57
|
+
const properties = SchemaAST.getPropertySignatures(schema.ast);
|
|
58
|
+
for (const property of properties) {
|
|
59
|
+
const name = property.name.toString() as SchemaEx.JsonPath;
|
|
60
|
+
if (sizes?.[name]) {
|
|
61
|
+
table.sizes[name] = sizes[name];
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
Match.type<SchemaAST.AST>().pipe(
|
|
66
|
+
Match.when({ _tag: 'BooleanKeyword' }, () => {
|
|
67
|
+
table.sizes[name] = 100;
|
|
68
|
+
}),
|
|
69
|
+
Match.when({ _tag: 'NumberKeyword' }, () => {
|
|
70
|
+
table.sizes[name] = 100;
|
|
71
|
+
}),
|
|
72
|
+
Match.orElse(() => {
|
|
73
|
+
// Noop.
|
|
74
|
+
}),
|
|
75
|
+
)(property.type);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return table;
|
|
80
|
+
};
|
package/src/types/index.ts
CHANGED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { Registry } from '@effect-atom/atom-react';
|
|
6
|
+
import { describe, expect, test } from 'vitest';
|
|
7
|
+
|
|
8
|
+
import { Format } from '@dxos/echo';
|
|
9
|
+
|
|
10
|
+
import { type TablePropertyDefinition, getBaseSchema, makeDynamicTable } from './dynamic-table';
|
|
11
|
+
|
|
12
|
+
describe('makeDynamicTable', () => {
|
|
13
|
+
/**
|
|
14
|
+
* Builds the Type entity from a JSON schema, then makes the table.
|
|
15
|
+
* Confirms makeDynamicTable + setProperties (title) works for the jsonSchema path.
|
|
16
|
+
*/
|
|
17
|
+
test('makeDynamicTable from a jsonSchema with properties with title does not throw', () => {
|
|
18
|
+
const registry = Registry.make();
|
|
19
|
+
const jsonSchema = {
|
|
20
|
+
typename: 'com.example.type.dynamicTablePlain',
|
|
21
|
+
version: '0.1.0',
|
|
22
|
+
type: 'object' as const,
|
|
23
|
+
properties: {
|
|
24
|
+
id: { type: 'string' as const },
|
|
25
|
+
name: { type: 'string' as const },
|
|
26
|
+
},
|
|
27
|
+
required: ['id'],
|
|
28
|
+
};
|
|
29
|
+
const properties: TablePropertyDefinition[] = [
|
|
30
|
+
{ name: 'id', format: Format.TypeFormat.String },
|
|
31
|
+
{ name: 'name', format: Format.TypeFormat.String, title: 'Name' },
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
expect(() => {
|
|
35
|
+
const { type } = getBaseSchema({ jsonSchema });
|
|
36
|
+
const { projection, object } = makeDynamicTable({ registry, type, properties });
|
|
37
|
+
expect(projection).toBeDefined();
|
|
38
|
+
expect(object).toBeDefined();
|
|
39
|
+
expect(projection.getFields().length).toBeGreaterThan(0);
|
|
40
|
+
}).not.toThrow();
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Builds the Type entity from property definitions, then makes the table.
|
|
45
|
+
* Confirms makeDynamicTable + setProperties (title) works for the property-definitions path.
|
|
46
|
+
*/
|
|
47
|
+
test('makeDynamicTable from getBaseSchema(typename, properties) with properties with title does not throw', () => {
|
|
48
|
+
const registry = Registry.make();
|
|
49
|
+
const typename = 'com.example.type.dynamicTableTest';
|
|
50
|
+
const properties: TablePropertyDefinition[] = [
|
|
51
|
+
{ name: 'id', format: Format.TypeFormat.String },
|
|
52
|
+
{ name: 'name', format: Format.TypeFormat.String, title: 'Name' },
|
|
53
|
+
];
|
|
54
|
+
|
|
55
|
+
expect(() => {
|
|
56
|
+
const { type } = getBaseSchema({ typename, properties });
|
|
57
|
+
const { projection, object } = makeDynamicTable({ registry, type, properties });
|
|
58
|
+
expect(projection).toBeDefined();
|
|
59
|
+
expect(object).toBeDefined();
|
|
60
|
+
expect(projection.getFields().length).toBeGreaterThan(0);
|
|
61
|
+
}).not.toThrow();
|
|
62
|
+
});
|
|
63
|
+
});
|