@controleonline/ui-default 1.0.276 → 1.0.278

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 (37) hide show
  1. package/docs/compact-order-history-1047.md +25 -0
  2. package/package.json +1 -1
  3. package/src/react/components/filters/CompactFilterSelector.js +194 -185
  4. package/src/react/components/filters/DefaultColumnFilter.js +8 -6
  5. package/src/react/components/filters/DefaultCompactFilterPicker.js +35 -0
  6. package/src/react/components/table/DefaultColumnMenu.js +36 -2
  7. package/src/react/components/table/DefaultCompactDialog.js +36 -0
  8. package/src/react/components/table/DefaultDebug.js +199 -197
  9. package/src/react/components/table/DefaultFiltersModal.js +44 -12
  10. package/src/react/components/table/DefaultTable.js +29 -29
  11. package/src/react/components/table/DefaultTableCards.js +18 -7
  12. package/src/react/components/table/DefaultTableCompact.helpers.js +26 -0
  13. package/src/react/components/table/DefaultTableCompact.styles.js +28 -0
  14. package/src/react/components/table/DefaultTableCompactToolbar.js +112 -0
  15. package/src/react/components/table/DefaultTableInput.js +30 -11
  16. package/src/react/components/table/DefaultTablePaginationBar.js +38 -0
  17. package/src/react/components/table/DefaultTableRows.js +17 -9
  18. package/src/react/components/table/DefaultTableToolbar.js +7 -0
  19. package/src/react/components/table/DefaultTableView.js +5 -2
  20. package/src/react/components/table/useDefaultTableCreateForm.js +29 -0
  21. package/src/react/components/table/useDefaultTablePagination.js +15 -1
  22. package/src/react/components/table/useDefaultTableRowInteraction.js +19 -0
  23. package/src/react/components/table/useDefaultTableStoreSync.js +30 -21
  24. package/src/react/components/table/useDefaultTableTheme.js +44 -41
  25. package/src/tests/react/components/table/DefaultTable.group1.test.js +441 -0
  26. package/src/tests/react/components/table/DefaultTable.group2.test.js +453 -0
  27. package/src/tests/react/components/table/DefaultTable.group3.test.js +289 -0
  28. package/src/tests/react/components/table/DefaultTable.test.js +1 -1381
  29. package/src/tests/react/components/table/DefaultTableToolbar.waiter.test.js +1 -0
  30. package/src/tests/react/components/table/compactDialogs.test.js +53 -0
  31. package/src/tests/react/components/table/compactFilters.test.js +47 -0
  32. package/src/tests/react/components/table/compactPagination.test.js +66 -0
  33. package/src/tests/react/components/table/compactTheme.test.js +34 -0
  34. package/src/tests/react/components/table/compactToolbar.test.js +41 -0
  35. package/src/tests/react/components/table/defaultTableStoreHarness.cjs +35 -0
  36. package/src/tests/react/components/table/defaultTableTestSetup.cjs +207 -0
  37. package/src/tests/react/components/table/useDefaultTableStoreSync.test.js +76 -3
