-
Notifications
You must be signed in to change notification settings - Fork 5
feat(core): Implement ApiSession and ApiSessionUtils with session management #434
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 18 commits
Commits
Show all changes
21 commits
Select commit
Hold shift + click to select a range
0825eb2
feat: Implement ApiSession and ApiSessionUtils with session managemen…
richie-ni b35328e
Merge branch 'main' into users/richie/create-api-session-key
richie-ni 8cb87c6
feat(api-session): Enhance ApiSessionUtils with session caching and i…
richie-ni 59aa1d2
fix(api-session): Update session key references to use 'session' inst…
richie-ni 47d2cc5
fix(api-session): Update mock session endpoint in tests to use 'http:…
richie-ni 7ac0a9b
fix(api-session): Improve error handling in createApiSession method w…
richie-ni 4b336c4
docs: Update README and example.yaml for clearer API and UI ingress i…
richie-ni a68cc73
fix(example.yaml): Remove trailing space in SystemLink Products datas…
richie-ni abc0587
test(DataSourceBase): Add unit tests for GET and POST methods with AP…
richie-ni 518c547
fix(README.md): Adjust table formatting for clarity in contribution g…
richie-ni 6240ce4
refactor(api-session): Convert session cache to static property and u…
richie-ni ce60ea7
fix(ApiSessionUtils): Simplify session creation logic and update erro…
richie-ni ceba513
fix(README.md): Update instructions to navigate to the Application Ta…
richie-ni 485bca1
fix(api-session): Rename 'session' to 'sessionKey' for consistency in…
richie-ni 568cc4f
fix(comments): Restructure ApiSessionUtils and update session handlin…
richie-ni 1a2f21f
Added test cases
richie-ni b0028e4
fix(test): Update POST request parameters to include body and options…
richie-ni e9530ad
refactor(api-session): Improve ApiSessionUtils constructor and update…
richie-ni f4d4eb9
fix(api-session): Update createApiSession return type to NonNullable …
richie-ni 50c4009
test(DataSourceBase): Add POST request test for API ingress with no o…
richie-ni 0dbf679
Merge branch 'main' into users/richie/create-api-session-key
richie-ni File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,154 @@ | ||
| import { DataQuery, DataSourceInstanceSettings, TestDataSourceResponse } from "@grafana/data"; | ||
| import { BackendSrv } from "@grafana/runtime"; | ||
|
|
||
| jest.mock('./utils', () => ({ | ||
| get: jest.fn(), | ||
| post: jest.fn(), | ||
| })); | ||
|
|
||
| describe('DataSourceBase', () => { | ||
| let backendSrv: BackendSrv; | ||
| let dataSource: any; | ||
| let mockGet: jest.Mock; | ||
| let mockPost: jest.Mock; | ||
|
|
||
| const mockApiSession = { | ||
| endpoint: 'http://api-ingress.com', | ||
| sessionKey: { secret: 'api-key-secret' } | ||
| }; | ||
| const mockApiSessionUtils = { | ||
| createApiSession: jest.fn().mockResolvedValue(mockApiSession) | ||
| }; | ||
|
|
||
| beforeAll(async () => { | ||
| jest.resetModules(); | ||
|
|
||
| const { DataSourceBase } = await import('./DataSourceBase'); | ||
| const utils = await import('./utils'); | ||
|
|
||
| mockGet = utils.get as jest.Mock; | ||
| mockPost = utils.post as jest.Mock; | ||
richie-ni marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| mockGet.mockResolvedValue('test'); | ||
| mockPost.mockResolvedValue('test'); | ||
|
|
||
| backendSrv = {} as BackendSrv; | ||
|
|
||
| dataSource = setupMockDataSource(DataSourceBase); | ||
| dataSource.apiSessionUtils = mockApiSessionUtils; | ||
| }); | ||
|
|
||
| describe('get', () => { | ||
| it('should send GET request with correct parameters when useApiIngress is not set', async () => { | ||
| const response = await dataSource.get('/test-endpoint', { param1: 'value1' }); | ||
|
|
||
| expect(mockGet).toHaveBeenCalledWith( | ||
| backendSrv, | ||
| '/test-endpoint', | ||
| { param1: 'value1' }, | ||
| ); | ||
| expect(response).toEqual('test'); | ||
| }); | ||
|
|
||
| it('should send GET request with API ingress when useApiIngress is true', async () => { | ||
| const response = await dataSource.get('/test-endpoint', { param1: 'value1' }, true); | ||
|
|
||
| expect(mockApiSessionUtils.createApiSession).toHaveBeenCalled(); | ||
| expect(mockGet).toHaveBeenCalledWith( | ||
| backendSrv, | ||
| "http://api-ingress.com/test-endpoint", | ||
| { | ||
| 'param1': 'value1', | ||
| 'x-ni-api-key': 'api-key-secret' | ||
| }, | ||
| ); | ||
| expect(response).toEqual('test'); | ||
| }); | ||
|
|
||
| it('should not send GET request if no API session is returned', async () => { | ||
| jest.clearAllMocks(); | ||
| mockApiSessionUtils.createApiSession.mockRejectedValueOnce(new Error('No session created')); | ||
|
|
||
| await expect(dataSource.get('/test-endpoint', { param1: 'value1' }, true)) | ||
| .rejects.toThrow('No session created'); | ||
| expect(mockApiSessionUtils.createApiSession).toHaveBeenCalled(); | ||
| expect(mockGet).not.toHaveBeenCalled(); | ||
| }); | ||
| }); | ||
|
|
||
| describe('post', () => { | ||
| it('should send POST request with correct parameters when useApiIngress is not set', async () => { | ||
| const response = await dataSource.post('/test-endpoint', { body: 'body' }, { options: 'optionValue' }); | ||
|
|
||
| expect(mockPost).toHaveBeenCalledWith( | ||
| backendSrv, | ||
| '/test-endpoint', | ||
| { body: 'body' }, | ||
| { options: 'optionValue' } | ||
| ); | ||
| expect(response).toEqual('test'); | ||
| }); | ||
|
|
||
| it('should send POST request with API ingress when useApiIngress is true', async () => { | ||
| const response = await dataSource.post( | ||
| '/test-endpoint', | ||
| { body: 'body' }, | ||
| { | ||
| headers: { | ||
| testHeader: 'headerValue' | ||
| } | ||
| }, | ||
| true | ||
| ); | ||
|
|
||
| expect(mockApiSessionUtils.createApiSession).toHaveBeenCalled(); | ||
| expect(mockPost).toHaveBeenCalledWith( | ||
| backendSrv, | ||
| "http://api-ingress.com/test-endpoint", | ||
| { body: 'body' }, | ||
| { | ||
|
|
||
| headers: { | ||
| testHeader: 'headerValue', | ||
| "x-ni-api-key": "api-key-secret" | ||
| } | ||
|
|
||
| }, | ||
| ); | ||
| expect(response).toEqual('test'); | ||
| }); | ||
|
|
||
| it('should not send POST request if no API session is returned', async () => { | ||
| jest.clearAllMocks(); | ||
| mockApiSessionUtils.createApiSession.mockRejectedValueOnce(new Error('No session created')); | ||
|
|
||
| await expect(dataSource.post('/test-endpoint', { options: 'optionValue' }, {}, true)) | ||
| .rejects.toThrow('No session created'); | ||
| expect(mockApiSessionUtils.createApiSession).toHaveBeenCalled(); | ||
| expect(mockPost).not.toHaveBeenCalled(); | ||
| }); | ||
| }); | ||
|
|
||
| function setupMockDataSource(DataSourceBase: any) { | ||
| const instanceSettings = { | ||
| url: 'http://api-example.com', | ||
| } as DataSourceInstanceSettings; | ||
| class MockDataSource extends DataSourceBase<DataQuery> { | ||
| public constructor() { | ||
| super(instanceSettings, backendSrv, {} as any); | ||
| } | ||
| public defaultQuery = {}; | ||
| public runQuery(_query: DataQuery, _options: any) { | ||
| return Promise.resolve({ | ||
| fields: [], | ||
| }); | ||
| } | ||
| public shouldRunQuery() { | ||
| return true; | ||
| } | ||
| testDatasource(): Promise<TestDataSourceResponse> { | ||
| throw new Error("Method not implemented."); | ||
| } | ||
| } | ||
| return new MockDataSource(); | ||
| } | ||
| }); | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.