@controleonline/ui-common 1.2.90 → 1.2.92
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/.release/rc-manifest.json +16 -0
- package/docs/compact-order-history-1047.md +25 -0
- package/package.json +4 -3
- package/src/react/components/DefaultProvider.native.configuration.js +275 -0
- package/src/react/components/DefaultProvider.native.js +49 -537
- package/src/react/components/DefaultProvider.native.lifecycle.js +323 -0
- package/src/react/components/DefaultProvider.web.configuration.js +327 -0
- package/src/react/components/DefaultProvider.web.js +23 -603
- package/src/react/components/DefaultProvider.web.lifecycle.js +336 -0
- package/src/react/components/RuntimeFooterMarqueeText.js +5 -0
- package/src/react/components/resolveDomainThemeColors.js +5 -0
- package/src/react/pages/Connections.js +1 -1
- package/src/react/utils/runtimeZoom.js +6 -0
- package/src/tests/browser/manager/device-detail-alias-save.spec.js +1 -1
- package/src/tests/browser/manager/device-detail-pdv-current-company.spec.js +1 -1
- package/src/tests/react/components/DefaultProviderAuthority.test.js +4 -1
- package/src/tests/react/components/RuntimeFooterMarqueeText.test.js +22 -0
- package/src/tests/react/components/providerEffects.fingerprint.json +47 -0
- package/src/tests/react/components/providerEffects.test.js +24 -0
- package/src/tests/react/utils/runtimeZoom.test.js +6 -0
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
import {useEffect} from 'react';
|
|
2
|
+
|
|
3
|
+
// Extracted bootstrap effects retain their dependency arrays and invocation order.
|
|
4
|
+
|
|
5
|
+
export function useWebTranslationRefresh({setTranslateVersion}) {
|
|
6
|
+
useEffect(() => {
|
|
7
|
+
global.refreshTranslationsUI = () => {
|
|
8
|
+
setTranslateVersion(version => version + 1);
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
return () => {
|
|
12
|
+
if (global.refreshTranslationsUI) {
|
|
13
|
+
delete global.refreshTranslationsUI;
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
}, []);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function useWebTranslationReset({isLogged, isPublicRouteActive, setTranslateReady, setActiveTranslateBootstrapKey, translateBootstrapKeyRef, translateActions}) {
|
|
20
|
+
useEffect(() => {
|
|
21
|
+
if (isLogged && !isPublicRouteActive) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
setTranslateReady(true);
|
|
26
|
+
setActiveTranslateBootstrapKey('');
|
|
27
|
+
translateBootstrapKeyRef.current = '';
|
|
28
|
+
translateActions.setMessages({});
|
|
29
|
+
translateActions.setPendingMessages?.({});
|
|
30
|
+
|
|
31
|
+
if (global.t) {
|
|
32
|
+
delete global.t;
|
|
33
|
+
}
|
|
34
|
+
}, [isLogged, isPublicRouteActive, translateActions]);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function useWebDeviceConfigReset({deviceConfigPeopleIri, lastDeviceConfigPeopleIriRef, setDeviceConfigFetched, setDeviceRuntimeConfigSynced, deviceConfigsActions}) {
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
if (
|
|
40
|
+
!deviceConfigPeopleIri ||
|
|
41
|
+
lastDeviceConfigPeopleIriRef.current === deviceConfigPeopleIri
|
|
42
|
+
) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
lastDeviceConfigPeopleIriRef.current = deviceConfigPeopleIri;
|
|
47
|
+
setDeviceConfigFetched(false);
|
|
48
|
+
setDeviceRuntimeConfigSynced(false);
|
|
49
|
+
deviceConfigsActions.setItem({});
|
|
50
|
+
}, [deviceConfigPeopleIri, deviceConfigsActions]);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function useWebRuntimeIp({isLogged, api, getRuntimeIpFromResponse, setWebRuntimeIp, user}) {
|
|
54
|
+
useEffect(() => {
|
|
55
|
+
if (!isLogged) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
let cancelled = false;
|
|
60
|
+
|
|
61
|
+
api
|
|
62
|
+
.fetch('runtime/ip', {
|
|
63
|
+
method: 'GET',
|
|
64
|
+
})
|
|
65
|
+
.then(response => {
|
|
66
|
+
const nextRuntimeIp = getRuntimeIpFromResponse(response);
|
|
67
|
+
if (!nextRuntimeIp || cancelled) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
setWebRuntimeIp(currentIp =>
|
|
72
|
+
currentIp === nextRuntimeIp ? currentIp : nextRuntimeIp,
|
|
73
|
+
);
|
|
74
|
+
})
|
|
75
|
+
.catch(() => {});
|
|
76
|
+
|
|
77
|
+
return () => {
|
|
78
|
+
cancelled = true;
|
|
79
|
+
};
|
|
80
|
+
}, [isLogged, user?.id]);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function useWebWebDeviceIdentity({isLogged, isShopClientApp, buildWebDevice, lastWebDeviceSyncRef, setDevice, deviceActions, packageVersion, user, webRuntimeIp}) {
|
|
84
|
+
useEffect(() => {
|
|
85
|
+
if (!isLogged && !isShopClientApp) {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const nextDevice = buildWebDevice();
|
|
90
|
+
if (!nextDevice) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const signature = JSON.stringify({
|
|
95
|
+
id: nextDevice.id,
|
|
96
|
+
appVersion: nextDevice.appVersion,
|
|
97
|
+
appName: nextDevice.appName,
|
|
98
|
+
type: nextDevice.type,
|
|
99
|
+
metadata: nextDevice.metadata || {},
|
|
100
|
+
externalIp: nextDevice.externalIp || null,
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
if (lastWebDeviceSyncRef.current === signature) {
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
lastWebDeviceSyncRef.current = signature;
|
|
108
|
+
setDevice(nextDevice);
|
|
109
|
+
localStorage.setItem('device', JSON.stringify(nextDevice));
|
|
110
|
+
deviceActions.setItem(nextDevice);
|
|
111
|
+
localStorage.removeItem('master-device');
|
|
112
|
+
}, [deviceActions, isLogged, isShopClientApp, packageVersion, user?.id, webRuntimeIp]);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export function useWebMainCompany({isShopClientApp, device, peopleActions}) {
|
|
116
|
+
useEffect(() => {
|
|
117
|
+
if (isShopClientApp || device?.id) {
|
|
118
|
+
peopleActions.mainCompany().catch(() => {});
|
|
119
|
+
}
|
|
120
|
+
}, [device?.id, isShopClientApp, peopleActions]);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export function useWebDeviceRegistration({isLogged, device, currentCompany, canAdministerCompany, mainCompany, user, deviceActions, buildDeviceRegistrationPayload, app_type, hasDeviceRecordChanges, runtimeDeviceType, setDevice}) {
|
|
124
|
+
useEffect(() => {
|
|
125
|
+
if (!isLogged || !device?.id) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Device registration changes tenant context and is not valid without an
|
|
130
|
+
// active company or administrative authority for that company.
|
|
131
|
+
if (
|
|
132
|
+
!currentCompany?.id ||
|
|
133
|
+
!canAdministerCompany({company: currentCompany, mainCompany, user})
|
|
134
|
+
) {
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
let cancelled = false;
|
|
139
|
+
|
|
140
|
+
const syncDeviceRegistration = async () => {
|
|
141
|
+
const items = await deviceActions.getItems({
|
|
142
|
+
device: device.id,
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
if (cancelled) {
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const existingDevice =
|
|
150
|
+
Array.isArray(items) && items.length > 0 ? items[0] : null;
|
|
151
|
+
const nextDevice = buildDeviceRegistrationPayload({
|
|
152
|
+
deviceInfo: device,
|
|
153
|
+
appType: app_type,
|
|
154
|
+
existingDevice,
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
if (!hasDeviceRecordChanges({existingDevice, nextDevice})) {
|
|
158
|
+
const nextLocalDevice = {
|
|
159
|
+
...device,
|
|
160
|
+
entityId: existingDevice?.id || device?.entityId || null,
|
|
161
|
+
entityIri:
|
|
162
|
+
existingDevice?.['@id'] ||
|
|
163
|
+
device?.entityIri ||
|
|
164
|
+
(existingDevice?.id ? `/devices/${existingDevice.id}` : null),
|
|
165
|
+
alias: existingDevice?.alias || nextDevice.alias,
|
|
166
|
+
type: device?.type || runtimeDeviceType,
|
|
167
|
+
metadata: existingDevice?.metadata || nextDevice.metadata,
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
if (JSON.stringify(nextLocalDevice) !== JSON.stringify(device)) {
|
|
171
|
+
setDevice(nextLocalDevice);
|
|
172
|
+
localStorage.setItem('device', JSON.stringify(nextLocalDevice));
|
|
173
|
+
deviceActions.setItem(nextLocalDevice);
|
|
174
|
+
}
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const savedDevice = await deviceActions.save(nextDevice);
|
|
179
|
+
if (cancelled || !savedDevice) {
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const nextLocalDevice = {
|
|
184
|
+
...device,
|
|
185
|
+
entityId: savedDevice?.id || device?.entityId || null,
|
|
186
|
+
entityIri:
|
|
187
|
+
savedDevice?.['@id'] ||
|
|
188
|
+
device?.entityIri ||
|
|
189
|
+
(savedDevice?.id ? `/devices/${savedDevice.id}` : null),
|
|
190
|
+
alias: savedDevice.alias || nextDevice.alias,
|
|
191
|
+
type: device?.type || runtimeDeviceType,
|
|
192
|
+
metadata: savedDevice.metadata || nextDevice.metadata,
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
if (JSON.stringify(nextLocalDevice) !== JSON.stringify(device)) {
|
|
196
|
+
setDevice(nextLocalDevice);
|
|
197
|
+
localStorage.setItem('device', JSON.stringify(nextLocalDevice));
|
|
198
|
+
deviceActions.setItem(nextLocalDevice);
|
|
199
|
+
}
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
syncDeviceRegistration().catch(() => {});
|
|
203
|
+
|
|
204
|
+
return () => {
|
|
205
|
+
cancelled = true;
|
|
206
|
+
};
|
|
207
|
+
}, [
|
|
208
|
+
device?.appVersion,
|
|
209
|
+
device?.batteryLevel,
|
|
210
|
+
device?.buildNumber,
|
|
211
|
+
device?.deviceType,
|
|
212
|
+
device?.externalIp,
|
|
213
|
+
device?.id,
|
|
214
|
+
device?.manufacturer,
|
|
215
|
+
device?.model,
|
|
216
|
+
device?.systemVersion,
|
|
217
|
+
isLogged,
|
|
218
|
+
currentCompany,
|
|
219
|
+
mainCompany,
|
|
220
|
+
runtimeDeviceType,
|
|
221
|
+
user,
|
|
222
|
+
]);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
export function useWebPrinters({isShopClientApp, isLogged, currentCompany, printerActions}) {
|
|
226
|
+
useEffect(() => {
|
|
227
|
+
if (isShopClientApp || !isLogged || !currentCompany?.id) {
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
printerActions
|
|
232
|
+
.ensureCompanyPrintersLoaded({people: currentCompany.id})
|
|
233
|
+
.catch(() => {});
|
|
234
|
+
}, [currentCompany?.id, isLogged, isShopClientApp, printerActions]);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
export function useWebPaymentTypes({isShopClientApp, companyConfigs, currentCompany, device_config, walletPaymentTypeRequestRef, walletPaymentTypeLoadedKeyRef, paymentTypeActions, mainConfigsDiscovered, resolveDevicePaymentTypeIds, api, selectPosWalletPaymentTypes, getPaymentGateway}) {
|
|
238
|
+
useEffect(() => {
|
|
239
|
+
const paymentConfigSource = isShopClientApp
|
|
240
|
+
? Object.keys(companyConfigs || {}).length > 0
|
|
241
|
+
? companyConfigs
|
|
242
|
+
: currentCompany?.configs
|
|
243
|
+
: device_config?.configs;
|
|
244
|
+
|
|
245
|
+
if (!currentCompany?.id || !paymentConfigSource) {
|
|
246
|
+
walletPaymentTypeRequestRef.current = {key: '', promise: null};
|
|
247
|
+
walletPaymentTypeLoadedKeyRef.current = '';
|
|
248
|
+
paymentTypeActions.setItems([]);
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
if (!isShopClientApp && !mainConfigsDiscovered) {
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
const paymentTypeSignature = resolveDevicePaymentTypeIds(paymentConfigSource)
|
|
257
|
+
.sort()
|
|
258
|
+
.join(',');
|
|
259
|
+
const requestKey = `${currentCompany.id}:${paymentTypeSignature}`;
|
|
260
|
+
|
|
261
|
+
if (walletPaymentTypeLoadedKeyRef.current === requestKey) {
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
const existingRequestPromise =
|
|
266
|
+
walletPaymentTypeRequestRef.current.key === requestKey &&
|
|
267
|
+
walletPaymentTypeRequestRef.current.promise
|
|
268
|
+
? walletPaymentTypeRequestRef.current.promise
|
|
269
|
+
: null;
|
|
270
|
+
|
|
271
|
+
let isMounted = true;
|
|
272
|
+
|
|
273
|
+
const requestPromise =
|
|
274
|
+
existingRequestPromise ||
|
|
275
|
+
api.fetch('wallet_payment_types', {
|
|
276
|
+
params: {
|
|
277
|
+
people: `/people/${currentCompany.id}`,
|
|
278
|
+
},
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
if (!existingRequestPromise) {
|
|
282
|
+
walletPaymentTypeRequestRef.current = {
|
|
283
|
+
key: requestKey,
|
|
284
|
+
promise: requestPromise,
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
requestPromise
|
|
289
|
+
.then(response => {
|
|
290
|
+
if (!isMounted) {
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
const walletPaymentTypes = Array.isArray(response?.member)
|
|
295
|
+
? response.member
|
|
296
|
+
: Array.isArray(response?.['hydra:member'])
|
|
297
|
+
? response['hydra:member']
|
|
298
|
+
: Array.isArray(response)
|
|
299
|
+
? response
|
|
300
|
+
: [];
|
|
301
|
+
paymentTypeActions.setItems(
|
|
302
|
+
selectPosWalletPaymentTypes({
|
|
303
|
+
walletPaymentTypes,
|
|
304
|
+
deviceConfigs: paymentConfigSource,
|
|
305
|
+
companyConfigs,
|
|
306
|
+
gateway: getPaymentGateway(device_config || paymentConfigSource),
|
|
307
|
+
}),
|
|
308
|
+
);
|
|
309
|
+
walletPaymentTypeLoadedKeyRef.current = requestKey;
|
|
310
|
+
})
|
|
311
|
+
.catch(() => {
|
|
312
|
+
if (isMounted) {
|
|
313
|
+
paymentTypeActions.setItems([]);
|
|
314
|
+
}
|
|
315
|
+
})
|
|
316
|
+
.finally(() => {
|
|
317
|
+
if (
|
|
318
|
+
walletPaymentTypeRequestRef.current.key === requestKey &&
|
|
319
|
+
walletPaymentTypeRequestRef.current.promise === requestPromise
|
|
320
|
+
) {
|
|
321
|
+
walletPaymentTypeRequestRef.current = {key: '', promise: null};
|
|
322
|
+
}
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
return () => {
|
|
326
|
+
isMounted = false;
|
|
327
|
+
};
|
|
328
|
+
}, [
|
|
329
|
+
companyConfigs,
|
|
330
|
+
currentCompany?.configs,
|
|
331
|
+
currentCompany?.id,
|
|
332
|
+
device_config?.configs,
|
|
333
|
+
isShopClientApp,
|
|
334
|
+
paymentTypeActions,
|
|
335
|
+
]);
|
|
336
|
+
}
|
|
@@ -105,6 +105,10 @@ const RuntimeFooterMarqueeText = props => {
|
|
|
105
105
|
color: color,
|
|
106
106
|
flexShrink: 0,
|
|
107
107
|
flexGrow: 0,
|
|
108
|
+
// primaryText carries `flex: 1` (flexBasis 0 on native), which collapsed
|
|
109
|
+
// the Text to width 0 inside the row on Android. Force intrinsic sizing.
|
|
110
|
+
flexBasis: 'auto',
|
|
111
|
+
minWidth: 0,
|
|
108
112
|
minHeight: 14,
|
|
109
113
|
},
|
|
110
114
|
];
|
|
@@ -164,6 +168,7 @@ const RuntimeFooterMarqueeText = props => {
|
|
|
164
168
|
alignItems: 'center',
|
|
165
169
|
opacity: 1,
|
|
166
170
|
transform: [{translateX: translateX}],
|
|
171
|
+
justifyContent: shouldMarquee ? 'flex-start' : 'center',
|
|
167
172
|
alignSelf: shouldMarquee ? 'flex-start' : 'stretch',
|
|
168
173
|
},
|
|
169
174
|
},
|
|
@@ -213,7 +213,7 @@ export default function Connections() {
|
|
|
213
213
|
searchPlaceholder={
|
|
214
214
|
tt('connections_label', 'search') || 'Buscar conexao, telefone ou status'
|
|
215
215
|
}
|
|
216
|
-
searchKey="search
|
|
216
|
+
searchKey="search"
|
|
217
217
|
totalItemsLabel="connections"
|
|
218
218
|
visibleColumnsPreferenceKey="connections"
|
|
219
219
|
accentColor={brandColors.primary}
|
|
@@ -37,10 +37,16 @@ export const buildRuntimeZoomStyle = (
|
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
const inverseScale = 1 / scale;
|
|
40
|
+
// app-community#1051: the container also carries `flex: 1` (flexBasis 0),
|
|
41
|
+
// which overrides the compensated height. Disable flex sizing so the
|
|
42
|
+
// compensated size survives and the scaled content fills the viewport.
|
|
40
43
|
const nativeBase = {
|
|
41
44
|
transform: [{scale}],
|
|
42
45
|
transformOrigin: 'top left',
|
|
43
46
|
alignSelf: 'flex-start',
|
|
47
|
+
flexGrow: 0,
|
|
48
|
+
flexShrink: 0,
|
|
49
|
+
flexBasis: 'auto',
|
|
44
50
|
};
|
|
45
51
|
|
|
46
52
|
const viewportWidth = Number(viewport?.width);
|
|
@@ -17,7 +17,7 @@ const { API_ORIGIN } = require('../../../../../../../src/tests/browser/apiOrigin
|
|
|
17
17
|
const APP_VERSION = packageJson?.version || '1.0.0';
|
|
18
18
|
const CURRENT_DEVICE_ID = 'web-7';
|
|
19
19
|
const DEVICE_ENTITY_ID = 396;
|
|
20
|
-
const INITIAL_ALIAS = 'Caixa
|
|
20
|
+
const INITIAL_ALIAS = 'Caixa Santa Redonda';
|
|
21
21
|
const NEXT_ALIAS = 'Caixa Renomeado #382';
|
|
22
22
|
|
|
23
23
|
const CORS_HEADERS = {
|
|
@@ -250,7 +250,7 @@ test.describe('device-detail PDV currentCompany (#704)', () => {
|
|
|
250
250
|
|
|
251
251
|
await page.getByTestId(`device-config-${PDV_CONFIG_ID}`).click();
|
|
252
252
|
await expect(page).toHaveURL(/device-detail/, {timeout: 15000});
|
|
253
|
-
await expect(page.getByText('
|
|
253
|
+
await expect(page.getByText('Detalhes do Device', {exact: true})).toBeVisible({
|
|
254
254
|
timeout: 15000,
|
|
255
255
|
});
|
|
256
256
|
await writeEvidence(
|
|
@@ -11,11 +11,14 @@ describe('DefaultProvider company authority guard', () => {
|
|
|
11
11
|
it.each(providerFiles)(
|
|
12
12
|
'uses the shared authority helper in %s',
|
|
13
13
|
providerFile => {
|
|
14
|
-
const
|
|
14
|
+
const providerSource = fs.readFileSync(
|
|
15
15
|
path.resolve(__dirname, '../../../react/components', providerFile),
|
|
16
16
|
'utf8',
|
|
17
17
|
);
|
|
18
18
|
|
|
19
|
+
const root = path.resolve(__dirname, '../../../react/components');
|
|
20
|
+
const platform = providerFile.includes('.web.') ? 'web' : 'native';
|
|
21
|
+
const source = providerSource + ['lifecycle', 'configuration'].map(group => fs.readFileSync(path.join(root, `DefaultProvider.${platform}.${group}.js`), 'utf8')).join('\n');
|
|
19
22
|
expect(source).not.toContain('isTenantAdministrativeAuthority');
|
|
20
23
|
expect(source).toMatch(
|
|
21
24
|
/import\s*\{\s*canAdministerCompany\s*\}\s*from\s*['"]@controleonline\/ui-common\/src\/react\/utils\/companyAuthority['"]/,
|
|
@@ -169,3 +169,25 @@ test('long text enables marquee duplicate and starts loop animation', async () =
|
|
|
169
169
|
assert.ok(lastLoopConfig, 'Animated.loop should start when overflowing');
|
|
170
170
|
assert.ok(animationStarts >= 1);
|
|
171
171
|
});
|
|
172
|
+
|
|
173
|
+
test('native text keeps intrinsic width even when style carries flex: 1 (android #77)', () => {
|
|
174
|
+
const RuntimeFooterMarqueeText = loadComponent();
|
|
175
|
+
const renderer = require('react-test-renderer');
|
|
176
|
+
|
|
177
|
+
let tree;
|
|
178
|
+
renderer.act(() => {
|
|
179
|
+
tree = renderer.create(
|
|
180
|
+
React.createElement(RuntimeFooterMarqueeText, {
|
|
181
|
+
text: 'Samsung • DEVICE / v1.10.55',
|
|
182
|
+
color: '#111',
|
|
183
|
+
style: {flex: 1, minWidth: 0, fontSize: 11},
|
|
184
|
+
}),
|
|
185
|
+
);
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
const text = tree.root.findAllByType('Text')[0];
|
|
189
|
+
const flat = Object.assign({}, ...[].concat(text.props.style));
|
|
190
|
+
assert.equal(flat.flexBasis, 'auto');
|
|
191
|
+
assert.equal(flat.flexGrow, 0);
|
|
192
|
+
assert.equal(flat.flexShrink, 0);
|
|
193
|
+
});
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"web": [
|
|
3
|
+
"ea75d6ac3ae9c95e52c766bdb34d53bc105f14c39d99296870fe5ffc22871c9d",
|
|
4
|
+
"91eb2c6aa1cf5924d8741f6baffc1a1a55ee3a4724ccefa8bde421f9c64150bc",
|
|
5
|
+
"d9e3b6b0bda60f7ee7c20f3b764ef1cf6b3c4505b2dd0c14149d738afc4b7250",
|
|
6
|
+
"dc4de55291686857d4e1e9f450bf94dd7711e6d553b7f7c25f12cdcc15699e8d",
|
|
7
|
+
"3aac47f15f506f8a4f4c6c43025ac01df0d0686f53aeb2693cf995481f542300",
|
|
8
|
+
"401f05b86cbf58f51cf0f8daa9daedd9a11405bd88fd92c0c50f4425cb7426c8",
|
|
9
|
+
"6096f06d9b6dffc3402b2b23bdf1a49acb9d8b07c32a406cda0576d23835123d",
|
|
10
|
+
"08c333c63aab840cc566dfd7e1859624001c1e0cf41385b4fbd320a0772f8683",
|
|
11
|
+
"66e252433a95f6c234521d17405723faa27ff255950355d148c8915a6a121e50",
|
|
12
|
+
"9defefb6dd3fe794f7f5165415ad66bbf9364feabe2950f9101ee75b4e920bbd",
|
|
13
|
+
"e7e947e510177219121d1983055a9d3c1bbff5e2be0e1ed88f0ef33b8b04550d",
|
|
14
|
+
"6a48d5207d4e6ab178c856cba730992f4b7033e72328407bbf9687ab43fea31a",
|
|
15
|
+
"b855618a73da5452161007146c7e6dbc7a455377088e5f3b39740a50785717ea",
|
|
16
|
+
"4e436b845f79c9abb9b02ce885712f3d86cbfc58e7ac013bbf12aa4cadf8766b",
|
|
17
|
+
"b4a82937d543b1ec702eb39a4f59c50fb405591a5cf47d57f26ddf3204c00c79",
|
|
18
|
+
"52f1d9c7c0e526b45a517d5ca6d0bad10f6f13f9e28710d07fbe2c6390fd4663",
|
|
19
|
+
"7fd064dfd9939c27fd50ef7e98870027d6a243818b01a7961250c3541c489b37",
|
|
20
|
+
"5d82d7da62a6a2a1ea620b2e20aed981e54a57f7481d0d7b80274836d18c67b1",
|
|
21
|
+
"06a38bfbc8bea082ea8aed3d115eb0be46a66cf4067e15002a93332edcfe3e18",
|
|
22
|
+
"45f67afbb83db2fc03d4db5eb1cb97d0aef89960f7fed857a13104dc0d577996"
|
|
23
|
+
],
|
|
24
|
+
"native": [
|
|
25
|
+
"ea75d6ac3ae9c95e52c766bdb34d53bc105f14c39d99296870fe5ffc22871c9d",
|
|
26
|
+
"91eb2c6aa1cf5924d8741f6baffc1a1a55ee3a4724ccefa8bde421f9c64150bc",
|
|
27
|
+
"ca6d2dbaff4a3ceaf72de6a7309dd1fff040b8c0c8becd7e9ad9c5e951747e33",
|
|
28
|
+
"3568e8c2ad8a62ef8ecd3381ca564567348ac30775f77a8e162d0627e65c3149",
|
|
29
|
+
"251907db50e73d845caad88cebde534715c714c5656c71ba101840d1aa387995",
|
|
30
|
+
"69a271277a710e366340f53a73a0ad69c349c0d57903604895a577502982f968",
|
|
31
|
+
"d9e3b6b0bda60f7ee7c20f3b764ef1cf6b3c4505b2dd0c14149d738afc4b7250",
|
|
32
|
+
"ca2d71f74eee04d29f12f99eb6ad2a027d997e059ca624b050b626c33af048da",
|
|
33
|
+
"00aec313bce033cee0f7ec578b884c057d99082fc5d70bd4c427b71f443ac3be",
|
|
34
|
+
"89b61590c0cd1f85d8a0a91d73c2ed76879207aee74e4e06a5a299cd78569ced",
|
|
35
|
+
"e7225c56b302453cc1dca664733fd612b5537b4f172f325635366449d5f9204b",
|
|
36
|
+
"00726c053f3dd7242abc46334bda5e2d85b3881b41027a0bd6cf92d8017f089f",
|
|
37
|
+
"6a48d5207d4e6ab178c856cba730992f4b7033e72328407bbf9687ab43fea31a",
|
|
38
|
+
"ccb781af89d778267e58ed7d92a076bb9266074fabadaacf3615309565c221cd",
|
|
39
|
+
"4e436b845f79c9abb9b02ce885712f3d86cbfc58e7ac013bbf12aa4cadf8766b",
|
|
40
|
+
"b4a82937d543b1ec702eb39a4f59c50fb405591a5cf47d57f26ddf3204c00c79",
|
|
41
|
+
"52f1d9c7c0e526b45a517d5ca6d0bad10f6f13f9e28710d07fbe2c6390fd4663",
|
|
42
|
+
"17ed12ca2369541649112e7e894eb8e9e7f5af739406ae752e49c41f9d0f954c",
|
|
43
|
+
"5d82d7da62a6a2a1ea620b2e20aed981e54a57f7481d0d7b80274836d18c67b1",
|
|
44
|
+
"2e76f30b34a18f41ab7cc6e78525ac8e88d5dffe1aa76f92be795d4d4800652a",
|
|
45
|
+
"a8b1a30dc99d18b5c0c1361c71a604efc4a546e3af45bb9e33f4d51469bd570a"
|
|
46
|
+
]
|
|
47
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import crypto from 'node:crypto';
|
|
4
|
+
import {parse} from '@babel/parser';
|
|
5
|
+
import traverse from '@babel/traverse';
|
|
6
|
+
import expected from './providerEffects.fingerprint.json';
|
|
7
|
+
|
|
8
|
+
// Protect the unrelated auth/device/bootstrap callbacks while extracting hooks.
|
|
9
|
+
// Fingerprints record the approved runtime callbacks, dependencies and hook order.
|
|
10
|
+
it.each(['web', 'native'])('preserves bootstrap effects in %s', platform => {
|
|
11
|
+
const root = path.resolve(__dirname, '../../../react/components');
|
|
12
|
+
const provider = parse(fs.readFileSync(path.join(root, `DefaultProvider.${platform}.js`), 'utf8'), {sourceType: 'module', plugins: ['jsx']});
|
|
13
|
+
const hooks = new Map();
|
|
14
|
+
for (const group of ['lifecycle', 'configuration']) {
|
|
15
|
+
const code = fs.readFileSync(path.join(root, `DefaultProvider.${platform}.${group}.js`), 'utf8');
|
|
16
|
+
traverse(parse(code, {sourceType: 'module'}), {FunctionDeclaration(p) {
|
|
17
|
+
const effect = p.node.body.body.find(n => n.expression?.callee?.name === 'useEffect');
|
|
18
|
+
if (effect) hooks.set(p.node.id.name, crypto.createHash('sha256').update(code.slice(effect.start, effect.end)).digest('hex'));
|
|
19
|
+
}});
|
|
20
|
+
}
|
|
21
|
+
const actual = [];
|
|
22
|
+
traverse(provider, {CallExpression(p) {if (hooks.has(p.node.callee.name)) actual.push(hooks.get(p.node.callee.name));}});
|
|
23
|
+
expect(actual).toEqual(expected[platform]);
|
|
24
|
+
});
|
|
@@ -31,6 +31,9 @@ test('builds compensated container dimensions for native scaled content', () =>
|
|
|
31
31
|
buildRuntimeZoomStyle(70),
|
|
32
32
|
{
|
|
33
33
|
alignSelf: 'flex-start',
|
|
34
|
+
flexBasis: 'auto',
|
|
35
|
+
flexGrow: 0,
|
|
36
|
+
flexShrink: 0,
|
|
34
37
|
height: '142.85714285714286%',
|
|
35
38
|
transform: [{scale: 0.7}],
|
|
36
39
|
transformOrigin: 'top left',
|
|
@@ -44,6 +47,9 @@ test('uses viewport pixels on native so scale origin stays top-left without dist
|
|
|
44
47
|
buildRuntimeZoomStyle(70, {viewport: {width: 360, height: 800}}),
|
|
45
48
|
{
|
|
46
49
|
alignSelf: 'flex-start',
|
|
50
|
+
flexBasis: 'auto',
|
|
51
|
+
flexGrow: 0,
|
|
52
|
+
flexShrink: 0,
|
|
47
53
|
height: 800 / 0.7,
|
|
48
54
|
transform: [{scale: 0.7}],
|
|
49
55
|
transformOrigin: 'top left',
|