@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.
@@ -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
  },
@@ -0,0 +1,5 @@
1
+ // The domain palette owns branding. Franchise selection must not change it.
2
+ export const resolveDomainThemeColors = (baseThemeColors = {}, mainCompany = {}) => ({
3
+ ...(mainCompany?.theme?.colors || {}),
4
+ ...(baseThemeColors || {}),
5
+ });
@@ -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 atual';
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('Configuração do PDV')).toBeVisible({
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 source = fs.readFileSync(
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',