Skip to content

Commit

Permalink
add: tests enhanced reject error for missing feed details
Browse files Browse the repository at this point in the history
  • Loading branch information
daniele-mng committed Oct 11, 2024
1 parent 3988553 commit 2d64a3f
Show file tree
Hide file tree
Showing 6 changed files with 188 additions and 23 deletions.
2 changes: 2 additions & 0 deletions allowedSnakeCase.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,8 @@ module.exports = [
'family_list',
'feed_event',
'feed_type',
'feed_owner_set',
'feed_resources_access',

Check warning on line 180 in allowedSnakeCase.cjs

View check run for this annotation

Codecov / codecov/patch

allowedSnakeCase.cjs#L179-L180

Added lines #L179 - L180 were not covered by tests
'field_value',
'filtered_count',
'filter_func',
Expand Down
43 changes: 42 additions & 1 deletion src/gmp/commands/__tests__/feedstatus.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

import {describe, test, expect} from '@gsa/testing';
import {describe, test, expect, testing} from '@gsa/testing';

import {createResponse, createHttp} from '../testing';

Expand Down Expand Up @@ -113,4 +113,45 @@ describe('FeedStatusCommand tests', () => {

await expect(cmd.checkFeedSync()).rejects.toThrow('Network error');
});

describe('checkFeedOwnerAndPermissions', () => {
test('should return feed owner and permissions', async () => {
const response = createResponse({
get_feeds: {
get_feeds_response: {
feed_owner_set: 0,
feed_resources_access: 1,
},
},
});

const fakeHttp = createHttp(response);
const cmd = new FeedStatus(fakeHttp);

const result = await cmd.checkFeedOwnerAndPermissions();

expect(fakeHttp.request).toHaveBeenCalledWith('get', {
args: {
cmd: 'get_feeds',
},
});

expect(result.isFeedOwner).toBe(false);
expect(result.isFeedResourcesAccess).toBe(true);
});

test('should log an error when checkFeedSync fails', async () => {
const fakeHttp = createHttp(Promise.reject(new Error('Network error')));
const cmd = new FeedStatus(fakeHttp);

console.error = testing.fn();

await expect(cmd.checkFeedSync()).rejects.toThrow('Network error');

expect(console.error).toHaveBeenCalledWith(
'Error checking if feed is syncing:',
expect.any(Error),
);
});
});
});
73 changes: 73 additions & 0 deletions src/gmp/http/__tests__/http.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/* SPDX-FileCopyrightText: 2024 Greenbone AG
*
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

import {describe, test, expect, testing, beforeEach} from '@gsa/testing';

import Http from 'gmp/http/http';
import Rejection from '../rejection';
import {vi} from 'vitest';

const mockGetFeedAccessStatusMessage = testing.fn();

vi.mock('gmp/http/utils', async () => {
return {
getFeedAccessStatusMessage: () => mockGetFeedAccessStatusMessage(),
};
});

global.XMLHttpRequest = testing.fn(() => ({
open: testing.fn(),
send: testing.fn(),
setRequestHeader: testing.fn(),
status: 0,
responseText: '',
onreadystatechange: null,
readyState: 0,
}));

describe('Http', () => {
describe('handleResponseError', () => {
let instance;
let reject;
let resolve;
let xhr;
let options;

beforeEach(() => {
instance = new Http();
resolve = testing.fn();
reject = testing.fn();
xhr = {status: 500};
options = {};
testing.clearAllMocks();
});
test('should handle response error without error handlers', async () => {
await instance.handleResponseError(xhr, reject, resolve, options);
expect(reject).toHaveBeenCalledWith(expect.any(Rejection));
});

test('401 error should call error handler', async () => {
xhr.status = 401;
await instance.handleResponseError(resolve, reject, xhr, options);
expect(reject).toHaveBeenCalledWith(expect.any(Rejection));
expect(reject.mock.calls[0][0].reason).toBe(
Rejection.REASON_UNAUTHORIZED,
);
});

test('404 error should append additional message', async () => {
xhr.status = 404;
const additionalMessage = 'Additional feed access status message';
mockGetFeedAccessStatusMessage.mockResolvedValue(additionalMessage);

await instance.handleResponseError(resolve, reject, xhr, options);
expect(mockGetFeedAccessStatusMessage).toHaveBeenCalled();

expect(reject).toHaveBeenCalledWith(expect.any(Rejection));
const rejectedResponse = reject.mock.calls[0][0];
expect(rejectedResponse.message).toContain(additionalMessage);
});
});
});
50 changes: 50 additions & 0 deletions src/gmp/http/__tests__/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/* SPDX-FileCopyrightText: 2024 Greenbone AG
*
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

import {describe, test, expect} from '@gsa/testing';

import {createResponse, createHttp} from 'gmp/commands/testing';

import {getFeedAccessStatusMessage} from 'gmp/http/utils';
import {FeedStatus} from 'gmp/commands/feedstatus';

describe('Http', () => {
describe('getFeedAccessStatusMessage', () => {
const setupTest = async (feedOwnerSet, feedResourcesAccess) => {
const response = createResponse({
get_feeds: {
get_feeds_response: {
feed_owner_set: feedOwnerSet,
feed_resources_access: feedResourcesAccess,
},
},
});
const fakeHttp = createHttp(response);
const feedCmd = new FeedStatus(fakeHttp);
await feedCmd.checkFeedOwnerAndPermissions();
return getFeedAccessStatusMessage(fakeHttp);
};

test.each([
[
0,
1,
'The feed owner is currently not set. This issue may be due to the feed not having completed its synchronization.\nPlease try again shortly.',
],
[
1,
0,
'Access to the feed resources is currently restricted. This issue may be due to the feed not having completed its synchronization.\nPlease try again shortly.',
],
[1, 1, ''],
])(
'should return correct message for feedOwnerSet: %i, feedResourcesAccess: %i',
async (feedOwnerSet, feedResourcesAccess, expectedMessage) => {
const message = await setupTest(feedOwnerSet, feedResourcesAccess);
expect(message).toBe(expectedMessage);
},
);
});
});
23 changes: 2 additions & 21 deletions src/gmp/http/http.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ import Response from './response';

import DefaultTransform from './transform/default';

import {buildUrlParams} from './utils';
import {FeedStatus} from 'gmp/commands/feedstatus';
import {buildUrlParams, getFeedAccessStatusMessage} from './utils';

const log = logger.getLogger('gmp.http');

Expand All @@ -25,23 +24,6 @@ function formdata_append(formdata, key, value) {
}
}

async function checkFeedOwnershipAndAccess(context) {
const feedStatus = new FeedStatus(context);
const {isFeedOwner, isFeedResourcesAccess} =
await feedStatus.checkFeedOwnerAndPermissions();
const syncMessage = _(
'This issue may be due to the feed not having completed its synchronization.\nPlease try again shortly.',
);

if (!isFeedOwner) {
return `${_('The feed owner is currently not set.')} ${syncMessage}`;
} else if (!isFeedResourcesAccess) {
return `${_('Access to the feed resources is currently restricted.')} ${syncMessage}`;
}

return '';
}

class Http {
constructor(url, options = {}) {
const {timeout, transform = DefaultTransform} = options;
Expand Down Expand Up @@ -196,13 +178,12 @@ class Http {
let rejectedResponse = await this.transformRejection(rej, options);

if (rej.status === 404) {
const additionalMessage = await checkFeedOwnershipAndAccess(this);
const additionalMessage = await getFeedAccessStatusMessage(this);

if (additionalMessage) {
rejectedResponse.message = `${rejectedResponse.message}\n${additionalMessage}`;
}
}

reject(rejectedResponse);
} catch (error) {
log.error('Could not handle response error', error);
Expand Down
20 changes: 19 additions & 1 deletion src/gmp/http/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

import _ from 'gmp/locale';

import {isDefined} from 'gmp/utils/identity';
import {FeedStatus} from 'gmp/commands/feedstatus';

export const buildUrlParams = params => {
let argcount = 0;
Expand Down Expand Up @@ -31,4 +34,19 @@ export const buildServerUrl = (server, path = '', protocol) => {
return protocol + '//' + server + '/' + path;
};

// vim: set ts=2 sw=2 tw=80:
export async function getFeedAccessStatusMessage(context) {
const feedStatus = new FeedStatus(context);
const {isFeedOwner, isFeedResourcesAccess} =
await feedStatus.checkFeedOwnerAndPermissions();
const syncMessage = _(
'This issue may be due to the feed not having completed its synchronization.\nPlease try again shortly.',
);

if (!isFeedOwner) {
return `${_('The feed owner is currently not set.')} ${syncMessage}`;
} else if (!isFeedResourcesAccess) {
return `${_('Access to the feed resources is currently restricted.')} ${syncMessage}`;
}

return '';
}

0 comments on commit 2d64a3f

Please sign in to comment.