@velocitycareerlabs/velocity-registrar-app 1.26.0-dev-build.1f18e8395 → 1.26.0-dev-build.19f1147f8
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/babel.config.js +3 -0
- package/jest.config.js +29 -0
- package/package.json +8 -4
- package/src/pages/services/components/SecureIntegrationPopup/tests/SecureIntegrationPopup.test.jsx +84 -0
- package/src/pages/services/components/SecureMessageUrl/tests/SecureMessageURL.test.jsx +231 -0
- package/src/pages/services/components/SecureTransfer/index.jsx +1 -1
- package/src/pages/services/components/SecureTransfer/tests/SecureTransfer.test.jsx +127 -0
- package/src/pages/services/hooks/useAdditionalServiceProperties.js +1 -1
- package/src/pages/services/utils/index.jsx +1 -1
- package/src/pages/services/utils/tests/optionalUrlValidation.test.js +26 -0
- package/src/setupTests.js +32 -0
package/babel.config.js
ADDED
package/jest.config.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
const pack = require('./package.json');
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
testEnvironment: 'jsdom',
|
|
5
|
+
transform: {
|
|
6
|
+
'^.+\\.(js|jsx)$': 'babel-jest',
|
|
7
|
+
},
|
|
8
|
+
moduleNameMapper: {
|
|
9
|
+
'\\.(css|less|scss|sass)$': 'identity-obj-proxy',
|
|
10
|
+
},
|
|
11
|
+
setupFilesAfterEnv: ['./src/setupTests.js'],
|
|
12
|
+
testPathIgnorePatterns: ['/node_modules/', '/dist/'],
|
|
13
|
+
moduleFileExtensions: ['js', 'jsx', 'json', 'node'],
|
|
14
|
+
displayName: pack.name,
|
|
15
|
+
reporters: [
|
|
16
|
+
'default',
|
|
17
|
+
[
|
|
18
|
+
'jest-junit',
|
|
19
|
+
{
|
|
20
|
+
outputName: `${pack.name.split('/')[1]}-junit.xml`,
|
|
21
|
+
outputDirectory: '<rootDir>/../../test-results',
|
|
22
|
+
ancestorSeparator: ' › ',
|
|
23
|
+
suiteNameTemplate: '{filepath}',
|
|
24
|
+
classNameTemplate: '{classname}',
|
|
25
|
+
titleTemplate: '{title}',
|
|
26
|
+
},
|
|
27
|
+
],
|
|
28
|
+
],
|
|
29
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@velocitycareerlabs/velocity-registrar-app",
|
|
3
|
-
"version": "1.26.0-dev-build.
|
|
3
|
+
"version": "1.26.0-dev-build.19f1147f8",
|
|
4
4
|
"description": "Velocity Registrar",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"publishConfig": {
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"@mui/icons-material": "^6.0.0",
|
|
15
15
|
"@mui/material": "^6.0.0",
|
|
16
16
|
"@react-pdf/renderer": "^3.0.0",
|
|
17
|
-
"@velocitycareerlabs/components-organizations-registrar": "2.0.0-pre.
|
|
17
|
+
"@velocitycareerlabs/components-organizations-registrar": "2.0.0-pre.1750748342",
|
|
18
18
|
"autosuggest-highlight": "^3.3.4",
|
|
19
19
|
"classnames": "~2.5.0",
|
|
20
20
|
"env-cmd": "^10.1.0",
|
|
@@ -30,6 +30,8 @@
|
|
|
30
30
|
"react-router": "7.5.3"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
|
+
"@testing-library/jest-dom": "6.6.3",
|
|
34
|
+
"@testing-library/react": "16.2.0",
|
|
33
35
|
"@vitejs/plugin-react-swc": "3.10.2",
|
|
34
36
|
"eslint": "8.57.1",
|
|
35
37
|
"eslint-config-airbnb-base": "14.2.1",
|
|
@@ -41,6 +43,7 @@
|
|
|
41
43
|
"eslint-plugin-prettier": "4.2.1",
|
|
42
44
|
"eslint-plugin-react": "7.37.5",
|
|
43
45
|
"eslint-plugin-react-hooks": "4.6.2",
|
|
46
|
+
"jest-environment-jsdom": "29.7.0",
|
|
44
47
|
"postcss-normalize": "13.0.1",
|
|
45
48
|
"vite": "6.3.5"
|
|
46
49
|
},
|
|
@@ -51,7 +54,8 @@
|
|
|
51
54
|
"build": "vite build",
|
|
52
55
|
"preview": "vite preview",
|
|
53
56
|
"lint": "eslint src --format json >> eslint.json",
|
|
54
|
-
"lint:fix": "eslint src --fix"
|
|
57
|
+
"lint:fix": "eslint src --fix",
|
|
58
|
+
"test": "jest --config ./jest.config.js --runInBand --coverage"
|
|
55
59
|
},
|
|
56
60
|
"browserslist": [
|
|
57
61
|
">0.2%",
|
|
@@ -59,5 +63,5 @@
|
|
|
59
63
|
"not ie <= 11",
|
|
60
64
|
"not op_mini all"
|
|
61
65
|
],
|
|
62
|
-
"gitHead": "
|
|
66
|
+
"gitHead": "24b6b242448d219645f7563e2016e91432111939"
|
|
63
67
|
}
|
package/src/pages/services/components/SecureIntegrationPopup/tests/SecureIntegrationPopup.test.jsx
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import '@testing-library/jest-dom';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { render, screen } from '@testing-library/react';
|
|
4
|
+
import { SecureIntegrationPopup } from '../index.jsx';
|
|
5
|
+
import * as useSecureSkipHook from '../../../hooks/useSecureSkip';
|
|
6
|
+
// import * as orgContext from '@velocitycareerlabs/components-organizations-registrar';
|
|
7
|
+
|
|
8
|
+
jest.mock('../../SecureMessageUrl/index.jsx', () => ({
|
|
9
|
+
SecureMessageURL: () => <div>SecureMessageURL component</div>,
|
|
10
|
+
}));
|
|
11
|
+
jest.mock('../../SecureTransfer/index.jsx', () => ({
|
|
12
|
+
SecureTransfer: () => <div>SecureTransfer component</div>,
|
|
13
|
+
}));
|
|
14
|
+
|
|
15
|
+
jest.mock('@velocitycareerlabs/components-organizations-registrar', () => ({
|
|
16
|
+
useSelectedOrganization: jest.fn(() => ['did:test']),
|
|
17
|
+
}));
|
|
18
|
+
jest.mock('@velocitycareerlabs/components-organizations-registrar/components', () => ({
|
|
19
|
+
Loading: () => <div>Loading...</div>,
|
|
20
|
+
}));
|
|
21
|
+
jest.mock('@velocitycareerlabs/components-organizations-registrar/components/common', () => ({
|
|
22
|
+
// eslint-disable-next-line react/prop-types
|
|
23
|
+
Popup: ({ children }) => <div>{children}</div>,
|
|
24
|
+
}));
|
|
25
|
+
|
|
26
|
+
describe('SecureIntegrationPopup', () => {
|
|
27
|
+
beforeEach(() => {
|
|
28
|
+
jest.clearAllMocks();
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('renders Loader when isLoading and isIssueOrInspection are true', () => {
|
|
32
|
+
jest.spyOn(useSecureSkipHook, 'useSecureSkip').mockReturnValue({ isLoading: true });
|
|
33
|
+
|
|
34
|
+
render(
|
|
35
|
+
<SecureIntegrationPopup
|
|
36
|
+
isInterceptOnCreateOpen={true}
|
|
37
|
+
serviceId="service-id"
|
|
38
|
+
onNext={jest.fn()}
|
|
39
|
+
onClose={jest.fn()}
|
|
40
|
+
isIssueOrInspection={true}
|
|
41
|
+
selectedCAO="test"
|
|
42
|
+
isCAO={false}
|
|
43
|
+
/>,
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
expect(screen.getByText('Loading...')).toBeInTheDocument();
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('renders SecureTransfer if isIssueOrInspection is true and not loading', () => {
|
|
50
|
+
jest.spyOn(useSecureSkipHook, 'useSecureSkip').mockReturnValue({ isLoading: false });
|
|
51
|
+
|
|
52
|
+
render(
|
|
53
|
+
<SecureIntegrationPopup
|
|
54
|
+
isInterceptOnCreateOpen={true}
|
|
55
|
+
serviceId="service-id"
|
|
56
|
+
onNext={jest.fn()}
|
|
57
|
+
onClose={jest.fn()}
|
|
58
|
+
isIssueOrInspection={true}
|
|
59
|
+
selectedCAO="test"
|
|
60
|
+
isCAO={false}
|
|
61
|
+
/>,
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
expect(screen.getByText('SecureTransfer component')).toBeInTheDocument();
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it('renders SecureMessageURL if isIssueOrInspection is false', () => {
|
|
68
|
+
jest.spyOn(useSecureSkipHook, 'useSecureSkip').mockReturnValue({ isLoading: false });
|
|
69
|
+
|
|
70
|
+
render(
|
|
71
|
+
<SecureIntegrationPopup
|
|
72
|
+
isInterceptOnCreateOpen={true}
|
|
73
|
+
serviceId="service-id"
|
|
74
|
+
onNext={jest.fn()}
|
|
75
|
+
onClose={jest.fn()}
|
|
76
|
+
isIssueOrInspection={false}
|
|
77
|
+
selectedCAO={null}
|
|
78
|
+
isCAO={true}
|
|
79
|
+
/>,
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
expect(screen.getByText('SecureMessageURL component')).toBeInTheDocument();
|
|
83
|
+
});
|
|
84
|
+
});
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
import '@testing-library/jest-dom';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
|
|
4
|
+
|
|
5
|
+
import { MemoryRouter } from 'react-router';
|
|
6
|
+
import { SecureMessageURL } from '../index.jsx';
|
|
7
|
+
import * as hook from '../../../hooks/useSecureMessageTest';
|
|
8
|
+
|
|
9
|
+
jest.mock('@mui/material', () => {
|
|
10
|
+
const original = jest.requireActual('@mui/material');
|
|
11
|
+
return {
|
|
12
|
+
...original,
|
|
13
|
+
// eslint-disable-next-line react/prop-types
|
|
14
|
+
Button: ({ children, endIcon, startIcon, disabled, ...props }) => (
|
|
15
|
+
<button disabled={disabled} {...props}>
|
|
16
|
+
{children}
|
|
17
|
+
</button>
|
|
18
|
+
),
|
|
19
|
+
};
|
|
20
|
+
});
|
|
21
|
+
jest.mock('@velocitycareerlabs/components-organizations-registrar/components', () => ({
|
|
22
|
+
Loading: () => <div>Loading...</div>,
|
|
23
|
+
}));
|
|
24
|
+
|
|
25
|
+
jest.mock('@velocitycareerlabs/components-organizations-registrar/components/common', () => ({
|
|
26
|
+
// eslint-disable-next-line react/prop-types
|
|
27
|
+
Popup: ({ children }) => <div>{children}</div>,
|
|
28
|
+
Save: () => <button>Save</button>,
|
|
29
|
+
}));
|
|
30
|
+
|
|
31
|
+
jest.mock('react-admin', () => ({
|
|
32
|
+
...jest.requireActual('react-admin'),
|
|
33
|
+
useGetOne: jest.fn(() => ({
|
|
34
|
+
data: { secureMessagesUrl: 'https://example.com' },
|
|
35
|
+
isLoading: false,
|
|
36
|
+
})),
|
|
37
|
+
}));
|
|
38
|
+
|
|
39
|
+
jest.mock('../../../hooks/useSecureMessageTest');
|
|
40
|
+
|
|
41
|
+
describe('SecureMessageURL', () => {
|
|
42
|
+
beforeEach(() => {
|
|
43
|
+
jest.clearAllMocks();
|
|
44
|
+
hook.useSecureMessageTest.mockReturnValue({
|
|
45
|
+
onTest: jest.fn(),
|
|
46
|
+
testPassed: false,
|
|
47
|
+
testError: false,
|
|
48
|
+
testInProgress: false,
|
|
49
|
+
tested: false,
|
|
50
|
+
reset: jest.fn(),
|
|
51
|
+
onSave: jest.fn(),
|
|
52
|
+
saveInProgress: false,
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
const mockUseGetOne = require('react-admin').useGetOne;
|
|
57
|
+
const onSaveMock = jest.fn();
|
|
58
|
+
const onSkipMock = jest.fn();
|
|
59
|
+
|
|
60
|
+
it('renders secure message input field', () => {
|
|
61
|
+
mockUseGetOne.mockReturnValue({
|
|
62
|
+
data: { secureMessagesUrl: '' },
|
|
63
|
+
isLoading: false,
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
render(<SecureMessageURL did="test-did" onSave={onSaveMock} onSkip={onSkipMock} />, {
|
|
67
|
+
wrapper: MemoryRouter,
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
// Title and description
|
|
71
|
+
expect(screen.getByText(/Set a Secure Messages URL/i)).toBeInTheDocument();
|
|
72
|
+
expect(
|
|
73
|
+
screen.getByText(
|
|
74
|
+
// eslint-disable-next-line max-len
|
|
75
|
+
/Ease your client's efforts by using a Secure Messages endpoint at which a Credential Agent Operator. The Secure Messages endpoint is used to securely receive clients. Ensure that the webhook is active and responding before setting this value otherwise the profile cannot be saved./i,
|
|
76
|
+
),
|
|
77
|
+
).toBeInTheDocument();
|
|
78
|
+
expect(
|
|
79
|
+
screen.getByText(
|
|
80
|
+
/Note: This value is shared by all Credential Agent Services and updating it will affect them all/i,
|
|
81
|
+
),
|
|
82
|
+
).toBeInTheDocument();
|
|
83
|
+
|
|
84
|
+
// Input field
|
|
85
|
+
const input = screen.getByLabelText(/Secure message URL/i);
|
|
86
|
+
expect(input).toBeInTheDocument();
|
|
87
|
+
expect(input).toHaveValue('');
|
|
88
|
+
|
|
89
|
+
// Buttons
|
|
90
|
+
expect(screen.getAllByRole('button', { name: /test/i })).toHaveLength(2);
|
|
91
|
+
expect(screen.getAllByRole('button', { name: /skip/i })).toHaveLength(1);
|
|
92
|
+
expect(screen.getAllByRole('button', { name: /save/i })).toHaveLength(1);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it('shows saved secureMessagesUrl if available', () => {
|
|
96
|
+
mockUseGetOne.mockReturnValue({
|
|
97
|
+
data: { secureMessagesUrl: 'https://example.com' },
|
|
98
|
+
isLoading: false,
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
render(<SecureMessageURL did="test-did" onSave={onSaveMock} onSkip={onSkipMock} />, {
|
|
102
|
+
wrapper: MemoryRouter,
|
|
103
|
+
});
|
|
104
|
+
const input = screen.getByLabelText(/Secure message URL/i);
|
|
105
|
+
expect(input).toHaveValue('https://example.com');
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it('can test secure message URL', async () => {
|
|
109
|
+
mockUseGetOne.mockReturnValue({
|
|
110
|
+
data: { secureMessagesUrl: '' },
|
|
111
|
+
isLoading: false,
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
render(<SecureMessageURL did="test-did" onSave={onSaveMock} onSkip={onSkipMock} />, {
|
|
115
|
+
wrapper: MemoryRouter,
|
|
116
|
+
});
|
|
117
|
+
const input = screen.getByLabelText(/Secure message URL/i);
|
|
118
|
+
expect(input).toHaveValue('');
|
|
119
|
+
|
|
120
|
+
fireEvent.change(input, { target: { value: 'https://new-url.com' } });
|
|
121
|
+
await waitFor(() => {
|
|
122
|
+
expect(input).toHaveValue('https://new-url.com');
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
const testBtn = screen.getAllByRole('button', { name: /test/i });
|
|
126
|
+
fireEvent.click(testBtn[0]);
|
|
127
|
+
await waitFor(() => {
|
|
128
|
+
expect(hook.useSecureMessageTest().onTest).toHaveBeenCalledWith('https://new-url.com');
|
|
129
|
+
});
|
|
130
|
+
});
|
|
131
|
+
it('shows status on Test success', async () => {
|
|
132
|
+
mockUseGetOne.mockReturnValue({
|
|
133
|
+
data: { secureMessagesUrl: 'https://example.com' },
|
|
134
|
+
isLoading: false,
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
hook.useSecureMessageTest.mockReturnValue({
|
|
138
|
+
onTest: jest.fn(),
|
|
139
|
+
testPassed: true,
|
|
140
|
+
testError: false,
|
|
141
|
+
testInProgress: false,
|
|
142
|
+
tested: true,
|
|
143
|
+
reset: jest.fn(),
|
|
144
|
+
onSave: jest.fn(),
|
|
145
|
+
saveInProgress: false,
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
render(<SecureMessageURL did="test-did" onSave={onSaveMock} onSkip={onSkipMock} />, {
|
|
149
|
+
wrapper: MemoryRouter,
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
const testBtn = screen.getAllByRole('button', { name: /test/i });
|
|
153
|
+
fireEvent.click(testBtn[0]);
|
|
154
|
+
await waitFor(() => {
|
|
155
|
+
expect(screen.getByText(/Secure message URL tested successfully!/i)).toBeInTheDocument();
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
it('shows status on Test failes', async () => {
|
|
160
|
+
mockUseGetOne.mockReturnValue({
|
|
161
|
+
data: { secureMessagesUrl: 'https://example.com' },
|
|
162
|
+
isLoading: false,
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
hook.useSecureMessageTest.mockReturnValue({
|
|
166
|
+
onTest: jest.fn(),
|
|
167
|
+
testPassed: false,
|
|
168
|
+
testError: true,
|
|
169
|
+
testInProgress: false,
|
|
170
|
+
tested: true,
|
|
171
|
+
reset: jest.fn(),
|
|
172
|
+
onSave: jest.fn(),
|
|
173
|
+
saveInProgress: false,
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
render(<SecureMessageURL did="test-did" onSave={onSaveMock} onSkip={onSkipMock} />, {
|
|
177
|
+
wrapper: MemoryRouter,
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
const testBtn = screen.getAllByRole('button', { name: /test/i });
|
|
181
|
+
fireEvent.click(testBtn[0]);
|
|
182
|
+
await waitFor(() => {
|
|
183
|
+
expect(screen.getByText(/Failed to test the secure message URL./i)).toBeInTheDocument();
|
|
184
|
+
});
|
|
185
|
+
});
|
|
186
|
+
it('shows warning popup if not tested and Save is clicked', async () => {
|
|
187
|
+
mockUseGetOne.mockReturnValue({
|
|
188
|
+
data: { secureMessagesUrl: 'https://example.com' },
|
|
189
|
+
isLoading: false,
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
hook.useSecureMessageTest.mockReturnValue({
|
|
193
|
+
onTest: jest.fn(),
|
|
194
|
+
testPassed: false,
|
|
195
|
+
testError: false,
|
|
196
|
+
testInProgress: false,
|
|
197
|
+
tested: false,
|
|
198
|
+
reset: jest.fn(),
|
|
199
|
+
onSave: jest.fn(),
|
|
200
|
+
saveInProgress: false,
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
render(<SecureMessageURL did="test-did" onSave={onSaveMock} onSkip={onSkipMock} />, {
|
|
204
|
+
wrapper: MemoryRouter,
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
const saveBtn = screen.getAllByRole('button', { name: /save/i });
|
|
208
|
+
fireEvent.click(saveBtn[0]);
|
|
209
|
+
|
|
210
|
+
await waitFor(() => {
|
|
211
|
+
expect(
|
|
212
|
+
screen.getByText(/Secure message URL should be tested before saving/i),
|
|
213
|
+
).toBeInTheDocument();
|
|
214
|
+
expect(
|
|
215
|
+
screen.getByText(
|
|
216
|
+
/They will not be available again and are critical for managing your organization data./i,
|
|
217
|
+
),
|
|
218
|
+
).toBeInTheDocument();
|
|
219
|
+
expect(screen.getByText(/Back to test/i)).toBeInTheDocument();
|
|
220
|
+
});
|
|
221
|
+
const continueBtn = screen.getByText(/Continue anyway/i);
|
|
222
|
+
expect(continueBtn).toBeInTheDocument();
|
|
223
|
+
fireEvent.click(continueBtn);
|
|
224
|
+
await waitFor(() => {
|
|
225
|
+
expect(hook.useSecureMessageTest().onSave).toHaveBeenCalledWith(
|
|
226
|
+
'https://example.com',
|
|
227
|
+
expect.any(Function),
|
|
228
|
+
);
|
|
229
|
+
});
|
|
230
|
+
});
|
|
231
|
+
});
|
|
@@ -30,7 +30,7 @@ export const SecureTransfer = ({ did, serviceId, onClose }) => {
|
|
|
30
30
|
{ returnPromise: true },
|
|
31
31
|
);
|
|
32
32
|
if (result.messageCode === MESSAGE_CODES.keys_sent) {
|
|
33
|
-
notify('
|
|
33
|
+
notify('Succeeded', { type: 'success' }, { autoHideDuration: 500 });
|
|
34
34
|
onClose(true);
|
|
35
35
|
} else {
|
|
36
36
|
notify('Error transferring keys', { type: 'warning' }, { autoHideDuration: 500 });
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/* eslint-disable react/prop-types */
|
|
2
|
+
import '@testing-library/jest-dom';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
|
|
5
|
+
import * as reactAdmin from 'react-admin';
|
|
6
|
+
|
|
7
|
+
import { MemoryRouter } from 'react-router';
|
|
8
|
+
import { SecureTransfer } from '../index.jsx';
|
|
9
|
+
|
|
10
|
+
jest.mock('@mui/material', () => {
|
|
11
|
+
const original = jest.requireActual('@mui/material');
|
|
12
|
+
return {
|
|
13
|
+
...original,
|
|
14
|
+
Button: ({ children, endIcon, startIcon, disabled, ...props }) => (
|
|
15
|
+
<button disabled={disabled} {...props}>
|
|
16
|
+
{children}
|
|
17
|
+
</button>
|
|
18
|
+
),
|
|
19
|
+
};
|
|
20
|
+
});
|
|
21
|
+
jest.mock('@velocitycareerlabs/components-organizations-registrar/components', () => ({
|
|
22
|
+
Loading: () => <div>Loading...</div>,
|
|
23
|
+
}));
|
|
24
|
+
|
|
25
|
+
jest.mock('@velocitycareerlabs/components-organizations-registrar/components/common', () => ({
|
|
26
|
+
Popup: ({ children }) => <div>{children}</div>,
|
|
27
|
+
Save: ({ disabled }) => (
|
|
28
|
+
<button disabled={disabled} type="submit">
|
|
29
|
+
Save
|
|
30
|
+
</button>
|
|
31
|
+
),
|
|
32
|
+
CustomBooleanInput: ({ value = false, onChange = () => {}, label }) => (
|
|
33
|
+
<label>
|
|
34
|
+
<input type="checkbox" checked={value} onChange={(e) => onChange(e.target.checked)} />
|
|
35
|
+
{label}
|
|
36
|
+
</label>
|
|
37
|
+
),
|
|
38
|
+
}));
|
|
39
|
+
|
|
40
|
+
jest.mock('react-admin', () => {
|
|
41
|
+
const transferKeysMock = jest.fn().mockResolvedValue({ messageCode: 'keys_sent' });
|
|
42
|
+
const { useForm, FormProvider } = require('react-hook-form');
|
|
43
|
+
return {
|
|
44
|
+
...jest.requireActual('react-admin'),
|
|
45
|
+
useCreate: jest.fn(() => [transferKeysMock]),
|
|
46
|
+
useNotify: jest.fn(() => jest.fn()),
|
|
47
|
+
Form: ({ onSubmit, children, defaultValues, ...props }) => {
|
|
48
|
+
const methods = useForm({ defaultValues: defaultValues ?? {} });
|
|
49
|
+
return (
|
|
50
|
+
<FormProvider {...methods}>
|
|
51
|
+
<form
|
|
52
|
+
onSubmit={methods.handleSubmit(onSubmit)}
|
|
53
|
+
data-testid="secure-transfer-form"
|
|
54
|
+
{...props}
|
|
55
|
+
>
|
|
56
|
+
{children}
|
|
57
|
+
</form>
|
|
58
|
+
</FormProvider>
|
|
59
|
+
);
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
jest.mock('../../../hooks/useSecureMessageTest');
|
|
65
|
+
|
|
66
|
+
describe('SecureTransfer', () => {
|
|
67
|
+
beforeEach(() => {
|
|
68
|
+
jest.clearAllMocks();
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
const onCloseMock = jest.fn();
|
|
72
|
+
it('renders SecureTransfer with titles and form', () => {
|
|
73
|
+
render(<SecureTransfer did="test-did" serviceId="test-service-id" onClose={jest.fn()} />, {
|
|
74
|
+
wrapper: MemoryRouter,
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
// Title and description
|
|
78
|
+
expect(screen.getByText(/Automatically setup your network integration/i)).toBeInTheDocument();
|
|
79
|
+
expect(
|
|
80
|
+
screen.getByText(/This Credential Agent Operator supports the secure transfer of keys./i),
|
|
81
|
+
).toBeInTheDocument();
|
|
82
|
+
|
|
83
|
+
// Confirm checkbox
|
|
84
|
+
expect(
|
|
85
|
+
screen.getByLabelText(
|
|
86
|
+
/Confirm that you consent to the secure transfer of your keys to your Credential Agent Operator. Click here for more information/i,
|
|
87
|
+
),
|
|
88
|
+
).toBeInTheDocument();
|
|
89
|
+
|
|
90
|
+
// Buttons
|
|
91
|
+
expect(screen.getByText(/Skip/i)).toBeInTheDocument();
|
|
92
|
+
expect(screen.getByText(/Confirm/i)).toBeInTheDocument();
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it('calls transferKeys on form submit', async () => {
|
|
96
|
+
const transferKeysMock = reactAdmin.useCreate()[0];
|
|
97
|
+
|
|
98
|
+
render(<SecureTransfer did="test-did" serviceId="test-service-id" onClose={onCloseMock} />, {
|
|
99
|
+
wrapper: MemoryRouter,
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
const checkbox = screen.getByLabelText(
|
|
103
|
+
/Confirm that you consent to the secure transfer of your keys to your Credential Agent Operator. Click here for more information/i,
|
|
104
|
+
);
|
|
105
|
+
expect(checkbox).not.toBeChecked();
|
|
106
|
+
|
|
107
|
+
fireEvent.click(checkbox);
|
|
108
|
+
|
|
109
|
+
fireEvent.submit(screen.getByTestId('secure-transfer-form'));
|
|
110
|
+
|
|
111
|
+
await waitFor(() => {
|
|
112
|
+
expect(transferKeysMock).toHaveBeenCalled();
|
|
113
|
+
expect(onCloseMock).toHaveBeenCalled();
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it('calls onClose when Skip button is clicked', async () => {
|
|
118
|
+
render(<SecureTransfer did="test-did" serviceId="test-service-id" onClose={onCloseMock} />, {
|
|
119
|
+
wrapper: MemoryRouter,
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
fireEvent.click(screen.getByText(/Skip/i));
|
|
123
|
+
await waitFor(() => {
|
|
124
|
+
expect(onCloseMock).toHaveBeenCalled();
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { optionalUrlValidation } from '../index.jsx';
|
|
2
|
+
|
|
3
|
+
describe('optionalUrlValidation', () => {
|
|
4
|
+
it('should return true for valid URLs', () => {
|
|
5
|
+
expect(optionalUrlValidation('https://www.example.com')).toBe(undefined);
|
|
6
|
+
expect(optionalUrlValidation('https://example.com/path?query=123')).toBe(undefined);
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
it('should return "Please type in a valid URL"', () => {
|
|
10
|
+
const errorMessage = 'Please type in a valid URL';
|
|
11
|
+
expect(optionalUrlValidation('https://e xample.com')).toBe(errorMessage);
|
|
12
|
+
expect(optionalUrlValidation('invalid-url')).toBe(errorMessage);
|
|
13
|
+
expect(optionalUrlValidation('ftp://example.com')).toBe(errorMessage);
|
|
14
|
+
expect(optionalUrlValidation('https://')).toBe(errorMessage);
|
|
15
|
+
});
|
|
16
|
+
it('should return Https is required for http URLs', () => {
|
|
17
|
+
const errorMessage = 'Https is required';
|
|
18
|
+
expect(optionalUrlValidation('http://example.com')).toBe(errorMessage);
|
|
19
|
+
expect(optionalUrlValidation('http://www.example.com')).toBe(errorMessage);
|
|
20
|
+
expect(optionalUrlValidation('http://example.com/path?query=123')).toBe(errorMessage);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('should return true for empty string', () => {
|
|
24
|
+
expect(optionalUrlValidation('')).toBe(undefined);
|
|
25
|
+
});
|
|
26
|
+
});
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
2
|
+
const { TextEncoder: NodeTextEncoder, TextDecoder: NodeTextDecoder } = require('util');
|
|
3
|
+
|
|
4
|
+
const { TestEnvironment } = require('jest-environment-jsdom');
|
|
5
|
+
|
|
6
|
+
// https://github.com/facebook/jest/blob/v29.4.3/website/versioned_docs/version-29.4/Configuration.md#testenvironment-string
|
|
7
|
+
class FixJSDOMEnvironment extends TestEnvironment {
|
|
8
|
+
constructor(...args) {
|
|
9
|
+
super(...args);
|
|
10
|
+
|
|
11
|
+
// https://github.com/jsdom/jsdom/issues/1724
|
|
12
|
+
this.global.fetch = fetch;
|
|
13
|
+
|
|
14
|
+
this.global.Headers = Headers;
|
|
15
|
+
this.global.Request = Request;
|
|
16
|
+
this.global.Response = Response;
|
|
17
|
+
this.global.TextEncoder = NodeTextEncoder;
|
|
18
|
+
this.global.TextDecoder = NodeTextDecoder;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Ensure TextEncoder and TextDecoder are globally available
|
|
23
|
+
if (typeof global.TextEncoder === 'undefined') {
|
|
24
|
+
// eslint-disable-next-line better-mutation/no-mutation
|
|
25
|
+
global.TextEncoder = require('util').TextEncoder;
|
|
26
|
+
}
|
|
27
|
+
if (typeof global.TextDecoder === 'undefined') {
|
|
28
|
+
// eslint-disable-next-line better-mutation/no-mutation
|
|
29
|
+
global.TextDecoder = require('util').TextDecoder;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
module.exports = FixJSDOMEnvironment;
|