Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
77f032d
[ #85 ] [ Aman ] Adds api key authentication feature
Aman-shabbas Oct 13, 2025
301ea16
[ #85 ] [ Aman ] Renames AuthForm to AuthFormProps
Aman-shabbas Oct 13, 2025
c72ae9b
Add. PR Build
hariramprasanth Oct 14, 2025
9408629
Remove. Circle CI PR Build
hariramprasanth Oct 14, 2025
11ed084
Add. CI Pipeline
hariramprasanth Oct 15, 2025
c2f9695
Add. CI Pipeline templates
hariramprasanth Oct 15, 2025
bb4f09e
Add. CI Pipeline templates
hariramprasanth Oct 15, 2025
4e6eafe
[#117] | Dhanoj | Enhance the styling of request completion time
Dhanoj0810 Oct 14, 2025
d63a854
[#117] | Dhanoj | separate status and time assertions in ResponsePane…
Dhanoj0810 Oct 21, 2025
993f9e1
[#166] | Dhanoj | Remove unnecessary stdout messages during test runs…
Dhanoj0810 Oct 21, 2025
907e74a
[#133] | Krishna | Add Trivy integration to Github Actions PR workflow
KrishnaSreeraj Oct 22, 2025
1f54ed8
[#133] | Krishna | Add Trivy integration to Github Actions workflow
KrishnaSreeraj Oct 21, 2025
b5cd5dc
[#133] | Krishna | Add the .trivyignore file to add the vulnerabiliti…
KrishnaSreeraj Oct 21, 2025
5b204ad
[#133] | Krishna | Update the README file to add the details related …
KrishnaSreeraj Oct 21, 2025
23730ba
[#133] | Krishna | Combine the trivy scan and report generation step …
KrishnaSreeraj Oct 22, 2025
febdb64
[#133] | Krishna | Remove redundant logs during trivy vulnerability scan
KrishnaSreeraj Oct 22, 2025
841b7ab
[#126] | Binni | Add header count badge to response panel
droidbg Oct 22, 2025
31c0e50
[#126] | Binni | Use color variables for badge styling
droidbg Oct 22, 2025
d66b4e5
[#126] | Binni | Refactor badge logic to use null instead of undefine…
droidbg Oct 22, 2025
65c0be0
Merge remote-tracking branch 'upstream/main'
Aman-shabbas Oct 26, 2025
bdfed7c
[ #78 ] [ Aman ] Implements API key authentication
Aman-shabbas Oct 26, 2025
d8a00ff
[ #78 ] [ Aman ] wrapes condition around api auth form render
Aman-shabbas Oct 27, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/components/AppBody/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,10 @@ const AppBody = () => {
consolidatedHeaders.push({ key: 'Authorization', value: encodedHeaderValue });
}

if (credentials.authType == AuthType.ApiKey && credentials.key && credentials.value) {
consolidatedHeaders.push({ key: credentials.key, value: credentials.value });
}

const startTime = performance.now();

if (method === Method.Get && url !== '') {
Expand Down
4 changes: 3 additions & 1 deletion src/components/RequestAuthForm/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,9 @@ const RequestAuthForm = (props: RequestAuthFormProps) => {
if (props.authType == AuthType.BasicAuth) {
return <BasicAuthForm onCredentialsChange={props.onCredentialsChange} />;
}
return <ApiKeyAuthForm onCredentialsChange={props.onCredentialsChange} />;
if (props.authType == AuthType.ApiKey) {
return <ApiKeyAuthForm onCredentialsChange={props.onCredentialsChange} />;
}
};

export default RequestAuthForm;
82 changes: 66 additions & 16 deletions tests/components/AppBody.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,9 @@ describe(`AppBody`, () => {

expect(mockedComponents.responsePanel?.statusCode).toBe(200);
expect(mockedComponents.responsePanel?.statusText).toBe('OK');
expect(mockedComponents.responsePanel?.response).toBe(JSON.stringify('patch response', null, 2));
expect(mockedComponents.responsePanel?.response).toBe(
JSON.stringify('patch response', null, 2)
);
});

it('should update ResponsePanel props on DELETE request', async () => {
Expand All @@ -176,7 +178,9 @@ describe(`AppBody`, () => {

expect(mockedComponents.responsePanel?.statusCode).toBe(204);
expect(mockedComponents.responsePanel?.statusText).toBe('No Content');
expect(mockedComponents.responsePanel?.response).toBe(JSON.stringify('delete response', null, 2));
expect(mockedComponents.responsePanel?.response).toBe(
JSON.stringify('delete response', null, 2)
);
});

it('should pass correct response headers to ResponsePanel when response contains headers', async () => {
Expand All @@ -203,7 +207,9 @@ describe(`AppBody`, () => {
}).then(() => {
expect(mockedComponents.responsePanel?.statusCode).toBe(200);
expect(mockedComponents.responsePanel?.statusText).toBe('OK');
expect(mockedComponents.responsePanel?.response).toBe(JSON.stringify('response with headers', null, 2));
expect(mockedComponents.responsePanel?.response).toBe(
JSON.stringify('response with headers', null, 2)
);
expect(mockedComponents.responsePanel?.headers).toEqual([
{ key: 'content-type', value: 'application/json' },
{ key: 'x-custom-header', value: 'custom-value' },
Expand All @@ -212,10 +218,12 @@ describe(`AppBody`, () => {
});
});


it('should handle missing statusText in successful response', async () => {
const { get } = await import('../../src/api/rest.ts');
(get as ReturnType<typeof vi.fn>).mockResolvedValueOnce({ status: 200, data: 'accepted response' });
(get as ReturnType<typeof vi.fn>).mockResolvedValueOnce({
status: 200,
data: 'accepted response',
});
act(() => {
mockedComponents.urlPanel?.onMethodChange('GET');
mockedComponents.urlPanel?.onUrlChange('https://example.com/accepted');
Expand All @@ -228,7 +236,9 @@ describe(`AppBody`, () => {
});
expect(mockedComponents.responsePanel?.statusCode).toBe(200);
expect(mockedComponents.responsePanel?.statusText).toBe('OK');
expect(mockedComponents.responsePanel?.response).toBe(JSON.stringify('accepted response', null, 2));
expect(mockedComponents.responsePanel?.response).toBe(
JSON.stringify('accepted response', null, 2)
);
});

it(`should update ResponsePanel props on API error`, async () => {
Expand Down Expand Up @@ -256,7 +266,9 @@ describe(`AppBody`, () => {

expect(mockedComponents.responsePanel?.statusCode).toBe(404);
expect(mockedComponents.responsePanel?.statusText).toBe('Not Found');
expect(mockedComponents.responsePanel?.response).toBe(JSON.stringify({ message: 'Resource not found' }, null, 2));
expect(mockedComponents.responsePanel?.response).toBe(
JSON.stringify({ message: 'Resource not found' }, null, 2)
);
});

it(`should handle missing statusText, body and statusCode in API error response`, async () => {
Expand Down Expand Up @@ -351,7 +363,9 @@ describe(`AppBody`, () => {
}).then(() => {
expect(mockedComponents.responsePanel?.statusCode).toBe(200);
expect(mockedComponents.responsePanel?.statusText).toBe('OK');
expect(mockedComponents.responsePanel?.response).toBe(JSON.stringify('response with headers', null, 2));
expect(mockedComponents.responsePanel?.response).toBe(
JSON.stringify('response with headers', null, 2)
);
expect(mockedComponents.responsePanel?.headers).toEqual([
{ key: 'content-type', value: 'application/json' },
{ key: 'x-custom-header', value: 'custom-value' },
Expand All @@ -360,7 +374,6 @@ describe(`AppBody`, () => {
});
});


it('should use updated data from RequestPanel callbacks in API calls', async () => {
const { post } = await import('../../src/api/rest.ts');

Expand All @@ -374,9 +387,7 @@ describe(`AppBody`, () => {
{ key: 'X-Custom-Header', value: 'header-value' },
]);

mockedComponents.requestPanel?.onParamsChange([
{ key: 'param1', value: 'value1' },
]);
mockedComponents.requestPanel?.onParamsChange([{ key: 'param1', value: 'value1' }]);

mockedComponents.requestPanel?.onCredentialsChange({
authType: AuthType.BasicAuth,
Expand All @@ -401,14 +412,55 @@ describe(`AppBody`, () => {
});
});

it('should use API key data from RequestPanel callbacks in API calls', async () => {
const { post } = await import('../../src/api/rest.ts');

act(() => {
mockedComponents.urlPanel?.onMethodChange('POST');
mockedComponents.urlPanel?.onUrlChange('https://example.com');

mockedComponents.requestPanel?.onBodyChange('{"my_key":"my_value"}');

mockedComponents.requestPanel?.onHeadersChange([
{ key: 'X-Custom-Header', value: 'header-value' },
]);

mockedComponents.requestPanel?.onParamsChange([{ key: 'param1', value: 'value1' }]);

mockedComponents.requestPanel?.onCredentialsChange({
authType: AuthType.ApiKey,
key: 'my_value',
value: 'api_key_value',
});
});

act(() => {
mockedComponents.urlPanel?.onSend();
});

await waitFor(() => {
const expectedUrl = 'https://example.com?param1=value1';
const expectedBody = { my_key: 'my_value' };
const expectedHeaders = expect.arrayContaining([
{ key: 'X-Custom-Header', value: 'header-value' },
{ key: 'my_value', value: 'api_key_value' },
]);

expect(post).toHaveBeenCalledWith(expectedUrl, expectedBody, expectedHeaders);
});
});

it('should add new header and parameter via RequestPanel callbacks', async () => {
const { get } = await import('../../src/api/rest.ts');

act(() => {
mockedComponents.urlPanel?.onMethodChange('GET');
mockedComponents.urlPanel?.onUrlChange('https://example.com');

mockedComponents.requestPanel?.onNewHeaderAddition({ key: 'X-New-Header', value: 'new-value' });
mockedComponents.requestPanel?.onNewHeaderAddition({
key: 'X-New-Header',
value: 'new-value',
});

mockedComponents.requestPanel?.onNewParamAddition({ key: 'newParam', value: 'newValue' });
});
Expand All @@ -419,9 +471,7 @@ describe(`AppBody`, () => {

await waitFor(() => {
const expectedUrl = 'https://example.com?newParam=newValue';
const expectedHeaders = expect.arrayContaining([
{ key: 'X-New-Header', value: 'new-value' },
]);
const expectedHeaders = expect.arrayContaining([{ key: 'X-New-Header', value: 'new-value' }]);

expect(get).toHaveBeenCalledWith(expectedUrl, expectedHeaders);
});
Expand Down