@controleonline/ui-common 1.2.70 → 1.2.71
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/package.json +31 -28
- package/src/api/index.js +237 -37
- package/src/react/components/AddImportModal.js +1 -1
- package/src/react/components/AnimatedModal.js +171 -0
- package/src/react/components/AnimatedModal.styles.js +21 -0
- package/src/react/components/AppTypeSwitcher.js +164 -0
- package/src/react/components/AppTypeSwitcher.styles.js +109 -0
- package/src/react/components/BackgroundRuntimeBridge.js +5 -4
- package/src/react/components/BottomNavigationBar.js +86 -31
- package/src/react/components/BottomNavigationBar.styles.js +118 -110
- package/src/react/components/DefaultProvider.native.js +68 -66
- package/src/react/components/DefaultProvider.web.js +44 -42
- package/src/react/components/DeliveryPushBridge.native.js +2 -2
- package/src/react/components/DeviceAlertSoundService.js +3 -3
- package/src/react/components/KioskModeBridge.js +2 -2
- package/src/react/components/LauncherModeBridge.js +2 -2
- package/src/react/components/ManagerPushBridge.native.js +2 -2
- package/src/react/components/RemoteCheckoutService.js +28 -20
- package/src/react/components/RuntimeBottomNavigationBar.js +146 -119
- package/src/react/components/RuntimeInfoFooter.js +37 -9
- package/src/react/components/StateStore.js +258 -0
- package/src/react/components/WebsocketListener.native.js +11 -11
- package/src/react/config/deviceConfigBootstrap.js +66 -27
- package/src/react/css/orders.js +72 -0
- package/src/react/pages/SettingsPage/PaymentTypesByWalletTab.js +484 -454
- package/src/react/pages/SettingsPage/index.js +1266 -1167
- package/src/react/print/providers/local.js +1 -1
- package/src/react/router/publicRoutes.js +25 -0
- package/src/react/services/Cielo/Checkout.js +39 -0
- package/src/react/services/Cielo/Cielo.js +193 -0
- package/src/react/services/Cielo/Print.js +7 -0
- package/src/react/services/InfinitePay/Checkout.js +33 -0
- package/src/react/services/InfinitePay/InfinitePay.js +24 -0
- package/src/react/{utils → services}/paymentGatewayExecution.js +91 -91
- package/src/react/styles/global.js +115 -0
- package/src/react/utils/fileUrl.js +182 -16
- package/src/react/utils/menuNavigation.js +31 -0
- package/src/react/utils/orderIdentity.js +277 -0
- package/src/react/utils/remotePayment.js +115 -61
- package/src/react/utils/runtimeMenu.js +35 -3
- package/src/react/utils/shopConfig.js +50 -24
- package/src/react/utils/shopFranchises.js +56 -22
- package/src/react/utils/socketRuntimePipeline.js +14 -14
- package/src/store/configs/index.js +2 -2
- package/src/tests/react/api/loadSmokeIndex.test.js +75 -0
- package/src/tests/react/config/deviceConfigBootstrap.test.js +47 -0
- package/src/tests/react/print/localPrintProvider.test.js +1 -1
- package/src/tests/react/services/Cielo.test.js +190 -0
- package/src/tests/react/utils/fileUrl.test.js +62 -0
- package/src/tests/react/utils/importStatus.test.js +2 -2
- package/src/tests/react/utils/orderIdentity.test.js +139 -0
- package/src/tests/react/utils/remotePayment.test.js +62 -0
- package/src/tests/react/utils/runtimeFooter.test.js +4 -6
- package/src/tests/react/utils/runtimeLanguage.test.js +2 -2
- package/src/tests/react/utils/runtimeMenu.test.js +23 -3
- package/src/tests/react/utils/shopConfig.test.js +74 -0
- package/src/tests/react/utils/shopFranchises.test.js +79 -12
- package/src/tests/react/utils/translate.test.mjs +166 -102
- package/src/utils/formatter.js +18 -0
- package/src/utils/integrationConfigs.js +80 -79
- package/src/utils/translate.js +125 -30
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
const {jest} = require('@jest/globals')
|
|
2
|
+
|
|
3
|
+
const mockPayment = jest.fn()
|
|
4
|
+
const mockFetch = jest.fn()
|
|
5
|
+
const mockGetAllStores = jest.fn()
|
|
6
|
+
|
|
7
|
+
jest.mock('@controleonline-rn/react-native-cielo-payment', () => ({
|
|
8
|
+
payment: (...args) => mockPayment(...args),
|
|
9
|
+
}))
|
|
10
|
+
|
|
11
|
+
jest.mock('@controleonline/ui-common/src/api', () => ({
|
|
12
|
+
api: {
|
|
13
|
+
fetch: (...args) => mockFetch(...args),
|
|
14
|
+
},
|
|
15
|
+
}))
|
|
16
|
+
|
|
17
|
+
jest.mock('@store', () => ({
|
|
18
|
+
getAllStores: (...args) => mockGetAllStores(...args),
|
|
19
|
+
}))
|
|
20
|
+
|
|
21
|
+
jest.mock('@env', () => ({
|
|
22
|
+
env: {
|
|
23
|
+
CIELO: {
|
|
24
|
+
ACCESS_TOKEN: '',
|
|
25
|
+
CLIENT_ID: '',
|
|
26
|
+
EMAIL: '',
|
|
27
|
+
MERCHANT_CODE: '',
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
}))
|
|
31
|
+
|
|
32
|
+
const {describe, expect, it, beforeEach} = global
|
|
33
|
+
|
|
34
|
+
const loadService = () => {
|
|
35
|
+
const serviceModule = require('../../../react/services/Cielo/Cielo')
|
|
36
|
+
return serviceModule.default || serviceModule
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const runtimeStores = merchantCode => ({
|
|
40
|
+
people: {
|
|
41
|
+
getters: {
|
|
42
|
+
currentCompany: {
|
|
43
|
+
id: 99,
|
|
44
|
+
configs: {
|
|
45
|
+
CIELO: JSON.stringify({
|
|
46
|
+
ACCESS_TOKEN: 'runtime-token',
|
|
47
|
+
CLIENT_ID: 'runtime-client',
|
|
48
|
+
EMAIL: 'runtime@empresa.com',
|
|
49
|
+
...(merchantCode ? {MERCHANT_CODE: merchantCode} : {}),
|
|
50
|
+
}),
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
defaultCompany: {id: 99},
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
configs: {
|
|
57
|
+
getters: {
|
|
58
|
+
items: {
|
|
59
|
+
CIELO: JSON.stringify({
|
|
60
|
+
ACCESS_TOKEN: 'runtime-token',
|
|
61
|
+
CLIENT_ID: 'runtime-client',
|
|
62
|
+
EMAIL: 'runtime@empresa.com',
|
|
63
|
+
...(merchantCode ? {MERCHANT_CODE: merchantCode} : {}),
|
|
64
|
+
}),
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
describe('CieloService', () => {
|
|
71
|
+
beforeEach(() => {
|
|
72
|
+
jest.resetModules()
|
|
73
|
+
mockPayment.mockReset()
|
|
74
|
+
mockFetch.mockReset()
|
|
75
|
+
mockGetAllStores.mockReset()
|
|
76
|
+
|
|
77
|
+
mockPayment.mockResolvedValue({
|
|
78
|
+
success: true,
|
|
79
|
+
code: '0',
|
|
80
|
+
result: JSON.stringify({
|
|
81
|
+
status: 'ok',
|
|
82
|
+
payments: [{merchantCode: '0000000000000001'}],
|
|
83
|
+
}),
|
|
84
|
+
})
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
it('falls back to the main company private CIELO config', async () => {
|
|
88
|
+
mockGetAllStores.mockReturnValue({
|
|
89
|
+
people: {
|
|
90
|
+
getters: {
|
|
91
|
+
currentCompany: {id: 21, configs: {}},
|
|
92
|
+
defaultCompany: {id: 99},
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
configs: {getters: {items: {}}},
|
|
96
|
+
})
|
|
97
|
+
mockFetch.mockResolvedValue({
|
|
98
|
+
member: [
|
|
99
|
+
{
|
|
100
|
+
configKey: 'CIELO',
|
|
101
|
+
configValue: JSON.stringify({
|
|
102
|
+
ACCESS_TOKEN: 'private-token',
|
|
103
|
+
CLIENT_ID: 'private-client',
|
|
104
|
+
EMAIL: 'cielo@principal.com',
|
|
105
|
+
MERCHANT_CODE: '0000000000000001',
|
|
106
|
+
}),
|
|
107
|
+
},
|
|
108
|
+
],
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
const CieloService = loadService()
|
|
112
|
+
await new CieloService().payment('credit', [{name: 'Produto'}], 1250)
|
|
113
|
+
|
|
114
|
+
expect(mockFetch).toHaveBeenCalledWith('/configs', {
|
|
115
|
+
params: {
|
|
116
|
+
configKey: 'CIELO',
|
|
117
|
+
people: '/people/99',
|
|
118
|
+
visibility: 'private',
|
|
119
|
+
},
|
|
120
|
+
})
|
|
121
|
+
expect(JSON.parse(mockPayment.mock.calls[0][0])).toMatchObject({
|
|
122
|
+
accessToken: 'private-token',
|
|
123
|
+
clientID: 'private-client',
|
|
124
|
+
email: 'cielo@principal.com',
|
|
125
|
+
merchantCode: '0000000000000001',
|
|
126
|
+
paymentCode: 'credit',
|
|
127
|
+
value: 1250,
|
|
128
|
+
})
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
it('sends the configured merchantCode to Cielo', async () => {
|
|
132
|
+
mockGetAllStores.mockReturnValue(runtimeStores('0000000000000001'))
|
|
133
|
+
|
|
134
|
+
const CieloService = loadService()
|
|
135
|
+
await new CieloService().payment('debit', [], 500)
|
|
136
|
+
|
|
137
|
+
expect(mockFetch).not.toHaveBeenCalled()
|
|
138
|
+
expect(JSON.parse(mockPayment.mock.calls[0][0])).toMatchObject({
|
|
139
|
+
merchantCode: '0000000000000001',
|
|
140
|
+
paymentCode: 'debit',
|
|
141
|
+
value: 500,
|
|
142
|
+
})
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
it('keeps the legacy request when merchantCode is not configured', async () => {
|
|
146
|
+
mockGetAllStores.mockReturnValue(runtimeStores(''))
|
|
147
|
+
|
|
148
|
+
const CieloService = loadService()
|
|
149
|
+
await new CieloService().payment('debit', [], 500)
|
|
150
|
+
|
|
151
|
+
expect(JSON.parse(mockPayment.mock.calls[0][0])).not.toHaveProperty(
|
|
152
|
+
'merchantCode',
|
|
153
|
+
)
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
it('rejects a successful response without merchantCode', async () => {
|
|
157
|
+
mockGetAllStores.mockReturnValue(runtimeStores('0000000000000001'))
|
|
158
|
+
mockPayment.mockResolvedValue({
|
|
159
|
+
success: true,
|
|
160
|
+
code: '0',
|
|
161
|
+
result: JSON.stringify({status: 'ok', payments: [{}]}),
|
|
162
|
+
})
|
|
163
|
+
|
|
164
|
+
const CieloService = loadService()
|
|
165
|
+
const response = await new CieloService().payment('debit', [], 500)
|
|
166
|
+
|
|
167
|
+
expect(response.success).toBe(false)
|
|
168
|
+
})
|
|
169
|
+
|
|
170
|
+
it('rejects a successful response from a different merchantCode', async () => {
|
|
171
|
+
mockGetAllStores.mockReturnValue(runtimeStores('0000000000000001'))
|
|
172
|
+
mockPayment.mockResolvedValue({
|
|
173
|
+
success: true,
|
|
174
|
+
code: '0',
|
|
175
|
+
result: JSON.stringify({
|
|
176
|
+
status: 'ok',
|
|
177
|
+
payments: [{merchantCode: '0000000000000002'}],
|
|
178
|
+
}),
|
|
179
|
+
})
|
|
180
|
+
|
|
181
|
+
const CieloService = loadService()
|
|
182
|
+
const response = await new CieloService().payment('debit', [], 500)
|
|
183
|
+
|
|
184
|
+
expect(response).toMatchObject({
|
|
185
|
+
success: false,
|
|
186
|
+
result:
|
|
187
|
+
'Pagamento processado em estabelecimento Cielo diferente do configurado.',
|
|
188
|
+
})
|
|
189
|
+
})
|
|
190
|
+
})
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
const {describe, expect, it} = global;
|
|
2
|
+
const {jest} = require('@jest/globals');
|
|
3
|
+
|
|
4
|
+
jest.mock('@env', () => ({
|
|
5
|
+
env: {
|
|
6
|
+
API_ENTRYPOINT: 'https://api.controleonline.com',
|
|
7
|
+
DOMAIN: 'manager.controleonline.com',
|
|
8
|
+
},
|
|
9
|
+
}));
|
|
10
|
+
|
|
11
|
+
const {
|
|
12
|
+
resolveDefaultFileSource,
|
|
13
|
+
resolveFileImageUrl,
|
|
14
|
+
} = require('../../../react/utils/fileUrl');
|
|
15
|
+
|
|
16
|
+
describe('fileUrl helpers', () => {
|
|
17
|
+
it('adds app-domain to backend download urls and keeps headers', () => {
|
|
18
|
+
const company = {
|
|
19
|
+
domain: 'maincompany.controleonline.com',
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const source = resolveDefaultFileSource(
|
|
23
|
+
{
|
|
24
|
+
id: 3,
|
|
25
|
+
url: '/files/3/download',
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
company,
|
|
29
|
+
headers: {
|
|
30
|
+
Authorization: 'Bearer token',
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
expect(source).toEqual({
|
|
36
|
+
uri: 'https://api.controleonline.com/files/3/download?app-domain=maincompany.controleonline.com',
|
|
37
|
+
headers: {
|
|
38
|
+
Authorization: 'Bearer token',
|
|
39
|
+
'app-domain': 'maincompany.controleonline.com',
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
expect(resolveFileImageUrl(3, {company})).toBe(
|
|
43
|
+
'https://api.controleonline.com/files/3/download?app-domain=maincompany.controleonline.com',
|
|
44
|
+
);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('keeps external image urls untouched', () => {
|
|
48
|
+
const source = resolveDefaultFileSource(
|
|
49
|
+
'https://cdn.controleonline.com/logo.png',
|
|
50
|
+
{
|
|
51
|
+
company: {
|
|
52
|
+
domain: 'maincompany.controleonline.com',
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
expect(source).toEqual({
|
|
58
|
+
uri: 'https://cdn.controleonline.com/logo.png',
|
|
59
|
+
headers: {},
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
});
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
const {jest} = require('@jest/globals');
|
|
2
|
+
|
|
3
|
+
const {resolveOrderIdentity} = require('../../../react/utils/orderIdentity');
|
|
4
|
+
|
|
5
|
+
const {describe, expect, it} = global;
|
|
6
|
+
|
|
7
|
+
global.t = {
|
|
8
|
+
t: jest.fn((store, type, key) => {
|
|
9
|
+
if (store === 'orders' && type === 'title' && key === 'table') {
|
|
10
|
+
return 'Mesa';
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (store === 'orders' && type === 'title' && key === 'order') {
|
|
14
|
+
return 'Pedido';
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return '';
|
|
18
|
+
}),
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
describe('orderIdentity', () => {
|
|
22
|
+
it('prioritizes the 99Food code field from extra data', () => {
|
|
23
|
+
const order = {
|
|
24
|
+
id: 70911,
|
|
25
|
+
app: '99Food',
|
|
26
|
+
extraData: [
|
|
27
|
+
{
|
|
28
|
+
extraFields: {
|
|
29
|
+
context: 'Food99',
|
|
30
|
+
name: 'id',
|
|
31
|
+
},
|
|
32
|
+
value: '71759',
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
extraFields: {
|
|
36
|
+
context: 'Food99',
|
|
37
|
+
name: 'code',
|
|
38
|
+
},
|
|
39
|
+
value: '70001',
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const identity = resolveOrderIdentity(order);
|
|
45
|
+
|
|
46
|
+
expect(identity.externalLabel).toBe('99');
|
|
47
|
+
expect(identity.externalId).toBe('70001');
|
|
48
|
+
expect(identity.primaryText).toBe('#70001');
|
|
49
|
+
expect(identity.secondaryText).toBe('#70911');
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it('does not invent an iFood marketplace code from pickup or display ids', () => {
|
|
53
|
+
const order = {
|
|
54
|
+
id: 81234,
|
|
55
|
+
app: 'ifood',
|
|
56
|
+
otherInformations: JSON.stringify({
|
|
57
|
+
ifood: {
|
|
58
|
+
latest_event_type: 'PLACED',
|
|
59
|
+
PLACED: {
|
|
60
|
+
order: {
|
|
61
|
+
id: 'ifood-order-1',
|
|
62
|
+
displayId: '70002',
|
|
63
|
+
delivery: {
|
|
64
|
+
pickupCode: '0176',
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
}),
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const identity = resolveOrderIdentity(order);
|
|
73
|
+
|
|
74
|
+
expect(identity.externalLabel).toBe('');
|
|
75
|
+
expect(identity.externalId).toBe('');
|
|
76
|
+
expect(identity.primaryText).toBe('#81234');
|
|
77
|
+
expect(identity.secondaryText).toBe('');
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it('prioritizes iFood code from extra data over pickup code', () => {
|
|
81
|
+
const order = {
|
|
82
|
+
id: 71759,
|
|
83
|
+
app: 'iFood',
|
|
84
|
+
extra_data: [
|
|
85
|
+
{
|
|
86
|
+
extra_fields: {
|
|
87
|
+
context: 'iFood',
|
|
88
|
+
name: 'pickup_code',
|
|
89
|
+
},
|
|
90
|
+
value: '9103',
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
extra_fields: {
|
|
94
|
+
context: 'iFood',
|
|
95
|
+
name: 'code',
|
|
96
|
+
},
|
|
97
|
+
value: '3984',
|
|
98
|
+
},
|
|
99
|
+
],
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
const identity = resolveOrderIdentity(order);
|
|
103
|
+
|
|
104
|
+
expect(identity.externalLabel).toBe('IFOOD');
|
|
105
|
+
expect(identity.externalId).toBe('3984');
|
|
106
|
+
expect(identity.primaryText).toBe('#3984');
|
|
107
|
+
expect(identity.secondaryText).toBe('#71759');
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it('prioritizes POS externalCode as the main order identity', () => {
|
|
111
|
+
const order = {
|
|
112
|
+
id: 71604,
|
|
113
|
+
app: 'POS',
|
|
114
|
+
externalCode: '570002',
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
const identity = resolveOrderIdentity(order);
|
|
118
|
+
|
|
119
|
+
expect(identity.externalLabel).toBe('');
|
|
120
|
+
expect(identity.externalId).toBe('570002');
|
|
121
|
+
expect(identity.primaryText).toBe('Mesa #570002');
|
|
122
|
+
expect(identity.secondaryText).toBe('#71604');
|
|
123
|
+
expect(global.t.t).toHaveBeenCalledWith('orders', 'title', 'table');
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it('uses only the hash-prefixed local id for non-marketplace orders', () => {
|
|
127
|
+
const order = {
|
|
128
|
+
id: 70700,
|
|
129
|
+
app: 'shop',
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
const identity = resolveOrderIdentity(order);
|
|
133
|
+
|
|
134
|
+
expect(identity.externalLabel).toBe('');
|
|
135
|
+
expect(identity.externalId).toBe('');
|
|
136
|
+
expect(identity.primaryText).toBe('#70700');
|
|
137
|
+
expect(identity.secondaryText).toBe('');
|
|
138
|
+
});
|
|
139
|
+
});
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
const {
|
|
2
|
+
buildRemotePaymentResultMessage,
|
|
3
|
+
isRemotePaymentCancellation,
|
|
4
|
+
normalizeRemotePaymentResultStatus,
|
|
5
|
+
} = require('../../../react/utils/remotePayment')
|
|
6
|
+
|
|
7
|
+
const {describe, expect, it} = global
|
|
8
|
+
|
|
9
|
+
describe('remotePayment result status', () => {
|
|
10
|
+
it.each(['canceled', 'cancelled', 'cancel'])(
|
|
11
|
+
'normalizes the explicit %s status as a cancellation',
|
|
12
|
+
status => {
|
|
13
|
+
expect(normalizeRemotePaymentResultStatus({status})).toBe('canceled')
|
|
14
|
+
expect(isRemotePaymentCancellation({status})).toBe(true)
|
|
15
|
+
},
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
it.each([
|
|
19
|
+
'Pagamento PIX cancelado pelo usuario.',
|
|
20
|
+
'Pagamento cancelado pelo usuário',
|
|
21
|
+
'Payment cancelled by user',
|
|
22
|
+
'Payment canceled by customer',
|
|
23
|
+
])('recognizes legacy cancellation errors: %s', error => {
|
|
24
|
+
const result = {status: 'error', error}
|
|
25
|
+
|
|
26
|
+
expect(normalizeRemotePaymentResultStatus(result)).toBe('canceled')
|
|
27
|
+
expect(isRemotePaymentCancellation(result)).toBe(true)
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
it.each([
|
|
31
|
+
'Falha de comunicacao com o terminal.',
|
|
32
|
+
'Nao foi possivel cancelar a transacao.',
|
|
33
|
+
'Tempo limite excedido.',
|
|
34
|
+
])('keeps a real gateway failure as an error: %s', error => {
|
|
35
|
+
const result = {status: 'error', error}
|
|
36
|
+
|
|
37
|
+
expect(normalizeRemotePaymentResultStatus(result)).toBe('error')
|
|
38
|
+
expect(isRemotePaymentCancellation(result)).toBe(false)
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
it('preserves cancellation when building the remote result message', () => {
|
|
42
|
+
expect(
|
|
43
|
+
buildRemotePaymentResultMessage({
|
|
44
|
+
destinationDeviceId: 'web-7',
|
|
45
|
+
orderId: 123,
|
|
46
|
+
requestKey: '123:158:pix:1',
|
|
47
|
+
status: 'cancelled',
|
|
48
|
+
}),
|
|
49
|
+
).toMatchObject({
|
|
50
|
+
action: 'pay-result',
|
|
51
|
+
destination: 'web-7',
|
|
52
|
+
order: '123',
|
|
53
|
+
requestKey: '123:158:pix:1',
|
|
54
|
+
status: 'canceled',
|
|
55
|
+
})
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
it('keeps successful and unknown results compatible with the existing contract', () => {
|
|
59
|
+
expect(normalizeRemotePaymentResultStatus({status: 'success'})).toBe('success')
|
|
60
|
+
expect(normalizeRemotePaymentResultStatus({status: 'unexpected'})).toBe('error')
|
|
61
|
+
})
|
|
62
|
+
})
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const assert = require('node:assert/strict')
|
|
2
|
-
const test =
|
|
3
|
-
const {jest
|
|
2
|
+
const {beforeAll, afterAll, test} = global
|
|
3
|
+
const {jest} = require('@jest/globals')
|
|
4
4
|
|
|
5
5
|
jest.mock('@controleonline/ui-common/src/react/utils/printerDevices', () => ({
|
|
6
6
|
getDeviceTypeLabel: value => String(value || ''),
|
|
@@ -43,7 +43,7 @@ const restoreLocation = () => {
|
|
|
43
43
|
delete globalThis.location
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
|
|
46
|
+
beforeAll(() => {
|
|
47
47
|
global.t = {
|
|
48
48
|
getMessageFromBuckets: (store, type, key) =>
|
|
49
49
|
store === 'common' && type === 'option'
|
|
@@ -52,7 +52,7 @@ test.before(() => {
|
|
|
52
52
|
}
|
|
53
53
|
})
|
|
54
54
|
|
|
55
|
-
|
|
55
|
+
afterAll(() => {
|
|
56
56
|
global.t = originalTranslator
|
|
57
57
|
})
|
|
58
58
|
|
|
@@ -425,5 +425,3 @@ test('falls back to the local device id when the backend identifier is unavailab
|
|
|
425
425
|
assert.equal(candidates[0]?.value, 'local-device-99')
|
|
426
426
|
assert.equal(candidates[0]?.source, 'device.id')
|
|
427
427
|
})
|
|
428
|
-
|
|
429
|
-
jestCompatTest('jest compatibility placeholder', () => {})
|
|
@@ -157,9 +157,29 @@ describe('runtimeMenu', () => {
|
|
|
157
157
|
expect(menus[3].menus.map(item => item.route)).toEqual([
|
|
158
158
|
'DevicesIndex',
|
|
159
159
|
'ConfiguratorPage',
|
|
160
|
-
]);
|
|
161
|
-
});
|
|
162
|
-
|
|
160
|
+
]);
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
it('falls back to the admin starter menu when the runtime menu is empty', () => {
|
|
164
|
+
const menus = normalizeRuntimeMenuResponse({}, {appType: 'ADMIN'});
|
|
165
|
+
|
|
166
|
+
expect(menus).toHaveLength(1);
|
|
167
|
+
expect(menus[0].label).toBe('Configuracoes');
|
|
168
|
+
expect(menus[0].menus).toHaveLength(2);
|
|
169
|
+
expect(menus[0].menus[0]).toMatchObject({
|
|
170
|
+
label: 'Menus por perfil',
|
|
171
|
+
menuKey: 'menu_access',
|
|
172
|
+
route: 'MenuAccessConfigPage',
|
|
173
|
+
menuType: 'home',
|
|
174
|
+
});
|
|
175
|
+
expect(menus[0].menus[1]).toMatchObject({
|
|
176
|
+
label: 'Resultados de testes',
|
|
177
|
+
menuKey: 'test_results',
|
|
178
|
+
route: 'TestsPlaygroundPage',
|
|
179
|
+
menuType: 'home',
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
|
|
163
183
|
it('does not invent a fallback menu for non-manager apps', () => {
|
|
164
184
|
expect(
|
|
165
185
|
normalizeRuntimeMenuResponse({}, {appType: 'SHOP'}),
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
const assert = require('node:assert/strict');
|
|
2
|
+
const {describe, it} = global;
|
|
3
|
+
|
|
4
|
+
const {
|
|
5
|
+
resolveShopSettings,
|
|
6
|
+
SHOP_LOYALTY_STAMP_ICON_URL_CONFIG_KEY,
|
|
7
|
+
toggleAndSaveBooleanConfig,
|
|
8
|
+
} = require('../../../react/utils/shopConfig');
|
|
9
|
+
|
|
10
|
+
describe('shopConfig', () => {
|
|
11
|
+
it('reads the configured loyalty stamp icon URL from general settings', () => {
|
|
12
|
+
const result = resolveShopSettings({
|
|
13
|
+
[SHOP_LOYALTY_STAMP_ICON_URL_CONFIG_KEY]:
|
|
14
|
+
'"https://cdn.example.com/loyalty-stamp.png"',
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
assert.equal(
|
|
18
|
+
result.loyaltyStampIconUrl,
|
|
19
|
+
'https://cdn.example.com/loyalty-stamp.png',
|
|
20
|
+
);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('keeps the loyalty stamp icon URL empty when it is not configured', () => {
|
|
24
|
+
const result = resolveShopSettings({});
|
|
25
|
+
|
|
26
|
+
assert.equal(result.loyaltyStampIconUrl, '');
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('persists the next boolean value when a toggle is clicked', async () => {
|
|
30
|
+
const calls = [];
|
|
31
|
+
const setValue = value => {
|
|
32
|
+
calls.push(['setValue', value]);
|
|
33
|
+
};
|
|
34
|
+
const saveConfig = async (configKey, value) => {
|
|
35
|
+
calls.push(['saveConfig', configKey, value]);
|
|
36
|
+
return true;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
await toggleAndSaveBooleanConfig({
|
|
40
|
+
configKey: 'shop-sales-page-enabled',
|
|
41
|
+
currentValue: false,
|
|
42
|
+
saveConfig,
|
|
43
|
+
setValue,
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
assert.deepEqual(calls, [
|
|
47
|
+
['setValue', true],
|
|
48
|
+
['saveConfig', 'shop-sales-page-enabled', '1'],
|
|
49
|
+
]);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it('persists the disabled value when toggling an enabled config', async () => {
|
|
53
|
+
const calls = [];
|
|
54
|
+
const setValue = value => {
|
|
55
|
+
calls.push(['setValue', value]);
|
|
56
|
+
};
|
|
57
|
+
const saveConfig = async (configKey, value) => {
|
|
58
|
+
calls.push(['saveConfig', configKey, value]);
|
|
59
|
+
return true;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
await toggleAndSaveBooleanConfig({
|
|
63
|
+
configKey: 'shop-bottom-bar-enabled',
|
|
64
|
+
currentValue: true,
|
|
65
|
+
saveConfig,
|
|
66
|
+
setValue,
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
assert.deepEqual(calls, [
|
|
70
|
+
['setValue', false],
|
|
71
|
+
['saveConfig', 'shop-bottom-bar-enabled', '0'],
|
|
72
|
+
]);
|
|
73
|
+
});
|
|
74
|
+
});
|