Skip to content

Commit 6898463

Browse files
committed
fix unit tests
1 parent b48ef27 commit 6898463

File tree

3 files changed

+196
-160
lines changed

3 files changed

+196
-160
lines changed

src/RuntimeBaseCommand.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,11 @@ class RuntimeBaseCommand extends Command {
7070
}
7171

7272
async wsk (options) {
73-
if (!options) {
74-
options = await this.getOptions()
73+
let _options = structuredClone(options)
74+
if (!_options) {
75+
_options = await this.getOptions()
7576
}
76-
return runtimeLib.init(options)
77+
return runtimeLib.init(_options)
7778
}
7879

7980
getImsOrgId () {

test/DeployServiceCommand.test.js

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
/*
2+
Copyright 2025 Adobe Inc. All rights reserved.
3+
This file is licensed to you under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License. You may obtain a copy
5+
of the License at http://www.apache.org/licenses/LICENSE-2.0
6+
7+
Unless required by applicable law or agreed to in writing, software distributed under
8+
the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9+
OF ANY KIND, either express or implied. See the License for the specific language
10+
governing permissions and limitations under the License.
11+
*/
12+
13+
const TheCommand = require('../src/DeployServiceCommand.js')
14+
const { Command } = require('@oclif/core')
15+
const { PropertyDefault } = require('../src/properties')
16+
const RuntimeLib = require('@adobe/aio-lib-runtime')
17+
const { getToken, context, CLI } = require('@adobe/aio-lib-ims')
18+
const { getCliEnv } = require('@adobe/aio-lib-env')
19+
20+
jest.mock('@adobe/aio-lib-ims', () => ({
21+
getToken: jest.fn(),
22+
context: {
23+
getCurrent: jest.fn(),
24+
setCli: jest.fn(),
25+
get: jest.fn()
26+
},
27+
CLI: 'cli'
28+
}))
29+
30+
jest.mock('@adobe/aio-lib-env', () => ({
31+
getCliEnv: jest.fn()
32+
}))
33+
34+
jest.mock('@adobe/aio-lib-runtime', () => ({
35+
init: jest.fn()
36+
}))
37+
38+
describe('DeployServiceCommand', () => {
39+
let command
40+
41+
beforeEach(() => {
42+
command = new TheCommand([])
43+
jest.clearAllMocks()
44+
})
45+
46+
test('exports', async () => {
47+
expect(typeof TheCommand).toEqual('function')
48+
expect(TheCommand.prototype).toBeInstanceOf(Command)
49+
})
50+
51+
test('flags', async () => {
52+
expect(Object.keys(TheCommand.flags)).toEqual(expect.arrayContaining([
53+
'useRuntimeAuth'
54+
]))
55+
})
56+
57+
describe('getAccessToken', () => {
58+
const mockToken = 'mock-token'
59+
const mockEnv = 'prod'
60+
61+
beforeEach(() => {
62+
getCliEnv.mockReturnValue(mockEnv)
63+
})
64+
65+
test('should use CLI context by default', async () => {
66+
context.getCurrent.mockResolvedValue(CLI)
67+
getToken.mockResolvedValue(mockToken)
68+
69+
const result = await command.getAccessToken()
70+
71+
expect(context.getCurrent).toHaveBeenCalled()
72+
expect(context.setCli).toHaveBeenCalledWith({ 'cli.bare-output': true }, false)
73+
expect(getToken).toHaveBeenCalledWith(CLI)
74+
expect(result).toEqual({
75+
accessToken: mockToken,
76+
env: mockEnv
77+
})
78+
})
79+
80+
test('should use custom context when available', async () => {
81+
const customContext = 'custom-context'
82+
context.getCurrent.mockResolvedValue(customContext)
83+
getToken.mockResolvedValue(mockToken)
84+
85+
const result = await command.getAccessToken()
86+
87+
expect(context.getCurrent).toHaveBeenCalled()
88+
expect(context.setCli).not.toHaveBeenCalled()
89+
expect(getToken).toHaveBeenCalledWith(customContext)
90+
expect(result).toEqual({
91+
accessToken: mockToken,
92+
env: mockEnv
93+
})
94+
})
95+
96+
test('should use cached token when requested', async () => {
97+
context.getCurrent.mockResolvedValue(CLI)
98+
context.get.mockResolvedValue({
99+
access_token: { token: mockToken }
100+
})
101+
102+
const result = await command.getAccessToken({ useCachedToken: true })
103+
104+
expect(context.get).toHaveBeenCalledWith(CLI)
105+
expect(getToken).not.toHaveBeenCalled()
106+
expect(result).toEqual({
107+
accessToken: mockToken,
108+
env: mockEnv
109+
})
110+
})
111+
})
112+
113+
describe('getAuthHandler', () => {
114+
test('should return auth handler with correct header', async () => {
115+
const mockToken = 'mock-token'
116+
const mockEnv = 'prod'
117+
getCliEnv.mockReturnValue(mockEnv)
118+
context.getCurrent.mockResolvedValue(CLI)
119+
getToken.mockResolvedValue(mockToken)
120+
121+
const authHandler = command.getAuthHandler()
122+
const header = await authHandler.getAuthHeader()
123+
124+
expect(header).toBe(`Bearer ${mockToken}`)
125+
})
126+
})
127+
128+
describe('setRuntimeApiHostAndAuthHandler', () => {
129+
test('if options is not defined (set auth handler)', async () => {
130+
const mockOptions = null
131+
const result = await command.setRuntimeApiHostAndAuthHandler(mockOptions)
132+
133+
expect(result.apihost).toBe(`${PropertyDefault.DEPLOYSERVICEURL}/runtime`)
134+
expect(result.auth_handler).toBeDefined()
135+
})
136+
137+
test('should set runtime API host and auth handler when useRuntimeAuth is false', async () => {
138+
const mockOptions = { someOption: 'value' }
139+
const result = await command.setRuntimeApiHostAndAuthHandler(mockOptions)
140+
141+
expect(result.apihost).toBe(`${PropertyDefault.DEPLOYSERVICEURL}/runtime`)
142+
expect(result.auth_handler).toBeDefined()
143+
})
144+
145+
test('should not modify options when useRuntimeAuth is true', async () => {
146+
const mockOptions = { useRuntimeAuth: true, someOption: 'value' }
147+
const result = await command.setRuntimeApiHostAndAuthHandler(mockOptions)
148+
149+
expect(result).toEqual(mockOptions)
150+
})
151+
152+
test('should use custom deploy service URL from environment', async () => {
153+
const customUrl = 'https://custom-deploy-service.com'
154+
process.env.AIO_DEPLOY_SERVICE_URL = customUrl
155+
156+
const mockOptions = { someOption: 'value' }
157+
const result = await command.setRuntimeApiHostAndAuthHandler(mockOptions)
158+
159+
expect(result.apihost).toBe(`${customUrl}/runtime`)
160+
delete process.env.AIO_DEPLOY_SERVICE_URL
161+
})
162+
})
163+
164+
describe('wsk', () => {
165+
test('should initialize runtime with correct options', async () => {
166+
const mockOptions = { someOption: 'value' }
167+
await command.wsk(mockOptions)
168+
169+
expect(RuntimeLib.init).toHaveBeenCalled()
170+
})
171+
172+
test('should get options from parent class when not provided', async () => {
173+
await command.wsk()
174+
175+
expect(RuntimeLib.init).toHaveBeenCalled()
176+
})
177+
})
178+
})

test/RuntimeBaseCommand.test.js

Lines changed: 14 additions & 157 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@ const { Command } = require('@oclif/core')
1515
const { PropertyEnv } = require('../src/properties')
1616
const RuntimeLib = require('@adobe/aio-lib-runtime')
1717
const OpenWhiskError = require('openwhisk/lib/openwhisk_error')
18-
const { getToken, context } = require('@adobe/aio-lib-ims')
19-
const { getCliEnv } = require('@adobe/aio-lib-env')
2018

2119
jest.mock('@adobe/aio-lib-ims', () => ({
2220
getToken: jest.fn(),
@@ -223,13 +221,26 @@ describe('instance methods', () => {
223221
})
224222

225223
describe('ow', () => {
224+
beforeEach(() => {
225+
RuntimeLib.init.mockClear()
226+
})
227+
226228
test('is a function', async () => {
227229
expect(command.wsk).toBeInstanceOf(Function)
228230
})
229231

230232
test('returns a promise', () => {
233+
RuntimeLib.init.mockReturnValue({})
231234
return command.wsk().then((ow) => {
232-
expect(ow).toBe(ow)
235+
expect(ow).toBeDefined()
236+
})
237+
})
238+
239+
test('returns a promise (pass options)', () => {
240+
RuntimeLib.init.mockReturnValue({})
241+
const options = { useRuntimeAuth: true }
242+
return command.wsk(options).then((ow) => {
243+
expect(ow).toBeDefined()
233244
})
234245
})
235246

@@ -334,158 +345,4 @@ describe('instance methods', () => {
334345
expect(command.error).toHaveBeenCalledWith('msg' + suffix)
335346
})
336347
})
337-
338-
describe('authHandler', () => {
339-
describe('when IS_DEPLOY_SERVICE_ENABLED = true', () => {
340-
beforeEach(() => {
341-
process.env.IS_DEPLOY_SERVICE_ENABLED = true
342-
})
343-
344-
afterEach(() => {
345-
process.env.IS_DEPLOY_SERVICE_ENABLED = false
346-
})
347-
test('No Options : should return the correct Authorization header using getAuthHeader', async () => {
348-
const mockToken = 'mock-access-token'
349-
getToken.mockResolvedValue(mockToken)
350-
351-
// Spy on runtimeLib.init to capture options before it's used
352-
let capturedOptions
353-
RuntimeLib.init.mockImplementation(async (options) => {
354-
capturedOptions = options // Store options for later verification
355-
return {} // Mock runtimeLib.init() return value
356-
})
357-
358-
// Call wsk() which internally sets auth_handler
359-
await command.wsk()
360-
361-
// Ensure options were captured
362-
expect(capturedOptions).toBeDefined()
363-
expect(capturedOptions.auth_handler).toBeDefined()
364-
expect(capturedOptions.apihost).toBeDefined()
365-
expect(capturedOptions.apihost).toBe('some.host')
366-
367-
// Call getAuthHeader() from captured options
368-
const authHeader = await capturedOptions.auth_handler.getAuthHeader()
369-
370-
expect(context.setCli).toHaveBeenCalledWith({ 'cli.bare-output': true }, false)
371-
expect(getCliEnv).toHaveBeenCalled()
372-
expect(getToken).toHaveBeenCalled()
373-
expect(authHeader).toBe(`Bearer ${mockToken}`)
374-
})
375-
376-
test('With Options : should return the correct Authorization header using getAuthHeader', async () => {
377-
const mockToken = 'mock-access-token'
378-
getToken.mockResolvedValue(mockToken)
379-
380-
const options = {
381-
auth_handler: {
382-
getAuthHeader: async () => `Bearer ${mockToken}`
383-
},
384-
apihost: 'https://custom-api.adobe.com'
385-
}
386-
387-
await command.wsk(options) // Call wsk() with an existing options object
388-
389-
expect(RuntimeLib.init).toHaveBeenCalledWith(options)
390-
})
391-
392-
test('Default OW Host testing', async () => {
393-
delete process.env[PropertyEnv.APIHOST]
394-
395-
const mockToken = 'mock-access-token'
396-
getToken.mockResolvedValue(mockToken)
397-
398-
command.getOptions = jest.fn().mockResolvedValue({})
399-
400-
// Mock runtimeLib.init to track its calls
401-
const mockInit = jest.fn().mockResolvedValue({})
402-
RuntimeLib.init = mockInit
403-
404-
// Call wsk() without options
405-
await command.wsk()
406-
407-
// Assertions
408-
expect(RuntimeLib.init).toHaveBeenCalled()
409-
410-
// Verify the passed options contain the default apihost
411-
const optionsPassedToInit = mockInit.mock.calls[0][0] // Get the options passed to init
412-
expect(optionsPassedToInit.apihost).toBe('https://adobeioruntime.net')
413-
414-
// Ensure the Authorization header is set correctly
415-
expect(optionsPassedToInit.auth_handler).toBeDefined()
416-
const authHeader = await optionsPassedToInit.auth_handler.getAuthHeader()
417-
expect(authHeader).toBe(`Bearer ${mockToken}`)
418-
})
419-
})
420-
421-
describe('when IS_DEPLOY_SERVICE_ENABLED = false', () => {
422-
beforeEach(() => {
423-
process.env.IS_DEPLOY_SERVICE_ENABLED = false
424-
})
425-
426-
test('No Options : should return the correct Authorization header using getAuthHeader', async () => {
427-
const mockToken = 'mock-access-token'
428-
getToken.mockResolvedValue(mockToken)
429-
430-
// Spy on runtimeLib.init to capture options before it's used
431-
let capturedOptions
432-
RuntimeLib.init.mockImplementation(async (options) => {
433-
capturedOptions = options // Store options for later verification
434-
return {} // Mock runtimeLib.init() return value
435-
})
436-
437-
// Call wsk() which internally sets auth_handler
438-
await command.wsk()
439-
440-
// Ensure options were captured
441-
expect(capturedOptions).toBeDefined()
442-
expect(capturedOptions.auth_handler).not.toBeDefined()
443-
expect(capturedOptions.apihost).toBeDefined()
444-
expect(capturedOptions.apihost).toBe('some.host')
445-
})
446-
447-
test('With Options : should return the correct Authorization header using getAuthHeader', async () => {
448-
const mockToken = 'mock-access-token'
449-
getToken.mockResolvedValue(mockToken)
450-
451-
const options = {
452-
auth_handler: {
453-
getAuthHeader: async () => `Bearer ${mockToken}`
454-
},
455-
apihost: 'https://custom-api.adobe.com'
456-
}
457-
458-
await command.wsk(options) // Call wsk() with an existing options object
459-
460-
expect(RuntimeLib.init).toHaveBeenCalledWith(options)
461-
})
462-
463-
test('Default OW Host testing', async () => {
464-
delete process.env[PropertyEnv.APIHOST]
465-
466-
const mockToken = 'mock-access-token'
467-
getToken.mockResolvedValue(mockToken)
468-
469-
// command.getOptions = jest.fn().mockResolvedValue({})
470-
471-
// Mock runtimeLib.init to track its calls
472-
const mockInit = jest.fn().mockResolvedValue({})
473-
RuntimeLib.init = mockInit
474-
475-
// Call wsk() without options
476-
await command.wsk()
477-
478-
// Assertions
479-
expect(RuntimeLib.init).toHaveBeenCalled()
480-
481-
// Verify the passed options contain the default apihost
482-
const optionsPassedToInit = mockInit.mock.calls[0][0] // Get the options passed to init
483-
expect(optionsPassedToInit.apihost).toBe('some.host')
484-
expect(optionsPassedToInit.namespace).toBe('some_namespace')
485-
486-
// Ensure the Authorization header is set correctly
487-
expect(optionsPassedToInit.auth_handler).not.toBeDefined()
488-
})
489-
})
490-
})
491348
})

0 commit comments

Comments
 (0)