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

snapshots_spec.js tests updated #933

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
* SPDX-License-Identifier: Apache-2.0
*/

/* eslint-disable cypress/no-unnecessary-waiting */

import { IM_PLUGIN_NAME, BASE_PATH } from "../../../utils/constants";

describe("Snapshots", () => {
Expand All @@ -13,8 +15,8 @@ describe("Snapshots", () => {
// Visit ISM Snapshots Dashboard
cy.visit(`${BASE_PATH}/app/${IM_PLUGIN_NAME}#/snapshots`);

// Common text to wait for to confirm page loaded, give up to 60 seconds for initial load
cy.contains("Restore", { timeout: 60000 });
// Common text to wait for to confirm page loaded, give up to 120 seconds for initial load
cy.contains("Restore", { timeout: 120000 });
});

describe("Repository can be created", () => {
Expand All @@ -31,6 +33,9 @@ describe("Snapshots", () => {
// Type in repository location
cy.get(`input[placeholder="e.g., /mnt/snapshots"]`).focus().type("~/Desktop");

// if a toast message pops up then dismiss it
cy.dismissToast();

// Click Add button
cy.get("button").contains("Add").click({ force: true });

Expand All @@ -51,12 +56,12 @@ describe("Snapshots", () => {
cy.createIndex("test_index_2");
cy.createIndex("test_index_3");

// wait needed here to enable cypress to find "Take snapshot" button. Timeout
// cannot be used with cy.createIndex
cy.wait(5000);

// Click Take snapshot button
cy.get("button").contains("Take snapshot").click({ force: true });
// Click Take snapshot button with a 12sec timeout
cy.get(`[data-test-subj="takeSnapshotButton"]`, { timeout: 12000 })
.should("be.visible")
.should("not.be.disabled")
.contains("Take snapshot")
.click({ force: true });

// Confirm test_repo exists and is in the Select repo field
cy.contains("test_repo");
Expand All @@ -69,8 +74,11 @@ describe("Snapshots", () => {
cy.get(`[data-test-subj="indicesComboBoxInput"]`).type("test_index_2{enter}");
cy.get(`[data-test-subj="indicesComboBoxInput"]`).type("test_index_3{enter}");

// if a toast message pops up then dismiss it
cy.dismissToast();

// Click 'Add' button to create snapshot
cy.get("button").contains("Add", { timeout: 3000 }).click({ force: true });
cy.get(`[data-test-subj="flyout-footer-action-button"]`).contains("Add", { timeout: 3000 }).click({ force: true });

// check for success status and snapshot name
cy.get("button").contains("Refresh").click({ force: true });
Expand All @@ -84,17 +92,21 @@ describe("Snapshots", () => {

describe("Snapshot can be restored", () => {
it("Successfully restores indexes from snapshot", () => {
// Must wait here before refreshing so snapshot status becomes 'success'
cy.wait(5000);

// Wait for snapshot to be created successfully
cy.get("button").contains("Refresh").click({ force: true });
// Wait for snapshot to be created successfully with a 12sec timeout
cy.get(`[data-test-subj="refreshButton"]`, { timeout: 12000 })
.should("be.visible")
.should("not.be.disabled")
.contains("Refresh")
.click({ force: true });

// Select test snapshot
cy.get(`[data-test-subj="checkboxSelectRow-test_repo:test_snapshot"]`).check({ force: true });
// Select test snapshot with a 2sec timeout
cy.get(`[data-test-subj="checkboxSelectRow-test_repo:test_snapshot"]`, { timeout: 2000 }).check({ force: true });

// click "Restore" button
cy.get(`[data-test-subj="restoreButton"]`).click({ force: true });
cy.get(`[data-test-subj="restoreButton"]`).should("be.visible").should("not.be.disabled").click({ force: true });

// if a toast message pops up then dismiss it
cy.dismissToast();

// Check for restore flyout
cy.contains("Restore snapshot");
Expand All @@ -103,23 +115,28 @@ describe("Snapshots", () => {
cy.get(`input[data-test-subj="prefixInput"]`).type("restored_");

// Click restore snapshot button
cy.get("button").contains("Restore snapshot").click({ force: true });
cy.get(`[data-test-subj="flyout-footer-action-button"]`).contains("Restore snapshot").click({ force: true });

// Check for success toast
cy.contains(`Restore from snapshot "test_snapshot" is in progress.`);
});
});

describe("Snapshot can be deleted", () => {
it("deletes snapshot successfully", async () => {
it("deletes snapshot successfully", () => {
// Select test snapshot
cy.get(`[data-test-subj="checkboxSelectRow-test_repo:test_snapshot"]`).check({ force: true });

// click "Delete" button
cy.get("button").contains("Delete", { timeout: 3000 }).click({ force: true });

// click "Delete snapshot" button on modal
cy.get("button").contains("Delete snapshot").click({ force: true });
cy.get(`[data-test-subj="deleteButton"]`)
.should("be.visible")
.should("not.be.disabled")
.get("button")
.contains("Delete", { timeout: 3000 })
.click({ force: true });

// click "Delete snapshot" button on modal with a 2sec timeout
cy.get("button", { timeout: 2000 }).contains("Delete snapshot").click({ force: true });

cy.contains("Deleted snapshot");
cy.contains("No items found");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,3 +125,11 @@ Cypress.Commands.add("removeIndexAlias", (alias) => {
failOnStatusCode: false,
});
});

Cypress.Commands.add("dismissToast", () => {
cy.get("body").then(($body) => {
if ($body.find(`[data-test-subj="toastCloseButton"]`).length) {
cy.get(`[data-test-subj="toastCloseButton"]`).click({ force: true });
}
});
});
74 changes: 36 additions & 38 deletions public/pages/Snapshots/containers/Snapshots/Snapshots.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { FieldValueSelectionFilterConfigType } from "@elastic/eui/src/components
import { CoreServicesContext } from "../../../../components/core_services";
import { SnapshotManagementService, IndexService } from "../../../../services";
import { getErrorMessage } from "../../../../utils/helpers";
import { Toast, RestoreError } from "../../../../models/interfaces"
import { Toast, RestoreError } from "../../../../models/interfaces";
import { CatSnapshotWithRepoAndPolicy as SnapshotsWithRepoAndPolicy } from "../../../../../server/models/interfaces";
import { ContentPanel } from "../../../../components/ContentPanel";
import SnapshotFlyout from "../../components/SnapshotFlyout/SnapshotFlyout";
Expand All @@ -32,9 +32,9 @@ import RestoreActivitiesPanel from "../../components/RestoreActivitiesPanel";
import { Snapshot } from "../../../../../models/interfaces";
import { BREADCRUMBS, ROUTES } from "../../../../utils/constants";
import { renderTimestampMillis } from "../../../SnapshotPolicies/helpers";
import ErrorModal from "../../../Snapshots/components/ErrorModal/ErrorModal"
import ErrorModal from "../../../Snapshots/components/ErrorModal/ErrorModal";
import DeleteModal from "../../../Repositories/components/DeleteModal/DeleteModal";
import { getToasts } from "../../helper"
import { getToasts } from "../../helper";
import { snapshotStatusRender, truncateSpan } from "../../helper";

interface SnapshotsProps extends RouteComponentProps {
Expand Down Expand Up @@ -174,11 +174,11 @@ export default class Snapshots extends Component<SnapshotsProps, SnapshotsState>
] as string[];
this.setState({ snapshots, existingPolicyNames });
} else {
const message = JSON.parse(response.error).error.root_cause[0].reason
const message = JSON.parse(response.error).error.root_cause[0].reason;
const trimmedMessage = message.slice(message.indexOf("]") + 1, message.indexOf(".") + 1);
this.context.notifications.toasts.addError(response.error, {
title: `There was a problem getting the snapshots.`,
toastMessage: `${trimmedMessage} Open browser console & click below for details.`
toastMessage: `${trimmedMessage} Open browser console & click below for details.`,
});
}
} catch (err) {
Expand Down Expand Up @@ -212,11 +212,11 @@ export default class Snapshots extends Component<SnapshotsProps, SnapshotsState>
if (response.ok) {
this.context.notifications.toasts.addSuccess(`Deleted snapshot ${snapshotId} from repository ${repository}.`);
} else {
const message = JSON.parse(response.error).error.root_cause[0].reason
const message = JSON.parse(response.error).error.root_cause[0].reason;
const trimmedMessage = message.slice(message.indexOf("]") + 1, message.indexOf(".") + 1);
this.context.notifications.toasts.addError(response.error, {
title: `There was a problem deleting the snapshot.`,
toastMessage: `${trimmedMessage} Open browser console & click below for details.`
toastMessage: `${trimmedMessage} Open browser console & click below for details.`,
});
}
} catch (err) {
Expand All @@ -241,12 +241,12 @@ export default class Snapshots extends Component<SnapshotsProps, SnapshotsState>
this.context.notifications.toasts.addSuccess(`Created snapshot ${snapshotId} in repository ${repository}.`);
await this.getSnapshots();
} else {
const message = JSON.parse(response.error).error.root_cause[0].reason
const message = JSON.parse(response.error).error.root_cause[0].reason;
const trimmedMessage = message.slice(message.indexOf("]") + 1, message.indexOf(".") + 1);

this.context.notifications.toasts.addError(response.error, {
title: `There was a problem creating the snapshot.`,
toastMessage: `${trimmedMessage} Open browser console & click below for details.`
toastMessage: `${trimmedMessage} Open browser console & click below for details.`,
});
}
} catch (err) {
Expand All @@ -256,7 +256,7 @@ export default class Snapshots extends Component<SnapshotsProps, SnapshotsState>

restoreSnapshot = async (snapshotId: string, repository: string, options: object) => {
try {
await this.setState({ toasts: [], indicesToRestore: options.indices })
await this.setState({ toasts: [], indicesToRestore: options.indices });
const { snapshotManagementService } = this.props;
const response = await snapshotManagementService.restoreSnapshot(snapshotId, repository, options);

Expand All @@ -277,43 +277,43 @@ export default class Snapshots extends Component<SnapshotsProps, SnapshotsState>
let optionalMessage = "";

if (error.reason.indexOf("open index with same name") >= 0) {
optionalMessage = "You have an index with the same name. Try a different prefix."
optionalMessage = "You have an index with the same name. Try a different prefix.";
}
errorMessage = `${optionalMessage}`
errorMessage = `${optionalMessage}`;
}

const toasts = success ?
getToasts("success_restore_toast", errorMessage, selectedItems[0].id, this.onClickTab) :
getToasts("error_restore_toast", errorMessage, selectedItems[0].id, this.onOpenError);
const toasts = success
? getToasts("success_restore_toast", errorMessage, selectedItems[0].id, this.onClickTab)
: getToasts("error_restore_toast", errorMessage, selectedItems[0].id, this.onOpenError);
this.setState({ toasts, error: error });
}
};

onOpenError = () => {
this.setState({ viewError: true });
}
};

collectError = (error: object) => {
this.setState(error);
}
};

collectToast = (toasts: Toast[]) => {
this.setState({ toasts: toasts })
}
this.setState({ toasts: toasts });
};

onCloseModal = () => {
this.setState({ viewError: false, error: {} });
}
};

getRestoreTime = (time: number) => {
this.setState({ restoreStart: time })
}
this.setState({ restoreStart: time });
};

onClickRestore = async () => {
const { selectedItems } = this.state;
const snapshot = selectedItems[0];
const errorMessage = `${snapshot.id} is not available for restore`;
const failedText = "This shapshot is incomplete. Pick another snapshot to restore."
const inProgressText = "This snapshot is still being created. Try again once the snapshot has been completed."
const failedText = "This shapshot is incomplete. Pick another snapshot to restore.";
const inProgressText = "This snapshot is still being created. Try again once the snapshot has been completed.";

if (snapshot.status === "FAILED" || snapshot.status === "IN_PROGRESS") {
const errorText = snapshot.status === "IN_PROGRESS" ? inProgressText : failedText;
Expand All @@ -325,7 +325,7 @@ export default class Snapshots extends Component<SnapshotsProps, SnapshotsState>

onToastEnd = () => {
this.setState({ toasts: [] });
}
};

onCloseRestoreFlyout = () => {
this.setState({ showRestoreFlyout: false });
Expand Down Expand Up @@ -366,7 +366,7 @@ export default class Snapshots extends Component<SnapshotsProps, SnapshotsState>
secondTab!.ariaSelected = "true";
secondTab!.classList.add("euiTab-isSelected");
}
let newState = { snapshotPanel: snapshotPanel, selectedItems }
let newState = { snapshotPanel: snapshotPanel, selectedItems };

if (snapshotPanel) newState.selectedItems = [];

Expand Down Expand Up @@ -434,15 +434,17 @@ export default class Snapshots extends Component<SnapshotsProps, SnapshotsState>
<EuiButton disabled={selectedItems.length !== 1} onClick={this.onClickRestore} color="primary" data-test-subj="restoreButton">
Restore
</EuiButton>,
<EuiButton onClick={this.onClickCreate} fill={true}>
<EuiButton onClick={this.onClickCreate} fill={true} data-test-subj="takeSnapshotButton">
Take snapshot
</EuiButton>,
];

const subTitleText = (
<EuiText color="subdued" size="s" style={{ padding: "5px 0px" }}>
<p style={{ fontWeight: 200 }}>
Snapshots of indices are taken automatically from snapshot policies, <br />or you can initiate manual snapshots to save to a repository.<br />
Snapshots of indices are taken automatically from snapshot policies, <br />
or you can initiate manual snapshots to save to a repository.
<br />
You can restore indices by selecting a snapshot.
</p>
</EuiText>
Expand All @@ -452,8 +454,10 @@ export default class Snapshots extends Component<SnapshotsProps, SnapshotsState>
<>
<EuiPageHeader>
<EuiTabs size="m" ref={this.tabsRef}>
<EuiTab isSelected={true} onClick={this.onClickTab} >Snapshots</EuiTab>
<EuiTab onClick={this.onClickTab} >Restore activities in progress</EuiTab>
<EuiTab isSelected={true} onClick={this.onClickTab}>
Snapshots
</EuiTab>
<EuiTab onClick={this.onClickTab}>Restore activities in progress</EuiTab>
</EuiTabs>
</EuiPageHeader>
{snapshotPanel || (
Expand Down Expand Up @@ -525,13 +529,7 @@ export default class Snapshots extends Component<SnapshotsProps, SnapshotsState>

<EuiGlobalToastList toasts={toasts} dismissToast={this.onToastEnd} toastLifeTimeMs={6000} />

{viewError && (
<ErrorModal
onClick={this.onCloseModal}
onClose={this.onCloseModal}
snapshotId={selectedItems[0].id}
error={error} />
)}
{viewError && <ErrorModal onClick={this.onCloseModal} onClose={this.onCloseModal} snapshotId={selectedItems[0].id} error={error} />}

{isDeleteModalVisible && (
<DeleteModal
Expand Down
Loading