Skip to content
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

Load alerts into task dialog from graphql #2376

Merged
merged 10 commits into from
Aug 13, 2020
122 changes: 122 additions & 0 deletions gsa/src/web/graphql/__mocks__/alerts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/* Copyright (C) 2020 Greenbone Networks GmbH
*
* SPDX-License-Identifier: AGPL-3.0-or-later
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License
* as published by the Free Software Foundation, either version 3
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

import {deepFreeze, createGenericQueryMock} from 'web/utils/testing';

import {GET_ALERTS} from '../alerts';

const alert1 = deepFreeze({
id: '1',
name: 'alert 1',
inUse: true,
writable: true,
active: true,
creationTime: '2020-08-06T11:34:15+00:00',
modificationTime: '2020-08-06T11:34:15+00:00',
owner: 'admin',
method: {
type: 'Alemba vFire',
data: [
{name: 'report_formats', value: 'c1645568-627a-11e3-a660-406186ea4fc5'},
{name: 'vfire_base_url', value: '127.0.0.1'},
{name: 'vfire_call_type_name', value: 'foo'},
{name: 'delta_type', value: 'None'},
{name: 'vfire_client_id', value: 'clientID'},
{name: 'vfire_call_partition_name', value: 'lorem'},
{name: 'delta_report_id', value: null},
{name: 'vfire_call_template_name', value: 'bar'},
{name: 'vfire_call_urgency_name', value: 'hello'},
{name: 'vfire_call_impact_name', value: 'baz'},
{name: 'details_url', value: 'https://secinfo.greenbone.net/etc'},
],
},
event: {
type: 'Task run status changed',
data: [{name: 'status', value: 'Done'}],
},
condition: {
type: 'Always',
data: [],
},
permissions: [{name: 'Everything'}],
tasks: [
{id: '8589296f-5051-4ed9-9d86-c022936e2893', name: 'task_with_alerts'},
{id: '173a38fe-1038-48a6-9c48-a623ffc04ba8', name: 'scan_local'},
],
});

const alert2 = deepFreeze({
id: '2',
name: 'alert 2',
inUse: true,
writable: false,
active: true,
creationTime: '2020-08-06T11:30:41+00:00',
modificationTime: '2020-08-07T09:26:05+00:00',
owner: 'admin',
method: {
type: 'Email',
data: [
{name: 'notice', value: '1'},
{name: 'from_address', value: 'foo@bar.com'},
{name: 'delta_type', value: 'None'},
{name: 'to_address', value: 'foo@bar.com'},
{name: 'delta_report_id', value: null},
{name: 'subject', value: '[GVM] $T $q $S since $d'},
{name: 'details_url', value: 'https://secinfo.greenbone.net/etc'},
],
},
event: {
type: 'Updated SecInfo arrived',
data: [{name: 'secinfo_type', value: 'nvt'}],
},
condition: {
type: 'Filter count at least',
data: [{name: 'count', value: '3'}],
},
permissions: [{name: 'Everything'}],
tasks: null,
});

const mockAlerts = {
edges: [
{
node: alert1,
},
{
node: alert2,
},
],
counts: {
total: 2,
filtered: 2,
offset: 0,
limit: 10,
length: 2,
},
pageInfo: {
hasNextPage: false,
hasPreviousPage: false,
startCursor: 'YWxlcnQ6MA==',
endCursor: 'YWxlcnQ6OQ==',
lastPageCursor: 'YWxlcnQ6MA==',
},
};

export const createGetAlertsQueryMock = () =>
createGenericQueryMock(GET_ALERTS, {alerts: mockAlerts});
102 changes: 102 additions & 0 deletions gsa/src/web/graphql/__tests__/alerts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/* Copyright (C) 2020 Greenbone Networks GmbH
*
* SPDX-License-Identifier: AGPL-3.0-or-later
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License
* as published by the Free Software Foundation, either version 3
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

import React from 'react';

import {isDefined} from 'gmp/utils/identity';

import {rendererWith, screen, wait, fireEvent} from 'web/utils/testing';

import {useLazyGetAlerts} from '../alerts';
import {createGetAlertsQueryMock} from '../__mocks__/alerts';

const GetLazyAlertsComponent = () => {
const [getAlerts, {counts, loading, alerts}] = useLazyGetAlerts();

if (loading) {
return <span data-testid="loading">Loading</span>;
}
return (
<div>
<button data-testid="load" onClick={() => getAlerts()} />
{isDefined(counts) ? (
<div data-testid="counts">
<span data-testid="total">{counts.all}</span>
<span data-testid="filtered">{counts.filtered}</span>
<span data-testid="first">{counts.first}</span>
<span data-testid="limit">{counts.rows}</span>
<span data-testid="length">{counts.length}</span>
</div>
) : (
<div data-testid="no-counts" />
)}
{isDefined(alerts) ? (
alerts.map(alert => {
return (
<div key={alert.id} data-testid="alert">
{alert.name}
</div>
);
})
) : (
<div data-testid="no-alert" />
)}
</div>
);
};

describe('useLazyGetAlert tests', () => {
test('should query alerts after user interaction', async () => {
const [mock, resultFunc] = createGetAlertsQueryMock();
const {render} = rendererWith({queryMocks: [mock]});

render(<GetLazyAlertsComponent />);

let alertElements = screen.queryAllByTestId('alert');
expect(alertElements).toHaveLength(0);

let noAlerts = screen.queryByTestId('no-alert');
expect(noAlerts).toBeInTheDocument();
const noCounts = screen.queryByTestId('no-counts');
expect(noCounts).toBeInTheDocument();

const button = screen.getByTestId('load');
fireEvent.click(button);

expect(screen.getByTestId('loading')).toHaveTextContent('Loading');

await wait();

expect(resultFunc).toHaveBeenCalled();

alertElements = screen.getAllByTestId('alert');
expect(alertElements).toHaveLength(2);

expect(alertElements[0]).toHaveTextContent('alert 1');
expect(alertElements[1]).toHaveTextContent('alert 2');

noAlerts = screen.queryByTestId('no-alert');
expect(noAlerts).not.toBeInTheDocument();

expect(screen.getByTestId('total')).toHaveTextContent(2);
expect(screen.getByTestId('filtered')).toHaveTextContent(2);
expect(screen.getByTestId('first')).toHaveTextContent(1);
expect(screen.getByTestId('limit')).toHaveTextContent(10);
expect(screen.getByTestId('length')).toHaveTextContent(2);
});
});
131 changes: 131 additions & 0 deletions gsa/src/web/graphql/alerts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
/* Copyright (C) 2020 Greenbone Networks GmbH
*
* SPDX-License-Identifier: AGPL-3.0-or-later
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License
* as published by the Free Software Foundation, either version 3
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

import {useCallback} from 'react';

import gql from 'graphql-tag';

import {useLazyQuery} from '@apollo/react-hooks';

import CollectionCounts from 'gmp/collection/collectioncounts';

import Alert from 'gmp/models/alert';

import {isDefined} from 'gmp/utils/identity';

export const GET_ALERTS = gql`
query Alert(
$filterString: FilterString
$after: String
$before: String
$first: Int
$last: Int
) {
alerts(
filterString: $filterString
after: $after
before: $before
first: $first
last: $last
) {
edges {
node {
name
id
inUse
writable
owner
creationTime
modificationTime
tasks {
id
name
}
event {
type
data {
name
value
}
}
condition {
type
data {
name
value
}
}
method {
type
data {
name
value
}
}
permissions {
name
}
active
}
}
pageInfo {
hasNextPage
hasPreviousPage
startCursor
endCursor
lastPageCursor
}
counts {
total
filtered
offset
limit
length
}
}
}
`;

export const useLazyGetAlerts = (variables, options) => {
const [queryAlerts, {data, ...other}] = useLazyQuery(GET_ALERTS, {
...options,
variables,
});
const alerts = isDefined(data?.alerts)
? data.alerts.edges.map(entity => Alert.fromObject(entity.node))
: undefined;

const {total, filtered, offset = -1, limit, length} =
data?.alerts?.counts || {};
const counts = isDefined(data?.alerts?.counts)
? new CollectionCounts({
all: total,
filtered: filtered,
first: offset + 1,
length: length,
rows: limit,
})
: undefined;
const getAlerts = useCallback(
// eslint-disable-next-line no-shadow
(variables, options) => queryAlerts({...options, variables}),
[queryAlerts],
);
const pageInfo = data?.alerts?.pageInfo;
return [getAlerts, {...other, counts, alerts, pageInfo}];
};
Loading