Skip to content

Commit

Permalink
snapshots_spec.js tests updated (#933)
Browse files Browse the repository at this point in the history
Co-authored-by: bowenlan-amzn <bowenlan23@gmail.com>
  • Loading branch information
kohinoor98 and bowenlan-amzn committed Jan 18, 2024
1 parent e855cb5 commit 3c2a9a4
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 61 deletions.
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

0 comments on commit 3c2a9a4

Please sign in to comment.