@controleonline/ui-customers 1.0.81
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/.github/agents/developer.agent.md +30 -0
- package/.github/agents/devops.agent.md +30 -0
- package/.github/agents/qa.agent.md +30 -0
- package/.github/agents/security.agent.md +30 -0
- package/.scrutinizer.yml +20 -0
- package/AGENTS.md +50 -0
- package/FUNDING.yml +1 -0
- package/README.md +23 -0
- package/docs/technical/Client-Details-Franquia-Filial.md +18 -0
- package/docs/technical/Client-Details-People-Name-Case.md +103 -0
- package/docs/technical/Cliente-Vendedor-Vinculo-e-Permissoes.md +152 -0
- package/docs/wiki.md +1 -0
- package/package.json +32 -0
- package/scripts/validate-wiki-pointer.cjs +13 -0
- package/src/react/components/tabs/AddressesTab.js +494 -0
- package/src/react/components/tabs/CategoriesTab.js +196 -0
- package/src/react/components/tabs/ClassificationChips.js +494 -0
- package/src/react/components/tabs/ContactTab.js +621 -0
- package/src/react/components/tabs/ContactTab.styles.js +119 -0
- package/src/react/components/tabs/ContractsTab.js +13 -0
- package/src/react/components/tabs/DocumentsTab.js +463 -0
- package/src/react/components/tabs/DocumentsTab.styles.js +133 -0
- package/src/react/components/tabs/EmployeeContactRow.js +83 -0
- package/src/react/components/tabs/EmployeesTab.js +454 -0
- package/src/react/components/tabs/EmployeesTab.styles.js +172 -0
- package/src/react/components/tabs/FiscalTab.js +6 -0
- package/src/react/components/tabs/FranchiseCommissionSection.js +307 -0
- package/src/react/components/tabs/FranchiseLinksManageModal.js +215 -0
- package/src/react/components/tabs/FranchiseLinksTab.js +282 -0
- package/src/react/components/tabs/GeneralTab.js +466 -0
- package/src/react/components/tabs/GeneralTab.styles.js +101 -0
- package/src/react/components/tabs/MediaTab.js +356 -0
- package/src/react/components/tabs/PeopleCategoriesPanel.js +601 -0
- package/src/react/components/tabs/ProductsTab.js +236 -0
- package/src/react/components/tabs/ProductsTab.styles.js +143 -0
- package/src/react/components/tabs/SalesmanCommissionBlock.js +120 -0
- package/src/react/components/tabs/SalesmanManageModal.js +208 -0
- package/src/react/components/tabs/SalesmanTab.js +436 -0
- package/src/react/components/tabs/SalesmanTab.styles.js +4 -0
- package/src/react/components/tabs/UserApiKeyModal.js +90 -0
- package/src/react/components/tabs/UserFormModal.js +301 -0
- package/src/react/components/tabs/UsersTab.js +426 -0
- package/src/react/components/tabs/UsersTab.styles.js +283 -0
- package/src/react/components/tabs/UsersTab.styles.test.js +42 -0
- package/src/react/components/tabs/contactMutationMessage.js +18 -0
- package/src/react/components/tabs/employeeContacts.js +214 -0
- package/src/react/components/tabs/employeeUnlink.js +68 -0
- package/src/react/components/tabs/employeesTabHelpers.js +227 -0
- package/src/react/components/tabs/franchiseCommissionHelpers.js +134 -0
- package/src/react/components/tabs/franchiseLinksTab.helpers.js +247 -0
- package/src/react/components/tabs/generalTabHelpers.js +120 -0
- package/src/react/components/tabs/salesmanTab.helpers.js +114 -0
- package/src/react/components/tabs/salesmanTabHelpers.js +173 -0
- package/src/react/components/tabs/salesmanTabMedia.js +55 -0
- package/src/react/components/tabs/salesmanTabSession.js +39 -0
- package/src/react/components/tabs/useEmployeeUnlink.js +58 -0
- package/src/react/components/tabs/useFranchiseLinksManage.js +215 -0
- package/src/react/components/tabs/useSalesmanManage.js +222 -0
- package/src/react/components/tabs/usersTabHelpers.js +221 -0
- package/src/react/domain/productSupplierFlow.js +37 -0
- package/src/react/index.js +4 -0
- package/src/react/pages/ClientDetailsSkeleton.js +84 -0
- package/src/react/pages/clientDetailsHelpers.js +17 -0
- package/src/react/pages/clients.js +27 -0
- package/src/react/pages/details.js +529 -0
- package/src/react/pages/details.page.styles.js +105 -0
- package/src/react/pages/details.styles.js +15 -0
- package/src/react/pages/employees.js +69 -0
- package/src/react/pages/franchisees.js +30 -0
- package/src/react/pages/prospects.js +21 -0
- package/src/react/pages/provider.js +21 -0
- package/src/react/router/routes.js +104 -0
- package/src/react/styles/details.js +571 -0
- package/src/store/people_categories/index.js +72 -0
- package/src/tests/browser/manager/client-details-create-user.spec.js +321 -0
- package/src/tests/browser/manager/client-details-employee-unlink.spec.js +215 -0
- package/src/tests/browser/manager/client-details-employees-refresh.spec.js +271 -0
- package/src/tests/browser/manager/client-details-enable.spec.js +241 -0
- package/src/tests/browser/manager/client-details-fiscal-tabs.spec.js +410 -0
- package/src/tests/browser/manager/client-details-franchise-commission.spec.js +318 -0
- package/src/tests/browser/manager/client-details-franchise-links.spec.js +365 -0
- package/src/tests/browser/manager/client-details-media.spec.js +405 -0
- package/src/tests/browser/manager/client-details-relationships.spec.js +313 -0
- package/src/tests/browser/manager/client-details-salesman-commission.spec.js +291 -0
- package/src/tests/browser/manager/client-details-salesman-manage.spec.js +448 -0
- package/src/tests/react/components/tabs/contactMutationMessage.test.js +25 -0
- package/src/tests/react/components/tabs/employeeContacts.test.js +266 -0
- package/src/tests/react/components/tabs/employeeUnlink.test.js +67 -0
- package/src/tests/react/components/tabs/employeesTabHelpers.media.test.js +78 -0
- package/src/tests/react/components/tabs/employeesTabHelpers.test.js +64 -0
- package/src/tests/react/components/tabs/fiscalTabContract.test.mjs +29 -0
- package/src/tests/react/components/tabs/franchiseCommissionHelpers.test.js +128 -0
- package/src/tests/react/components/tabs/franchiseLinksTab.helpers.test.mjs +166 -0
- package/src/tests/react/components/tabs/generalTabHelpers.test.js +130 -0
- package/src/tests/react/components/tabs/peopleMediaTabs.test.js +322 -0
- package/src/tests/react/components/tabs/salesmanTab.helpers.test.mjs +75 -0
- package/src/tests/react/components/tabs/salesmanTabHelpers.test.js +142 -0
- package/src/tests/react/components/tabs/salesmanTabHelpers.test.mjs +92 -0
- package/src/tests/react/components/tabs/usersTabHelpers.test.js +59 -0
- package/src/tests/react/domain/productSupplierFlow.test.mjs +55 -0
- package/src/tests/react/pages/clientDetailsHelpers.test.js +98 -0
- package/src/tests/react/pages/employees.test.js +44 -0
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for SalesmanTab commission helpers (override precedence + permissions).
|
|
3
|
+
*/
|
|
4
|
+
const {
|
|
5
|
+
isCommissionFilled,
|
|
6
|
+
toCommissionNumber,
|
|
7
|
+
resolveEffectiveCommission,
|
|
8
|
+
formatCommissionPercent,
|
|
9
|
+
formatCommissionSubtitle,
|
|
10
|
+
canEditSalesmanCommission,
|
|
11
|
+
shouldDisplayCommission,
|
|
12
|
+
indexDefaultSalesmanLinksByPeopleId,
|
|
13
|
+
buildCommissionSavePayload,
|
|
14
|
+
} = require('../../../../react/components/tabs/salesmanTabHelpers');
|
|
15
|
+
|
|
16
|
+
describe('salesmanTabHelpers', () => {
|
|
17
|
+
describe('isCommissionFilled / toCommissionNumber', () => {
|
|
18
|
+
it('treats null/undefined/empty as not filled', () => {
|
|
19
|
+
expect(isCommissionFilled(null)).toBe(false);
|
|
20
|
+
expect(isCommissionFilled(undefined)).toBe(false);
|
|
21
|
+
expect(isCommissionFilled('')).toBe(false);
|
|
22
|
+
expect(isCommissionFilled(' ')).toBe(false);
|
|
23
|
+
expect(toCommissionNumber(null)).toBe(null);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('treats 0 as filled', () => {
|
|
27
|
+
expect(isCommissionFilled(0)).toBe(true);
|
|
28
|
+
expect(toCommissionNumber(0)).toBe(0);
|
|
29
|
+
expect(toCommissionNumber('12.5')).toBe(12.5);
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
describe('resolveEffectiveCommission', () => {
|
|
34
|
+
it('uses client link commission when filled (override)', () => {
|
|
35
|
+
const result = resolveEffectiveCommission(
|
|
36
|
+
{ comission: 15, minimum_comission: 5 },
|
|
37
|
+
{ comission: 10, minimum_comission: 2 },
|
|
38
|
+
);
|
|
39
|
+
expect(result).toEqual({
|
|
40
|
+
comission: 15,
|
|
41
|
+
minimumComission: 5,
|
|
42
|
+
isOverride: true,
|
|
43
|
+
source: 'client',
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('falls back to salesman-company default when client commission is empty', () => {
|
|
48
|
+
const result = resolveEffectiveCommission(
|
|
49
|
+
{ comission: null, minimum_comission: null },
|
|
50
|
+
{ comission: 10, minimum_comission: 2 },
|
|
51
|
+
);
|
|
52
|
+
expect(result).toEqual({
|
|
53
|
+
comission: 10,
|
|
54
|
+
minimumComission: 2,
|
|
55
|
+
isOverride: false,
|
|
56
|
+
source: 'default',
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('returns none when neither client nor default is filled', () => {
|
|
61
|
+
expect(resolveEffectiveCommission({}, null)).toEqual({
|
|
62
|
+
comission: null,
|
|
63
|
+
minimumComission: null,
|
|
64
|
+
isOverride: false,
|
|
65
|
+
source: 'none',
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('overrides only the filled field and keeps default for the other', () => {
|
|
70
|
+
const result = resolveEffectiveCommission(
|
|
71
|
+
{ comission: 20, minimum_comission: null },
|
|
72
|
+
{ comission: 10, minimum_comission: 3 },
|
|
73
|
+
);
|
|
74
|
+
expect(result.comission).toBe(20);
|
|
75
|
+
expect(result.minimumComission).toBe(3);
|
|
76
|
+
expect(result.isOverride).toBe(true);
|
|
77
|
+
expect(result.source).toBe('client');
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
describe('formatCommissionPercent / formatCommissionSubtitle', () => {
|
|
82
|
+
it('formats percent and subtitle with override/default tags', () => {
|
|
83
|
+
expect(formatCommissionPercent(10)).toBe('10%');
|
|
84
|
+
expect(formatCommissionPercent(null)).toBe('—');
|
|
85
|
+
expect(
|
|
86
|
+
formatCommissionSubtitle({
|
|
87
|
+
comission: 15,
|
|
88
|
+
minimumComission: 5,
|
|
89
|
+
isOverride: true,
|
|
90
|
+
source: 'client',
|
|
91
|
+
}),
|
|
92
|
+
).toContain('override');
|
|
93
|
+
expect(
|
|
94
|
+
formatCommissionSubtitle({
|
|
95
|
+
comission: 10,
|
|
96
|
+
minimumComission: null,
|
|
97
|
+
isOverride: false,
|
|
98
|
+
source: 'default',
|
|
99
|
+
}),
|
|
100
|
+
).toContain('padrão');
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
describe('canEditSalesmanCommission / shouldDisplayCommission', () => {
|
|
105
|
+
it('allows ROLE_SUPER and ROLE_OWNER only', () => {
|
|
106
|
+
expect(canEditSalesmanCommission({ roles: ['ROLE_SUPER'] })).toBe(true);
|
|
107
|
+
expect(canEditSalesmanCommission({ roles: ['ROLE_OWNER'] })).toBe(true);
|
|
108
|
+
expect(canEditSalesmanCommission({ roles: ['ROLE_EMPLOYEE'] })).toBe(false);
|
|
109
|
+
expect(canEditSalesmanCommission(null)).toBe(false);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it('shows commission only for MANAGER/ADMIN app types', () => {
|
|
113
|
+
expect(shouldDisplayCommission('MANAGER')).toBe(true);
|
|
114
|
+
expect(shouldDisplayCommission('ADMIN')).toBe(true);
|
|
115
|
+
expect(shouldDisplayCommission('CRM')).toBe(false);
|
|
116
|
+
expect(shouldDisplayCommission('POS')).toBe(false);
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
describe('indexDefaultSalesmanLinksByPeopleId / buildCommissionSavePayload', () => {
|
|
121
|
+
it('indexes default salesman links by people id', () => {
|
|
122
|
+
const map = indexDefaultSalesmanLinksByPeopleId([
|
|
123
|
+
{ id: 1, people: { id: 50 }, comission: 10 },
|
|
124
|
+
{ id: 2, people: '/people/51', comission: 8 },
|
|
125
|
+
]);
|
|
126
|
+
expect(map['50'].comission).toBe(10);
|
|
127
|
+
expect(map['51'].comission).toBe(8);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it('builds save payload with numeric commissions', () => {
|
|
131
|
+
expect(
|
|
132
|
+
buildCommissionSavePayload(
|
|
133
|
+
{ id: 101 },
|
|
134
|
+
{ comission: '15', minimumComission: '5' },
|
|
135
|
+
),
|
|
136
|
+
).toEqual({ id: '101', comission: 15, minimum_comission: 5 });
|
|
137
|
+
expect(buildCommissionSavePayload({}, { comission: 1, minimumComission: 0 })).toBe(
|
|
138
|
+
null,
|
|
139
|
+
);
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
});
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for SalesmanTab commission helpers (override precedence + permissions).
|
|
3
|
+
* Node native test runner.
|
|
4
|
+
*/
|
|
5
|
+
import assert from 'node:assert/strict';
|
|
6
|
+
import { describe, it } from 'node:test';
|
|
7
|
+
import {
|
|
8
|
+
isCommissionFilled,
|
|
9
|
+
toCommissionNumber,
|
|
10
|
+
resolveEffectiveCommission,
|
|
11
|
+
canEditSalesmanCommission,
|
|
12
|
+
shouldDisplayCommission,
|
|
13
|
+
buildCommissionSavePayload,
|
|
14
|
+
} from '../../../../react/components/tabs/salesmanTabHelpers.js';
|
|
15
|
+
|
|
16
|
+
describe('salesmanTabHelpers', () => {
|
|
17
|
+
describe('isCommissionFilled / toCommissionNumber', () => {
|
|
18
|
+
it('treats null/undefined/empty as not filled', () => {
|
|
19
|
+
assert.equal(isCommissionFilled(null), false);
|
|
20
|
+
assert.equal(isCommissionFilled(undefined), false);
|
|
21
|
+
assert.equal(isCommissionFilled(''), false);
|
|
22
|
+
assert.equal(isCommissionFilled(' '), false);
|
|
23
|
+
assert.equal(toCommissionNumber(null), null);
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('treats 0 as filled', () => {
|
|
27
|
+
assert.equal(isCommissionFilled(0), true);
|
|
28
|
+
assert.equal(toCommissionNumber(0), 0);
|
|
29
|
+
assert.equal(toCommissionNumber('12.5'), 12.5);
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
describe('resolveEffectiveCommission', () => {
|
|
34
|
+
it('prefers client override when filled', () => {
|
|
35
|
+
const result = resolveEffectiveCommission(
|
|
36
|
+
{ comission: 10, minimum_comission: 5 },
|
|
37
|
+
{ comission: 20, minimum_comission: 8 },
|
|
38
|
+
);
|
|
39
|
+
assert.equal(result.comission, 10);
|
|
40
|
+
assert.equal(result.minimumComission, 5);
|
|
41
|
+
assert.equal(result.isOverride, true);
|
|
42
|
+
assert.equal(result.source, 'client');
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('falls back to default when client empty', () => {
|
|
46
|
+
const result = resolveEffectiveCommission(
|
|
47
|
+
{ comission: null, minimum_comission: null },
|
|
48
|
+
{ comission: 15, minimum_comission: 3 },
|
|
49
|
+
);
|
|
50
|
+
assert.equal(result.comission, 15);
|
|
51
|
+
assert.equal(result.minimumComission, 3);
|
|
52
|
+
assert.equal(result.isOverride, false);
|
|
53
|
+
assert.equal(result.source, 'default');
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
describe('canEditSalesmanCommission', () => {
|
|
58
|
+
it('allows ROLE_SUPER and ROLE_OWNER', () => {
|
|
59
|
+
assert.equal(canEditSalesmanCommission({ roles: ['ROLE_SUPER'] }), true);
|
|
60
|
+
assert.equal(canEditSalesmanCommission({ roles: ['ROLE_OWNER'] }), true);
|
|
61
|
+
assert.equal(canEditSalesmanCommission({ roles: ['ROLE_ADMIN'] }), false);
|
|
62
|
+
assert.equal(
|
|
63
|
+
canEditSalesmanCommission(
|
|
64
|
+
{ roles: ['ROLE_ADMIN'] },
|
|
65
|
+
{ user: { owner_enabled: true } },
|
|
66
|
+
),
|
|
67
|
+
true,
|
|
68
|
+
);
|
|
69
|
+
assert.equal(canEditSalesmanCommission({}), false);
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
describe('shouldDisplayCommission', () => {
|
|
74
|
+
it('shows for MANAGER and ADMIN only', () => {
|
|
75
|
+
assert.equal(shouldDisplayCommission('MANAGER'), true);
|
|
76
|
+
assert.equal(shouldDisplayCommission('ADMIN'), true);
|
|
77
|
+
assert.equal(shouldDisplayCommission('CRM'), false);
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
describe('buildCommissionSavePayload', () => {
|
|
82
|
+
it('builds numeric payload with link id', () => {
|
|
83
|
+
const payload = buildCommissionSavePayload(
|
|
84
|
+
{ id: 42 },
|
|
85
|
+
{ comission: '12.5', minimumComission: '1' },
|
|
86
|
+
);
|
|
87
|
+
assert.equal(payload.id, '42');
|
|
88
|
+
assert.equal(payload.comission, 12.5);
|
|
89
|
+
assert.equal(payload.minimum_comission, 1);
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
});
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
const {
|
|
2
|
+
extractId,
|
|
3
|
+
toPeopleIri,
|
|
4
|
+
normalizeUserItem,
|
|
5
|
+
toTimezoneIri,
|
|
6
|
+
toTimezoneItem,
|
|
7
|
+
extractCollectionItems,
|
|
8
|
+
extractErrorMessage,
|
|
9
|
+
} = require('../../../../react/components/tabs/usersTabHelpers');
|
|
10
|
+
|
|
11
|
+
describe('usersTabHelpers', () => {
|
|
12
|
+
test('extractId strips non-digits', () => {
|
|
13
|
+
expect(extractId('/timezones/42')).toBe('42');
|
|
14
|
+
expect(extractId(7)).toBe('7');
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
test('toTimezoneIri builds IRI', () => {
|
|
18
|
+
expect(toTimezoneIri(3)).toBe('/timezones/3');
|
|
19
|
+
expect(toTimezoneIri('/timezones/9')).toBe('/timezones/9');
|
|
20
|
+
expect(toTimezoneIri('')).toBe(null);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
test('toPeopleIri builds API Platform IRI', () => {
|
|
24
|
+
expect(toPeopleIri(106218)).toBe('/people/106218');
|
|
25
|
+
expect(toPeopleIri('/people/9')).toBe('/people/9');
|
|
26
|
+
expect(toPeopleIri('')).toBe('');
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test('extractErrorMessage maps Authentication required', () => {
|
|
30
|
+
expect(extractErrorMessage({message: 'Authentication required'})).toMatch(/Autenticação necessária/);
|
|
31
|
+
expect(
|
|
32
|
+
extractErrorMessage({response: {status: 401, data: {message: 'Authentication required'}}}),
|
|
33
|
+
).toMatch(/Autenticação necessária/);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
test('toTimezoneItem maps entry', () => {
|
|
37
|
+
expect(toTimezoneItem({id: 1, name: 'America/Sao_Paulo'})).toEqual({
|
|
38
|
+
id: '1',
|
|
39
|
+
name: 'America/Sao_Paulo',
|
|
40
|
+
displayName: 'America/Sao_Paulo',
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
test('normalizeUserItem keeps timezoneId', () => {
|
|
45
|
+
const item = normalizeUserItem({
|
|
46
|
+
id: 10,
|
|
47
|
+
username: 'alice',
|
|
48
|
+
timezone: '/timezones/5',
|
|
49
|
+
});
|
|
50
|
+
expect(item.timezoneId).toBe('5');
|
|
51
|
+
expect(item.username).toBe('alice');
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test('extractCollectionItems supports hydra and member', () => {
|
|
55
|
+
expect(extractCollectionItems({'hydra:member': [{id: 1}]}).length).toBe(1);
|
|
56
|
+
expect(extractCollectionItems({member: [{id: 2}]}).length).toBe(1);
|
|
57
|
+
expect(extractCollectionItems([{id: 3}]).length).toBe(1);
|
|
58
|
+
});
|
|
59
|
+
});
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
buildCreateProductParams,
|
|
6
|
+
buildInitialProviderPayload,
|
|
7
|
+
extractId,
|
|
8
|
+
} from '../../../react/domain/productSupplierFlow.js';
|
|
9
|
+
|
|
10
|
+
test('extractId normalizes numeric ids and hydra ids', () => {
|
|
11
|
+
assert.equal(extractId(42), '42');
|
|
12
|
+
assert.equal(extractId('/people/17'), '17');
|
|
13
|
+
assert.equal(extractId({ '@id': '/people/81' }), '81');
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
test('buildInitialProviderPayload keeps provider identity when only id is available', () => {
|
|
17
|
+
const payload = buildInitialProviderPayload({
|
|
18
|
+
id: 15,
|
|
19
|
+
alias: 'Fornecedor XPTO',
|
|
20
|
+
name: 'Fornecedor XPTO LTDA',
|
|
21
|
+
peopleType: 'provider',
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
assert.deepEqual(payload, {
|
|
25
|
+
id: '15',
|
|
26
|
+
'@id': '/people/15',
|
|
27
|
+
alias: 'Fornecedor XPTO',
|
|
28
|
+
name: 'Fornecedor XPTO LTDA',
|
|
29
|
+
peopleType: 'provider',
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
test('buildCreateProductParams returns null when provider has no valid id', () => {
|
|
34
|
+
assert.equal(buildCreateProductParams({ alias: 'Sem id' }), null);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
test('buildCreateProductParams forwards supplier context to ProductDetails', () => {
|
|
38
|
+
const params = buildCreateProductParams({
|
|
39
|
+
'@id': '/people/33',
|
|
40
|
+
alias: 'Fornecedor Central',
|
|
41
|
+
name: 'Fornecedor Central SA',
|
|
42
|
+
peopleType: 'provider',
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
assert.deepEqual(params, {
|
|
46
|
+
context: 'products',
|
|
47
|
+
initialProvider: {
|
|
48
|
+
id: '33',
|
|
49
|
+
'@id': '/people/33',
|
|
50
|
+
alias: 'Fornecedor Central',
|
|
51
|
+
name: 'Fornecedor Central SA',
|
|
52
|
+
peopleType: 'provider',
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
});
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unit tests for ClientDetails pure helpers (app-community#297 modularization).
|
|
3
|
+
*/
|
|
4
|
+
import {
|
|
5
|
+
resolveContextKey,
|
|
6
|
+
normalizeCollection,
|
|
7
|
+
buildClientTabDefs,
|
|
8
|
+
resolveInitialTabIndex,
|
|
9
|
+
extractId,
|
|
10
|
+
resolveRouteClientId,
|
|
11
|
+
resolveRouteClientSeed,
|
|
12
|
+
} from '../../../react/pages/clientDetailsHelpers';
|
|
13
|
+
|
|
14
|
+
describe('clientDetailsHelpers', () => {
|
|
15
|
+
it('resolveContextKey normalizes string and object context', () => {
|
|
16
|
+
expect(resolveContextKey(' Provider ')).toBe('provider');
|
|
17
|
+
expect(resolveContextKey({ context: 'Contacts' })).toBe('contacts');
|
|
18
|
+
expect(resolveContextKey(null)).toBe('');
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it('normalizeCollection handles hydra and plain arrays', () => {
|
|
22
|
+
expect(normalizeCollection([{ id: 1 }])).toEqual([{ id: 1 }]);
|
|
23
|
+
expect(normalizeCollection({ 'hydra:member': [{ id: 2 }] })).toEqual([{ id: 2 }]);
|
|
24
|
+
expect(normalizeCollection(null)).toEqual([]);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('extractId strips non-digits', () => {
|
|
28
|
+
expect(extractId('/people/42')).toBe('42');
|
|
29
|
+
expect(extractId(7)).toBe('7');
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('resolves client id and seed from CRM navigation params', () => {
|
|
33
|
+
const client = {
|
|
34
|
+
'@id': '/people/9',
|
|
35
|
+
id: 9,
|
|
36
|
+
name: 'Cliente Teste',
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
expect(resolveRouteClientSeed({ client })).toBe(client);
|
|
40
|
+
expect(resolveRouteClientId({ client })).toBe('9');
|
|
41
|
+
expect(resolveRouteClientId({ clientId: '11', client })).toBe('11');
|
|
42
|
+
expect(resolveRouteClientId({ companyId: '12', client })).toBe('12');
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('buildClientTabDefs includes media and contacts for PJ', () => {
|
|
46
|
+
const tabs = buildClientTabDefs({
|
|
47
|
+
isPessoaJuridica: true,
|
|
48
|
+
isProviderContext: false,
|
|
49
|
+
t: { t: (_ns, _k, key) => key },
|
|
50
|
+
});
|
|
51
|
+
expect(tabs.map(t => t.key)).toEqual([
|
|
52
|
+
'general',
|
|
53
|
+
'media',
|
|
54
|
+
'sellers',
|
|
55
|
+
'contacts',
|
|
56
|
+
'contracts',
|
|
57
|
+
]);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('does not expose Categories for a person or resolve it by deep link', () => {
|
|
61
|
+
const tabs = buildClientTabDefs({
|
|
62
|
+
isPessoaJuridica: false,
|
|
63
|
+
isProviderContext: false,
|
|
64
|
+
t: { t: (_ns, _k, key) => key },
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
expect(tabs.map(t => t.key)).toEqual([
|
|
68
|
+
'general',
|
|
69
|
+
'media',
|
|
70
|
+
'users',
|
|
71
|
+
'contracts',
|
|
72
|
+
]);
|
|
73
|
+
expect(
|
|
74
|
+
resolveInitialTabIndex({
|
|
75
|
+
requestedInitialTab: 'categories',
|
|
76
|
+
nextClient: { peopleType: 'F' },
|
|
77
|
+
detailContext: 'employee',
|
|
78
|
+
}),
|
|
79
|
+
).toBe(0);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('resolveInitialTabIndex respects requested tab and defaults to 0', () => {
|
|
83
|
+
expect(
|
|
84
|
+
resolveInitialTabIndex({
|
|
85
|
+
requestedInitialTab: 'media',
|
|
86
|
+
nextClient: { peopleType: 'J' },
|
|
87
|
+
detailContext: '',
|
|
88
|
+
}),
|
|
89
|
+
).toBe(1);
|
|
90
|
+
expect(
|
|
91
|
+
resolveInitialTabIndex({
|
|
92
|
+
requestedInitialTab: '',
|
|
93
|
+
nextClient: { peopleType: 'F' },
|
|
94
|
+
detailContext: '',
|
|
95
|
+
}),
|
|
96
|
+
).toBe(0);
|
|
97
|
+
});
|
|
98
|
+
});
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/* global jest */
|
|
2
|
+
|
|
3
|
+
const {describe, expect, it, beforeEach, afterEach} = global
|
|
4
|
+
|
|
5
|
+
jest.mock('@controleonline/ui-people/src/react/pages/People', () => 'People')
|
|
6
|
+
|
|
7
|
+
const {
|
|
8
|
+
buildEmployeesContext,
|
|
9
|
+
} = require('../../../react/pages/employees')
|
|
10
|
+
|
|
11
|
+
describe('employees page context', () => {
|
|
12
|
+
const originalTranslator = global.t
|
|
13
|
+
|
|
14
|
+
beforeEach(() => {
|
|
15
|
+
global.t = {
|
|
16
|
+
t: (scope, group, key) => `${scope}.${group}.${key}`,
|
|
17
|
+
}
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
afterEach(() => {
|
|
21
|
+
global.t = originalTranslator
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
it('exposes courier alongside the default employee roles', () => {
|
|
25
|
+
const context = buildEmployeesContext({})
|
|
26
|
+
|
|
27
|
+
expect(context.context).toEqual(['all', 'employee', 'owner', 'courier'])
|
|
28
|
+
expect(context.defaultContext).toBe('all')
|
|
29
|
+
expect(context.selectedContext).toBe('all')
|
|
30
|
+
expect(context.defaultPeopleType).toBe('J')
|
|
31
|
+
expect(context.modalTitleByType.courier).toBe('Cadastro de Entregador')
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
it('keeps courier as the default physical-person role when selected directly', () => {
|
|
35
|
+
const context = buildEmployeesContext({
|
|
36
|
+
selectedContext: 'courier',
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
expect(context.context).toEqual(['courier'])
|
|
40
|
+
expect(context.defaultContext).toBe('courier')
|
|
41
|
+
expect(context.selectedContext).toBe('courier')
|
|
42
|
+
expect(context.defaultPeopleType).toBe('F')
|
|
43
|
+
})
|
|
44
|
+
})
|