Skip to content
This repository has been archived by the owner on Oct 20, 2023. It is now read-only.

Commit

Permalink
Bulk edit feature (#142)
Browse files Browse the repository at this point in the history
* Add tests for new Bulk Edit feature (incl. associated data selectors and commands).

* test

* retry

* update hide host bulk test

* Update bulk edit tests to streamline.

* Minor update to hide-host-bulk test.

---------

Co-authored-by: Sebastian Ang <dajian.ang@pnnl.gov>
  • Loading branch information
ccarpenter28 and sang2925 authored Jun 1, 2023
1 parent 19f8bd2 commit ff6bce3
Show file tree
Hide file tree
Showing 7 changed files with 212 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ export const BeaconRow = observer<BeaconProps>(({ beacon, ...props }) => {
{beacon.meta?.[0]?.maybeCurrent?.username}
</RowMuted>
<FlexSplitter />
{beacon?.hidden && <IconLabel title="Hidden" icon={ViewOff16} />}
{beacon?.hidden && <IconLabel cy-test="hidden" title="Hidden" icon={ViewOff16} />}
<MitreTechniqueIcons mitreAttackIds={beacon.mitreTechniques} />
<IconLabel
cy-test="row-command-count"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ export const BulkEdit = observer<HostRowProps>(
return (
<>
<div css={modeBarStyle}>
<Txt>
<Txt cy-test="selected-count">
{count} {typeName === 'beacons' ? 'Beacon' : 'Host'}
{count <= 1 ? '' : 's'} Selected
</Txt>
Expand All @@ -122,6 +122,7 @@ export const BulkEdit = observer<HostRowProps>(
disabled={count === 0}
icon={
<Button
cy-test="bulk-edit"
disabled={count === 0}
rightIcon={<CarbonIcon icon={Edit16} />}
intent={Intent.PRIMARY}
Expand All @@ -135,6 +136,7 @@ export const BulkEdit = observer<HostRowProps>(
<Menu>
{store.settings.showHidden && (
<MenuItem2
cy-test="show"
text={`Show ${typeName === 'beacons' ? 'Beacon' : 'Host'}${count === 1 ? '' : 's'}`}
icon={<CarbonIcon icon={View16} css={iconStyle(true)} />}
onClick={handleBulkShowClick}
Expand All @@ -146,6 +148,7 @@ export const BulkEdit = observer<HostRowProps>(
/>
)}
<MenuItem2
cy-test="hide"
text={`Hide ${typeName === 'beacons' ? 'Beacon' : 'Host'}${count === 1 ? '' : 's'}`}
icon={<CarbonIcon icon={ViewOff16} css={iconStyle()} />}
onClick={handleBulkHideClick}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ export const HostRow = observer<HostRowProps>(({ host, ...props }) => {
</Txt>
</RowTitle>
<FlexSplitter />
{host?.hidden && <IconLabel title="Hidden" icon={ViewOff16} />}
{host?.hidden && <IconLabel cy-test="hidden" title="Hidden" icon={ViewOff16} />}
{!host.cobaltStrikeServer && (
<>
<IconLabel
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ export const ControlBar = observer<ControlBarProps>(
/>
) : (
<Button
cy-test="cancel"
alignText={Alignment.LEFT}
onClick={() => store.campaign?.commentStore.setGroupSelect(false)}
minimal
Expand All @@ -136,6 +137,7 @@ export const ControlBar = observer<ControlBarProps>(
!store.appMeta.blueTeam &&
(!store.campaign?.hostGroupSelect.groupSelect ? (
<Button
cy-test="bulk-edit"
icon={<CarbonIcon icon={Edit16} />}
alignText={Alignment.LEFT}
intent={Intent.PRIMARY}
Expand All @@ -154,6 +156,7 @@ export const ControlBar = observer<ControlBarProps>(
/>
) : (
<Button
cy-test="cancel"
alignText={Alignment.LEFT}
onClick={() => {
store.campaign?.setHostGroupSelect({
Expand All @@ -173,6 +176,7 @@ export const ControlBar = observer<ControlBarProps>(
!store.appMeta.blueTeam &&
(!store.campaign?.beaconGroupSelect.groupSelect ? (
<Button
cy-test="bulk-edit"
icon={<CarbonIcon icon={Edit16} />}
alignText={Alignment.LEFT}
intent={Intent.PRIMARY}
Expand All @@ -190,6 +194,7 @@ export const ControlBar = observer<ControlBarProps>(
/>
) : (
<Button
cy-test="cancel"
alignText={Alignment.LEFT}
onClick={() => {
store.campaign?.setBeaconGroupSelect({
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/// <reference types="cypress" />

function selectMultipleBeacons() {
cy.get('[type=checkbox]').eq(0).check({ force: true });
cy.get('[type=checkbox]').eq(1).check({ force: true });
cy.get('[type=checkbox]').eq(2).check({ force: true });
}

describe('Bulk edit to hide beacons', () => {
const camp = 'bulkEditHideBeacon';
const fileName = 'gt.redeye';

it('Can hide multiple beacons using Bulk Edit', () => {
cy.uploadCampaign(camp, fileName);

// Search for new campaign by name
cy.selectCampaign(camp);

// // Toggle switch to not show hidden items
cy.doNotShowHiddenItems();

// Get beacon names and create array
cy.clickBeaconsTab();

const beacons = [];
cy.get('[cy-test=beacons-row]').each(($beac) => beacons.push($beac.text()));
cy.wrap(beacons).as('fullList').should('have.length', 5);

// Use Bulk Edit to hide 3 beacons
cy.clickBulkEdit();
selectMultipleBeacons();
cy.clickBulkEdit();
cy.bulkEditHide();

// Verify beacons no longer show
cy.get('[cy-test=beacons-row]')
.invoke('text')
.should(($in) => {
expect($in).to.not.contain(beacons[0]).and.to.not.contain(beacons[1]).and.to.not.contain(beacons[2]);
});

// Toggle switch back on
cy.showHiddenItems();

// Verify beacons now show again with the hidden icon
cy.clickBeaconsTab();
cy.get('[cy-test=beacons-row]').should('have.length', 5);
cy.get('[cy-test=hidden]')
.its('length')
.then((hiddenCount) => {
expect(hiddenCount).to.eq(3);
});

// Use Bulk Edit to unhide the beacons
cy.clickBulkEdit();
selectMultipleBeacons();
cy.clickBulkEdit();
cy.bulkEditShow();

// Toggle off switch for hidden beacons
cy.doNotShowHiddenItems();

// // Verify beacons show
cy.clickBeaconsTab();
cy.get('[cy-test=beacons-row]').should('have.length', 5);
});

it('Verify Cancel button works for Bulk Edit', () => {
// Search for new campaign by name
cy.selectCampaign(camp);

// Go to Beacons tab and log starting number of beacons
cy.clickBeaconsTab();
cy.get('[cy-test=beacons-row]').its('length').as('beaconCount').should('eq', 5);

// Use Bulk Edit to select the first three
cy.clickBulkEdit();
selectMultipleBeacons();

// Click Cancel button above Bulk Edit to cancel action
cy.get('[cy-test=cancel]').click();

// Toggle switch so that hidden items are not shown
cy.doNotShowHiddenItems();

// Verify beacon numbers are still the same
cy.clickBeaconsTab();
cy.get('@beaconCount').should('eq', 5);
});

after(() => {
cy.deleteCampaignGraphQL(camp);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/// <reference types="cypress" />

function selectMultipleHosts() {
cy.get('[type=checkbox]').eq(0).check({ force: true });
cy.get('[type=checkbox]').eq(1).check({ force: true });
cy.get('[type=checkbox]').eq(2).check({ force: true });
}

describe('Bulk edit to hide hosts', () => {
const camp = 'bulkEditHideHost';
const fileName = 'smalldata.redeye';

it('Can hide multiple hosts using Bulk Edit', () => {
cy.uploadCampaign(camp, fileName);

// Search for new campaign by name
cy.selectCampaign(camp);

// // Toggle switch to not show hidden items
cy.doNotShowHiddenItems();

// Get host names and create array
const hosts = [];
cy.get('[cy-test=hostName]').each(($ho) => hosts.push($ho.text()));
cy.wrap(hosts).as('fullList').should('have.length', 6);

// Use Bulk Edit to hide 3 hosts
cy.clickBulkEdit();
selectMultipleHosts();
cy.clickBulkEdit();
cy.bulkEditHide();

// Verify hosts no longer show
cy.get('[cy-test=hostName]')
.invoke('text')
.should(($in) => {
expect($in).to.not.contain(hosts[0]).and.to.not.contain(hosts[1]).and.to.not.contain(hosts[2]);
});

// Toggle switch back on
cy.showHiddenItems();

// Verify hosts show again with the hidden icon
cy.get('[cy-test=hostName]').should('have.length', 6);
cy.get('[cy-test=hidden]')
.its('length')
.then((hiddenCount) => {
expect(hiddenCount).to.be.gte(3);
});

// Use Bulk Edit to unhide the hosts
cy.clickBulkEdit();
selectMultipleHosts();
cy.clickBulkEdit();
cy.bulkEditShow();

// Toggle off switch for hidden items
cy.doNotShowHiddenItems();

// Verify hosts show
cy.get('[cy-test=hostName]').should('have.length', 6);
});

it('Verify Cancel button works for Bulk Edit', () => {
// Search for new campaign by name
cy.selectCampaign(camp);

// Log starting number of hosts
cy.get('[cy-test=info-row]').its('length').as('hostsCount').should('eq', 6);

// Use Bulk Edit to select the first three
cy.clickBulkEdit();
selectMultipleHosts();

// Click Cancel button above Bulk Edit to cancel action
cy.get('[cy-test=cancel]').click();

// Toggle switch so that hidden items are not shown
cy.doNotShowHiddenItems();

// Verify host numbers are still the same
cy.get('@hostsCount').should('eq', 6);
});

after(() => {
cy.deleteCampaignGraphQL(camp);
});
});
19 changes: 19 additions & 0 deletions applications/redeye-e2e/src/support/explore.js
Original file line number Diff line number Diff line change
Expand Up @@ -306,3 +306,22 @@ Cypress.Commands.add('confirmShowHide', () => {
Cypress.Commands.add('cancelShowHide', () => {
cy.get('[cy-test=cancel-show-hide]').click();
});

// CLICK BULK EDIT BUTTON TO SHOW/HIDE MULTIPLE ITEMS
Cypress.Commands.add('clickBulkEdit', () => {
cy.get('[cy-test=bulk-edit]').click();
});

// HIDE ITEMS USING BULK EDIT
Cypress.Commands.add('bulkEditHide', () => {
cy.get('[cy-test=hide]').click();
cy.get('[cy-test=confirm-show-hide]').click();
cy.wait(1000);
});

// SHOW ITEMS USING BULK EDIT
Cypress.Commands.add('bulkEditShow', () => {
cy.get('[cy-test=show]').click();
cy.get('[cy-test=confirm-show-hide]').click();
cy.wait(1000);
});

0 comments on commit ff6bce3

Please sign in to comment.