@@ -0,0 +1,289 @@
1
+ const {registerDefaultTableTests, React, renderer, mockState, DefaultTable, mergeSortedDataWithLiveItems, resolveColumnListLoadParams, shouldTriggerEndReachedFromScroll, DEFAULT_TABLE_PREFERENCES_STORAGE_KEY, reactNavigation, getAllStores, STORE_ACTION_META_KEY, flattenStyle} = require('./defaultTableTestSetup.cjs');
2
+ registerDefaultTableTests(() => {
3
+ it('protects custom card openRow while a card field is editing', () => {
4
+ const onRowPress = jest.fn();
5
+ let tree;
6
+
7
+ renderer.act(() => {
8
+ tree = renderer.create(
9
+ React.createElement(DefaultTable, {
10
+ columns: [{key: 'name', label: 'Nome', editable: true}],
11
+ data: [{id: 1, name: 'Cliente'}],
12
+ onRowPress,
13
+ renderCard: ({openRow, renderField}) => React.createElement(
14
+ 'CustomCard',
15
+ {openRow},
16
+ renderField('name'),
17
+ ),
18
+ showColumnFiltersButton: false,
19
+ showRowActions: false,
20
+ }),
21
+ );
22
+ });
23
+
24
+ const latestInput = () => mockState.capturedDefaultInputProps[mockState.capturedDefaultInputProps.length - 1];
25
+
26
+ renderer.act(() => {
27
+ latestInput().onStartEditing();
28
+ });
29
+ renderer.act(() => {
30
+ tree.root.findByType('CustomCard').props.openRow();
31
+ });
32
+ expect(onRowPress).not.toHaveBeenCalled();
33
+
34
+ renderer.act(() => {
35
+ latestInput().onCancelEditing();
36
+ });
37
+ renderer.act(() => {
38
+ tree.root.findByType('CustomCard').props.openRow();
39
+ });
40
+ expect(onRowPress).toHaveBeenCalledTimes(1);
41
+ });
42
+ it('protects both custom row action navigation callbacks during inline editing', () => {
43
+ const onRowPress = jest.fn();
44
+ mockState.windowDimensions = {width: 1024, height: 800};
45
+ let tree;
46
+ renderer.act(() => {tree = renderer.create(React.createElement(DefaultTable, {
47
+ columns: [{key: 'name', label: 'Nome', editable: true}],
48
+ data: [{id: 1, name: 'Cliente'}], onRowPress,
49
+ rowActionsComponent: props => React.createElement('CustomRowActions', props),
50
+ showColumnFiltersButton: false,
51
+ }));});
52
+ const input = () => mockState.capturedDefaultInputProps.at(-1);
53
+ renderer.act(() => {input().onStartEditing();});
54
+ renderer.act(() => {
55
+ const props = tree.root.findByType('CustomRowActions').props;
56
+ props.openRow(); props.helpers.openRow();
57
+ });
58
+ expect(onRowPress).not.toHaveBeenCalled();
59
+ renderer.act(() => {input().onCancelEditing();});
60
+ renderer.act(() => {
61
+ const props = tree.root.findByType('CustomRowActions').props;
62
+ props.openRow(); props.helpers.openRow();
63
+ });
64
+ expect(onRowPress).toHaveBeenCalledTimes(2);
65
+ });
66
+ it('renders a custom footer component when provided', () => {
67
+ let tree;
68
+ mockState.stores.orders = {
69
+ actions: {},
70
+ getters: {
71
+ totalItems: 7,
72
+ },
73
+ };
74
+
75
+ const FooterComponent = props =>
76
+ React.createElement('CustomFooter', {
77
+ resolvedTotalItemsText: props.resolvedTotalItemsText,
78
+ });
79
+
80
+ mockState.windowDimensions = {width: 1024, height: 800};
81
+
82
+ renderer.act(() => {
83
+ tree = renderer.create(
84
+ React.createElement(DefaultTable, {
85
+ columns: [{key: 'name', label: 'Nome'}],
86
+ data: [{id: 1, name: 'Pedido 1'}],
87
+ footerComponent: FooterComponent,
88
+ showColumnFiltersButton: false,
89
+ storeName: 'orders',
90
+ }),
91
+ );
92
+ });
93
+
94
+ const footer = tree.root.findByType('CustomFooter');
95
+
96
+ expect(footer.props.resolvedTotalItemsText).toBe('7 registros');
97
+ });
98
+ it('keeps infinite scroll loading transparent over existing rows', () => {
99
+ let tree;
100
+ const getItems = jest.fn(() => Promise.resolve({member: []}));
101
+ mockState.windowDimensions = {width: 1024, height: 800};
102
+ mockState.stores.invoices = {
103
+ actions: {
104
+ getItems,
105
+ },
106
+ getters: {
107
+ columns: [{key: 'status', label: 'Situação'}],
108
+ items: [{id: 332, status: 'Pago'}],
109
+ totalItems: 1394,
110
+ },
111
+ };
112
+
113
+ renderer.act(() => {
114
+ tree = renderer.create(
115
+ React.createElement(DefaultTable, {
116
+ showColumnFiltersButton: false,
117
+ showRowActions: false,
118
+ storeName: 'invoices',
119
+ }),
120
+ );
121
+ });
122
+
123
+ expect(tree.root.findAllByType('StateStore')).toHaveLength(0);
124
+ const flatList = tree.root.findByType('FlatList');
125
+ expect(flatList.props.onEndReachedThreshold).toBeGreaterThanOrEqual(0.75);
126
+ expect(tree.root.findByType('ScrollView').props.contentContainerStyle).toEqual(
127
+ expect.objectContaining({minWidth: '100%'}),
128
+ );
129
+
130
+ renderer.act(() => {
131
+ flatList.props.onScroll({
132
+ nativeEvent: {
133
+ contentOffset: {y: 650},
134
+ contentSize: {height: 1200},
135
+ layoutMeasurement: {height: 400},
136
+ },
137
+ });
138
+ });
139
+
140
+ expect(getItems).toHaveBeenCalledWith(expect.objectContaining({append: true}));
141
+ });
142
+ it('uses the configured summary and labels before the store summary', () => {
143
+ let tree;
144
+ mockState.windowDimensions = {width: 1024, height: 800};
145
+ mockState.stores.invoice = {
146
+ actions: {},
147
+ getters: {
148
+ summary: {
149
+ financial: {
150
+ paidAmount: 0,
151
+ },
152
+ },
153
+ totalItems: 1,
154
+ },
155
+ };
156
+
157
+ renderer.act(() => {
158
+ tree = renderer.create(
159
+ React.createElement(DefaultTable, {
160
+ columns: [{key: 'status', label: 'Situação'}],
161
+ data: [{id: 332, status: 'Pago'}],
162
+ showColumnFiltersButton: false,
163
+ showRowActions: false,
164
+ storeName: 'invoice',
165
+ summary: {
166
+ financial: {
167
+ paidAmount: 80.25,
168
+ },
169
+ },
170
+ summaryLabels: {
171
+ 'financial.paidAmount': 'Valor pago',
172
+ },
173
+ }),
174
+ );
175
+ });
176
+
177
+ const textValues = tree.root.findAllByType('Text').map(node => node.props.children);
178
+ expect(textValues).toContain('Valor pago');
179
+ expect(textValues).toContain('R$ 80,25');
180
+ });
181
+ it('opens a debug query modal when the store exposes debug.query', () => {
182
+ mockState.windowDimensions = {width: 1024, height: 800};
183
+ mockState.stores.orders = {
184
+ actions: {},
185
+ getters: {
186
+ columns: [{key: 'id', label: 'ID'}],
187
+ debug: {
188
+ interpolatedQuery: "SELECT * FROM orders WHERE provider_id = '2'",
189
+ query: 'SELECT * FROM orders WHERE provider_id = 2',
190
+ },
191
+ filters: {
192
+ provider: '/people/2',
193
+ },
194
+ items: [],
195
+ },
196
+ };
197
+
198
+ let tree;
199
+
200
+ renderer.act(() => {
201
+ tree = renderer.create(
202
+ React.createElement(DefaultTable, {
203
+ requestParams: {itemsPerPage: 50},
204
+ storeName: 'orders',
205
+ }),
206
+ );
207
+ });
208
+
209
+ const debugButton = tree.root
210
+ .findAllByType('TouchableOpacity')
211
+ .find(node => node.props.accessibilityLabel === 'Debug query');
212
+
213
+ expect(debugButton).toBeTruthy();
214
+
215
+ renderer.act(() => debugButton.props.onPress());
216
+
217
+ const textValues = tree.root.findAllByType('Text').map(node => node.props.children);
218
+ expect(textValues).toContain('Debug query');
219
+ expect(textValues).toContain('SELECT * FROM orders WHERE provider_id = 2');
220
+ expect(textValues).toContain('Query preenchida');
221
+ expect(textValues).toContain("SELECT * FROM orders WHERE provider_id = '2'");
222
+ expect(textValues.some(value => String(value).includes('"provider": "/people/2"'))).toBe(true);
223
+ });
224
+ it('uses store actions when no explicit table actions are passed', async () => {
225
+ const save = jest.fn(() => Promise.resolve({
226
+ id: 1,
227
+ jobTitle: '/categories/2',
228
+ }));
229
+
230
+ mockState.stores.employee_profiles = {
231
+ actions: {
232
+ save,
233
+ },
234
+ getters: {
235
+ columns: [],
236
+ },
237
+ };
238
+
239
+ await renderer.act(async () => {
240
+ renderer.create(
241
+ React.createElement(DefaultTable, {
242
+ columns: [
243
+ {
244
+ key: 'jobTitle',
245
+ label: 'Cargo',
246
+ editable: true,
247
+ list: 'categories/getItems',
248
+ formatList: item => ({
249
+ value: item.id,
250
+ label: item.name,
251
+ }),
252
+ saveFormat: value => `/categories/${parseInt(value.value || value, 10)}`,
253
+ },
254
+ ],
255
+ data: [{
256
+ id: 1,
257
+ jobTitle: '/categories/1',
258
+ }],
259
+ showColumnFiltersButton: false,
260
+ showRowActions: false,
261
+ storeName: 'employee_profiles',
262
+ }),
263
+ );
264
+ });
265
+
266
+ expect(mockState.capturedDefaultInputProps.length).toBeGreaterThan(0);
267
+
268
+ await renderer.act(async () => {
269
+ await mockState.capturedDefaultInputProps[0].onSave({
270
+ value: '2',
271
+ label: 'Departamento',
272
+ object: {id: 2, name: 'Departamento'},
273
+ });
274
+ });
275
+
276
+ expect(save).toHaveBeenCalledWith({
277
+ id: '1',
278
+ jobTitle: '/categories/2',
279
+ [STORE_ACTION_META_KEY]: {
280
+ savedItemPatch: {
281
+ jobTitle: {
282
+ id: 2,
283
+ name: 'Departamento',
284
+ },
285
+ },
286
+ },
287
+ });
288
+ });
289
+ });