odac 0.9.0
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/.editorconfig +21 -0
- package/.github/workflows/auto-pr-description.yml +49 -0
- package/.github/workflows/release.yml +32 -0
- package/.github/workflows/test-coverage.yml +58 -0
- package/.husky/pre-commit +2 -0
- package/.kiro/steering/code-style.md +56 -0
- package/.kiro/steering/product.md +20 -0
- package/.kiro/steering/structure.md +77 -0
- package/.kiro/steering/tech.md +87 -0
- package/.prettierrc +10 -0
- package/.releaserc.js +134 -0
- package/AGENTS.md +84 -0
- package/CHANGELOG.md +181 -0
- package/CODE_OF_CONDUCT.md +83 -0
- package/CONTRIBUTING.md +63 -0
- package/LICENSE +661 -0
- package/README.md +57 -0
- package/SECURITY.md +26 -0
- package/bin/candy +10 -0
- package/bin/candypack +10 -0
- package/cli/index.js +3 -0
- package/cli/src/Cli.js +348 -0
- package/cli/src/Connector.js +93 -0
- package/cli/src/Monitor.js +416 -0
- package/core/Candy.js +87 -0
- package/core/Commands.js +239 -0
- package/core/Config.js +1094 -0
- package/core/Lang.js +52 -0
- package/core/Log.js +43 -0
- package/core/Process.js +26 -0
- package/docs/backend/01-overview/01-whats-in-the-candy-box.md +9 -0
- package/docs/backend/01-overview/02-super-handy-helper-functions.md +9 -0
- package/docs/backend/01-overview/03-development-server.md +79 -0
- package/docs/backend/02-structure/01-typical-project-layout.md +39 -0
- package/docs/backend/03-config/00-configuration-overview.md +214 -0
- package/docs/backend/03-config/01-database-connection.md +60 -0
- package/docs/backend/03-config/02-static-route-mapping-optional.md +20 -0
- package/docs/backend/03-config/03-request-timeout.md +11 -0
- package/docs/backend/03-config/04-environment-variables.md +227 -0
- package/docs/backend/03-config/05-early-hints.md +352 -0
- package/docs/backend/04-routing/01-basic-page-routes.md +28 -0
- package/docs/backend/04-routing/02-controller-less-view-routes.md +43 -0
- package/docs/backend/04-routing/03-api-and-data-routes.md +20 -0
- package/docs/backend/04-routing/04-authentication-aware-routes.md +48 -0
- package/docs/backend/04-routing/05-advanced-routing.md +14 -0
- package/docs/backend/04-routing/06-error-pages.md +101 -0
- package/docs/backend/04-routing/07-cron-jobs.md +149 -0
- package/docs/backend/05-controllers/01-how-to-build-a-controller.md +17 -0
- package/docs/backend/05-controllers/02-your-trusty-candy-assistant.md +20 -0
- package/docs/backend/05-controllers/03-controller-classes.md +93 -0
- package/docs/backend/05-forms/01-custom-forms.md +395 -0
- package/docs/backend/05-forms/02-automatic-database-insert.md +297 -0
- package/docs/backend/06-request-and-response/01-the-request-object-what-is-the-user-asking-for.md +96 -0
- package/docs/backend/06-request-and-response/02-sending-a-response-replying-to-the-user.md +40 -0
- package/docs/backend/07-views/01-the-view-directory.md +73 -0
- package/docs/backend/07-views/02-rendering-a-view.md +179 -0
- package/docs/backend/07-views/03-template-syntax.md +181 -0
- package/docs/backend/07-views/03-variables.md +328 -0
- package/docs/backend/07-views/04-request-data.md +231 -0
- package/docs/backend/07-views/05-conditionals.md +290 -0
- package/docs/backend/07-views/06-loops.md +353 -0
- package/docs/backend/07-views/07-translations.md +358 -0
- package/docs/backend/07-views/08-backend-javascript.md +398 -0
- package/docs/backend/07-views/09-comments.md +297 -0
- package/docs/backend/08-database/01-database-connection.md +99 -0
- package/docs/backend/08-database/02-using-mysql.md +322 -0
- package/docs/backend/09-validation/01-the-validator-service.md +424 -0
- package/docs/backend/10-authentication/01-user-logins-with-authjs.md +53 -0
- package/docs/backend/10-authentication/02-foiling-villains-with-csrf-protection.md +55 -0
- package/docs/backend/10-authentication/03-register.md +134 -0
- package/docs/backend/10-authentication/04-candy-register-forms.md +676 -0
- package/docs/backend/10-authentication/05-session-management.md +159 -0
- package/docs/backend/10-authentication/06-candy-login-forms.md +596 -0
- package/docs/backend/11-mail/01-the-mail-service.md +42 -0
- package/docs/backend/12-streaming/01-streaming-overview.md +300 -0
- package/docs/backend/13-utilities/01-candy-var.md +504 -0
- package/docs/frontend/01-overview/01-introduction.md +146 -0
- package/docs/frontend/02-ajax-navigation/01-quick-start.md +608 -0
- package/docs/frontend/02-ajax-navigation/02-configuration.md +370 -0
- package/docs/frontend/02-ajax-navigation/03-advanced-usage.md +519 -0
- package/docs/frontend/03-forms/01-form-handling.md +420 -0
- package/docs/frontend/04-api-requests/01-get-post.md +443 -0
- package/docs/frontend/05-streaming/01-client-streaming.md +163 -0
- package/docs/index.json +452 -0
- package/docs/server/01-installation/01-quick-install.md +19 -0
- package/docs/server/01-installation/02-manual-installation-via-npm.md +9 -0
- package/docs/server/02-get-started/01-core-concepts.md +7 -0
- package/docs/server/02-get-started/02-basic-commands.md +57 -0
- package/docs/server/02-get-started/03-cli-reference.md +276 -0
- package/docs/server/02-get-started/04-cli-quick-reference.md +102 -0
- package/docs/server/03-service/01-start-a-new-service.md +57 -0
- package/docs/server/03-service/02-delete-a-service.md +48 -0
- package/docs/server/04-web/01-create-a-website.md +36 -0
- package/docs/server/04-web/02-list-websites.md +9 -0
- package/docs/server/04-web/03-delete-a-website.md +29 -0
- package/docs/server/05-subdomain/01-create-a-subdomain.md +32 -0
- package/docs/server/05-subdomain/02-list-subdomains.md +33 -0
- package/docs/server/05-subdomain/03-delete-a-subdomain.md +41 -0
- package/docs/server/06-ssl/01-renew-an-ssl-certificate.md +34 -0
- package/docs/server/07-mail/01-create-a-mail-account.md +23 -0
- package/docs/server/07-mail/02-delete-a-mail-account.md +20 -0
- package/docs/server/07-mail/03-list-mail-accounts.md +20 -0
- package/docs/server/07-mail/04-change-account-password.md +23 -0
- package/eslint.config.mjs +120 -0
- package/framework/index.js +4 -0
- package/framework/src/Auth.js +309 -0
- package/framework/src/Candy.js +81 -0
- package/framework/src/Config.js +79 -0
- package/framework/src/Env.js +60 -0
- package/framework/src/Lang.js +57 -0
- package/framework/src/Mail.js +83 -0
- package/framework/src/Mysql.js +575 -0
- package/framework/src/Request.js +301 -0
- package/framework/src/Route/Cron.js +128 -0
- package/framework/src/Route/Internal.js +439 -0
- package/framework/src/Route.js +455 -0
- package/framework/src/Server.js +15 -0
- package/framework/src/Stream.js +163 -0
- package/framework/src/Token.js +37 -0
- package/framework/src/Validator.js +271 -0
- package/framework/src/Var.js +211 -0
- package/framework/src/View/EarlyHints.js +190 -0
- package/framework/src/View/Form.js +600 -0
- package/framework/src/View.js +513 -0
- package/framework/web/candy.js +838 -0
- package/jest.config.js +22 -0
- package/locale/de-DE.json +80 -0
- package/locale/en-US.json +79 -0
- package/locale/es-ES.json +80 -0
- package/locale/fr-FR.json +80 -0
- package/locale/pt-BR.json +80 -0
- package/locale/ru-RU.json +80 -0
- package/locale/tr-TR.json +85 -0
- package/locale/zh-CN.json +80 -0
- package/package.json +86 -0
- package/server/index.js +5 -0
- package/server/src/Api.js +88 -0
- package/server/src/DNS.js +940 -0
- package/server/src/Hub.js +535 -0
- package/server/src/Mail.js +571 -0
- package/server/src/SSL.js +180 -0
- package/server/src/Server.js +27 -0
- package/server/src/Service.js +248 -0
- package/server/src/Subdomain.js +64 -0
- package/server/src/Web/Firewall.js +170 -0
- package/server/src/Web/Proxy.js +134 -0
- package/server/src/Web.js +451 -0
- package/server/src/mail/imap.js +1091 -0
- package/server/src/mail/server.js +32 -0
- package/server/src/mail/smtp.js +786 -0
- package/test/cli/Cli.test.js +36 -0
- package/test/core/Candy.test.js +234 -0
- package/test/core/Commands.test.js +538 -0
- package/test/core/Config.test.js +1435 -0
- package/test/core/Lang.test.js +250 -0
- package/test/core/Process.test.js +156 -0
- package/test/framework/Route.test.js +239 -0
- package/test/framework/View/EarlyHints.test.js +282 -0
- package/test/scripts/check-coverage.js +132 -0
- package/test/server/Api.test.js +647 -0
- package/test/server/Client.test.js +338 -0
- package/test/server/DNS.test.js +2050 -0
- package/test/server/DNS.test.js.bak +2084 -0
- package/test/server/Log.test.js +73 -0
- package/test/server/Mail.account.test_.js +460 -0
- package/test/server/Mail.init.test_.js +411 -0
- package/test/server/Mail.test_.js +1340 -0
- package/test/server/SSL.test_.js +1491 -0
- package/test/server/Server.test.js +765 -0
- package/test/server/Service.test_.js +1127 -0
- package/test/server/Subdomain.test.js +440 -0
- package/test/server/Web/Firewall.test.js +175 -0
- package/test/server/Web.test_.js +1562 -0
- package/test/server/__mocks__/acme-client.js +17 -0
- package/test/server/__mocks__/bcrypt.js +50 -0
- package/test/server/__mocks__/child_process.js +389 -0
- package/test/server/__mocks__/crypto.js +432 -0
- package/test/server/__mocks__/fs.js +450 -0
- package/test/server/__mocks__/globalCandy.js +227 -0
- package/test/server/__mocks__/http-proxy.js +105 -0
- package/test/server/__mocks__/http.js +575 -0
- package/test/server/__mocks__/https.js +272 -0
- package/test/server/__mocks__/index.js +249 -0
- package/test/server/__mocks__/mail/server.js +100 -0
- package/test/server/__mocks__/mail/smtp.js +31 -0
- package/test/server/__mocks__/mailparser.js +81 -0
- package/test/server/__mocks__/net.js +369 -0
- package/test/server/__mocks__/node-forge.js +328 -0
- package/test/server/__mocks__/os.js +320 -0
- package/test/server/__mocks__/path.js +291 -0
- package/test/server/__mocks__/selfsigned.js +8 -0
- package/test/server/__mocks__/server/src/mail/server.js +100 -0
- package/test/server/__mocks__/server/src/mail/smtp.js +31 -0
- package/test/server/__mocks__/smtp-server.js +106 -0
- package/test/server/__mocks__/sqlite3.js +394 -0
- package/test/server/__mocks__/testFactories.js +299 -0
- package/test/server/__mocks__/testHelpers.js +363 -0
- package/test/server/__mocks__/tls.js +229 -0
- package/watchdog/index.js +3 -0
- package/watchdog/src/Watchdog.js +156 -0
- package/web/config.json +5 -0
- package/web/controller/page/about.js +27 -0
- package/web/controller/page/index.js +34 -0
- package/web/package.json +18 -0
- package/web/public/assets/css/style.css +1835 -0
- package/web/public/assets/js/app.js +96 -0
- package/web/route/www.js +19 -0
- package/web/skeleton/main.html +22 -0
- package/web/view/content/about.html +65 -0
- package/web/view/content/home.html +205 -0
- package/web/view/footer/main.html +11 -0
- package/web/view/head/main.html +5 -0
- package/web/view/header/main.html +14 -0
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
// Create mock log function first
|
|
2
|
+
const mockLog = jest.fn()
|
|
3
|
+
|
|
4
|
+
// Mock global Candy first
|
|
5
|
+
const {mockCandy} = require('./__mocks__/globalCandy')
|
|
6
|
+
|
|
7
|
+
// Set up the Log mock before setting global.Candy
|
|
8
|
+
mockCandy.setMock('core', 'Log', {
|
|
9
|
+
init: jest.fn().mockReturnValue({
|
|
10
|
+
log: mockLog,
|
|
11
|
+
error: jest.fn()
|
|
12
|
+
})
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
global.Candy = mockCandy
|
|
16
|
+
|
|
17
|
+
// Mock axios
|
|
18
|
+
jest.mock('axios')
|
|
19
|
+
const axios = require('axios')
|
|
20
|
+
|
|
21
|
+
const Client = require('../../server/src/Client')
|
|
22
|
+
|
|
23
|
+
describe('Client', () => {
|
|
24
|
+
beforeEach(() => {
|
|
25
|
+
jest.clearAllMocks()
|
|
26
|
+
|
|
27
|
+
// Reset config
|
|
28
|
+
mockCandy.setMock('core', 'Config', {
|
|
29
|
+
config: {}
|
|
30
|
+
})
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
describe('authentication', () => {
|
|
34
|
+
it('should authenticate successfully with valid code', async () => {
|
|
35
|
+
// Arrange
|
|
36
|
+
const mockCode = 'valid-auth-code'
|
|
37
|
+
const mockResponse = {
|
|
38
|
+
data: {
|
|
39
|
+
result: {success: true},
|
|
40
|
+
data: {
|
|
41
|
+
token: 'test-token-123',
|
|
42
|
+
secret: 'test-secret-456'
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const mockConfig = {config: {}}
|
|
48
|
+
mockCandy.setMock('core', 'Config', mockConfig)
|
|
49
|
+
axios.post.mockResolvedValue(mockResponse)
|
|
50
|
+
|
|
51
|
+
// Act
|
|
52
|
+
Client.auth(mockCode)
|
|
53
|
+
|
|
54
|
+
// Wait for promise to resolve
|
|
55
|
+
await new Promise(resolve => setTimeout(resolve, 0))
|
|
56
|
+
|
|
57
|
+
// Assert
|
|
58
|
+
expect(mockLog).toHaveBeenCalledWith('CandyPack authenticating...')
|
|
59
|
+
expect(axios.post).toHaveBeenCalledWith('https://api.candypack.dev/auth', {code: mockCode})
|
|
60
|
+
expect(mockConfig.config.auth).toEqual({
|
|
61
|
+
token: 'test-token-123',
|
|
62
|
+
secret: 'test-secret-456'
|
|
63
|
+
})
|
|
64
|
+
expect(mockLog).toHaveBeenCalledWith('CandyPack authenticated!')
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
it('should handle authentication failure with error message', async () => {
|
|
68
|
+
// Arrange
|
|
69
|
+
const mockCode = 'invalid-code'
|
|
70
|
+
const mockError = 'Invalid authentication code'
|
|
71
|
+
|
|
72
|
+
axios.post.mockRejectedValue({
|
|
73
|
+
response: {data: mockError}
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
// Act
|
|
77
|
+
Client.auth(mockCode)
|
|
78
|
+
|
|
79
|
+
// Wait for promise to reject
|
|
80
|
+
await new Promise(resolve => setTimeout(resolve, 0))
|
|
81
|
+
|
|
82
|
+
// Assert
|
|
83
|
+
expect(mockLog).toHaveBeenCalledWith('CandyPack authenticating...')
|
|
84
|
+
expect(axios.post).toHaveBeenCalledWith('https://api.candypack.dev/auth', {code: mockCode})
|
|
85
|
+
expect(mockLog).toHaveBeenCalledWith(mockError)
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
it('should handle authentication failure without error message', async () => {
|
|
89
|
+
// Arrange
|
|
90
|
+
const mockCode = 'invalid-code'
|
|
91
|
+
|
|
92
|
+
axios.post.mockRejectedValue({
|
|
93
|
+
response: {data: null}
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
// Act
|
|
97
|
+
Client.auth(mockCode)
|
|
98
|
+
|
|
99
|
+
// Wait for promise to reject
|
|
100
|
+
await new Promise(resolve => setTimeout(resolve, 0))
|
|
101
|
+
|
|
102
|
+
// Assert
|
|
103
|
+
expect(mockLog).toHaveBeenCalledWith('CandyPack authenticating...')
|
|
104
|
+
expect(mockLog).toHaveBeenCalledWith('CandyPack authentication failed!')
|
|
105
|
+
})
|
|
106
|
+
|
|
107
|
+
it('should handle API response with success false', async () => {
|
|
108
|
+
// Arrange
|
|
109
|
+
const mockCode = 'valid-code'
|
|
110
|
+
const mockResponse = {
|
|
111
|
+
data: {
|
|
112
|
+
result: {
|
|
113
|
+
success: false,
|
|
114
|
+
message: 'Authentication failed on server'
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
axios.post.mockResolvedValue(mockResponse)
|
|
120
|
+
|
|
121
|
+
// Act
|
|
122
|
+
Client.auth(mockCode)
|
|
123
|
+
|
|
124
|
+
// Wait for promise to reject
|
|
125
|
+
await new Promise(resolve => setTimeout(resolve, 0))
|
|
126
|
+
|
|
127
|
+
// Assert
|
|
128
|
+
expect(mockLog).toHaveBeenCalledWith('CandyPack authenticating...')
|
|
129
|
+
expect(mockLog).toHaveBeenCalledWith('Authentication failed on server')
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
it('should store authentication credentials in config', async () => {
|
|
133
|
+
// Arrange
|
|
134
|
+
const mockCode = 'test-code'
|
|
135
|
+
const mockToken = 'stored-token'
|
|
136
|
+
const mockSecret = 'stored-secret'
|
|
137
|
+
const mockResponse = {
|
|
138
|
+
data: {
|
|
139
|
+
result: {success: true},
|
|
140
|
+
data: {
|
|
141
|
+
token: mockToken,
|
|
142
|
+
secret: mockSecret
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const mockConfig = {config: {existingProp: 'value'}}
|
|
148
|
+
mockCandy.setMock('core', 'Config', mockConfig)
|
|
149
|
+
axios.post.mockResolvedValue(mockResponse)
|
|
150
|
+
|
|
151
|
+
// Act
|
|
152
|
+
Client.auth(mockCode)
|
|
153
|
+
|
|
154
|
+
// Wait for promise to resolve
|
|
155
|
+
await new Promise(resolve => setTimeout(resolve, 0))
|
|
156
|
+
|
|
157
|
+
// Assert
|
|
158
|
+
expect(mockConfig.config.auth).toEqual({
|
|
159
|
+
token: mockToken,
|
|
160
|
+
secret: mockSecret
|
|
161
|
+
})
|
|
162
|
+
// Verify existing config is preserved
|
|
163
|
+
expect(mockConfig.config.existingProp).toBe('value')
|
|
164
|
+
})
|
|
165
|
+
})
|
|
166
|
+
|
|
167
|
+
describe('API communication', () => {
|
|
168
|
+
it('should make successful API call and return data', async () => {
|
|
169
|
+
// Arrange
|
|
170
|
+
const mockAction = 'test-action'
|
|
171
|
+
const mockData = {param1: 'value1', param2: 'value2'}
|
|
172
|
+
const mockResponseData = {result: 'success', info: 'test data'}
|
|
173
|
+
const mockResponse = {
|
|
174
|
+
data: {
|
|
175
|
+
result: {success: true},
|
|
176
|
+
data: mockResponseData
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
axios.post.mockResolvedValue(mockResponse)
|
|
181
|
+
|
|
182
|
+
// Act
|
|
183
|
+
const result = await Client.call(mockAction, mockData)
|
|
184
|
+
|
|
185
|
+
// Assert
|
|
186
|
+
expect(axios.post).toHaveBeenCalledWith('https://api.candypack.dev/test-action', mockData)
|
|
187
|
+
expect(result).toEqual(mockResponseData)
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
it('should handle API call with different endpoints', async () => {
|
|
191
|
+
// Arrange
|
|
192
|
+
const testCases = [
|
|
193
|
+
{action: 'users', data: {id: 1}},
|
|
194
|
+
{action: 'domains', data: {domain: 'example.com'}},
|
|
195
|
+
{action: 'ssl/renew', data: {cert: 'test.crt'}}
|
|
196
|
+
]
|
|
197
|
+
|
|
198
|
+
const mockResponseData = {status: 'ok'}
|
|
199
|
+
const mockResponse = {
|
|
200
|
+
data: {
|
|
201
|
+
result: {success: true},
|
|
202
|
+
data: mockResponseData
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
axios.post.mockResolvedValue(mockResponse)
|
|
207
|
+
|
|
208
|
+
// Act & Assert
|
|
209
|
+
for (const testCase of testCases) {
|
|
210
|
+
const result = await Client.call(testCase.action, testCase.data)
|
|
211
|
+
expect(axios.post).toHaveBeenCalledWith(`https://api.candypack.dev/${testCase.action}`, testCase.data)
|
|
212
|
+
expect(result).toEqual(mockResponseData)
|
|
213
|
+
}
|
|
214
|
+
})
|
|
215
|
+
|
|
216
|
+
it('should reject when API response indicates failure', async () => {
|
|
217
|
+
// Arrange
|
|
218
|
+
const mockAction = 'failing-action'
|
|
219
|
+
const mockData = {test: 'data'}
|
|
220
|
+
const mockErrorMessage = 'API operation failed'
|
|
221
|
+
const mockResponse = {
|
|
222
|
+
data: {
|
|
223
|
+
result: {
|
|
224
|
+
success: false,
|
|
225
|
+
message: mockErrorMessage
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
axios.post.mockResolvedValue(mockResponse)
|
|
231
|
+
|
|
232
|
+
// Act & Assert
|
|
233
|
+
await expect(Client.call(mockAction, mockData)).rejects.toBe(mockErrorMessage)
|
|
234
|
+
expect(axios.post).toHaveBeenCalledWith('https://api.candypack.dev/failing-action', mockData)
|
|
235
|
+
})
|
|
236
|
+
|
|
237
|
+
it('should handle network errors and log response data', async () => {
|
|
238
|
+
// Arrange
|
|
239
|
+
const mockAction = 'network-error'
|
|
240
|
+
const mockData = {test: 'data'}
|
|
241
|
+
const mockErrorData = {error: 'Network timeout', code: 500}
|
|
242
|
+
const mockError = {
|
|
243
|
+
response: {data: mockErrorData}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
axios.post.mockRejectedValue(mockError)
|
|
247
|
+
|
|
248
|
+
// Act & Assert
|
|
249
|
+
await expect(Client.call(mockAction, mockData)).rejects.toBe(mockErrorData)
|
|
250
|
+
expect(mockLog).toHaveBeenCalledWith(mockErrorData)
|
|
251
|
+
expect(axios.post).toHaveBeenCalledWith('https://api.candypack.dev/network-error', mockData)
|
|
252
|
+
})
|
|
253
|
+
|
|
254
|
+
it('should handle axios errors without response data', async () => {
|
|
255
|
+
// Arrange
|
|
256
|
+
const mockAction = 'connection-error'
|
|
257
|
+
const mockData = {test: 'data'}
|
|
258
|
+
const mockError = {
|
|
259
|
+
response: {
|
|
260
|
+
data: 'Connection refused'
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
axios.post.mockRejectedValue(mockError)
|
|
265
|
+
|
|
266
|
+
// Act & Assert
|
|
267
|
+
await expect(Client.call(mockAction, mockData)).rejects.toBe('Connection refused')
|
|
268
|
+
expect(mockLog).toHaveBeenCalledWith('Connection refused')
|
|
269
|
+
})
|
|
270
|
+
|
|
271
|
+
it('should format API requests correctly', async () => {
|
|
272
|
+
// Arrange
|
|
273
|
+
const mockAction = 'format-test'
|
|
274
|
+
const mockData = {
|
|
275
|
+
string: 'test',
|
|
276
|
+
number: 123,
|
|
277
|
+
boolean: true,
|
|
278
|
+
object: {nested: 'value'},
|
|
279
|
+
array: [1, 2, 3]
|
|
280
|
+
}
|
|
281
|
+
const mockResponse = {
|
|
282
|
+
data: {
|
|
283
|
+
result: {success: true},
|
|
284
|
+
data: {received: 'ok'}
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
axios.post.mockResolvedValue(mockResponse)
|
|
289
|
+
|
|
290
|
+
// Act
|
|
291
|
+
await Client.call(mockAction, mockData)
|
|
292
|
+
|
|
293
|
+
// Assert
|
|
294
|
+
expect(axios.post).toHaveBeenCalledWith('https://api.candypack.dev/format-test', mockData)
|
|
295
|
+
expect(axios.post).toHaveBeenCalledTimes(1)
|
|
296
|
+
})
|
|
297
|
+
|
|
298
|
+
it('should handle empty response data', async () => {
|
|
299
|
+
// Arrange
|
|
300
|
+
const mockAction = 'empty-response'
|
|
301
|
+
const mockData = {test: 'data'}
|
|
302
|
+
const mockResponse = {
|
|
303
|
+
data: {
|
|
304
|
+
result: {success: true},
|
|
305
|
+
data: null
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
axios.post.mockResolvedValue(mockResponse)
|
|
310
|
+
|
|
311
|
+
// Act
|
|
312
|
+
const result = await Client.call(mockAction, mockData)
|
|
313
|
+
|
|
314
|
+
// Assert
|
|
315
|
+
expect(result).toBeNull()
|
|
316
|
+
})
|
|
317
|
+
|
|
318
|
+
it('should handle API calls with no data parameter', async () => {
|
|
319
|
+
// Arrange
|
|
320
|
+
const mockAction = 'no-data'
|
|
321
|
+
const mockResponse = {
|
|
322
|
+
data: {
|
|
323
|
+
result: {success: true},
|
|
324
|
+
data: {message: 'success'}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
axios.post.mockResolvedValue(mockResponse)
|
|
329
|
+
|
|
330
|
+
// Act
|
|
331
|
+
const result = await Client.call(mockAction)
|
|
332
|
+
|
|
333
|
+
// Assert
|
|
334
|
+
expect(axios.post).toHaveBeenCalledWith('https://api.candypack.dev/no-data', undefined)
|
|
335
|
+
expect(result).toEqual({message: 'success'})
|
|
336
|
+
})
|
|
337
|
+
})
|
|
338
|
+
})
|