Menu Adjustments: Watch to Monitoring. Tiers to Settings. Notifications to Settings. (#1436)

Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>

Co-authored-by: Alex <33497058+bexsoft@users.noreply.github.com>
This commit is contained in:
Daniel Valdivia
2022-01-24 09:56:16 -08:00
committed by GitHub
parent 0ba60bd674
commit f6016c2769
29 changed files with 510 additions and 279 deletions

View File

@@ -1,4 +1,4 @@
name: "Front-End Permission Tests"
name: "UI"
on:
pull_request:
@@ -10,7 +10,7 @@ on:
jobs:
permissions:
name: Front-End Permission Tests
name: Permissions Tests
runs-on: ${{ matrix.os }}
strategy:
matrix:

View File

@@ -58,7 +58,7 @@
"redux-thunk": "^2.3.0",
"styled-components": "^5.3.1",
"superagent": "^6.1.0",
"testcafe": "^1.17.1",
"testcafe": "^1.18.2",
"typeface-roboto": "^0.0.75",
"use-debounce": "^5.0.1",
"websocket": "^1.0.31"

View File

@@ -27,7 +27,7 @@ const styles = (theme: Theme) =>
display: "flex",
alignItems: "center",
textDecoration: "none",
maxWidth: "250px",
maxWidth: "300px",
padding: "2rem 2rem 0rem 2rem",
color: theme.palette.primary.light,
fontSize: ".8rem",

View File

@@ -161,6 +161,7 @@ export const IAM_PAGES = {
METRICS: "/tools/metrics",
DASHBOARD: "/tools/dashboard",
TOOLS_HEAL: "/tools/heal",
TOOLS_WATCH: "/tools/watch",
/* Health */
HEALTH: "/health",
@@ -171,23 +172,22 @@ export const IAM_PAGES = {
TOOLS_SPEEDTEST: "/support/speedtest",
CALL_HOME: "/support/call-home",
PROFILE: "/support/profile",
TOOLS_WATCH: "/support/inspect",
/** License **/
LICENSE: "/license",
/* Settings **/
SETTINGS: "/settings",
SETTINGS_VIEW: "/settings/:option",
SETTINGS: "/settings/configurations",
SETTINGS_VIEW: "/settings/configurations/:option",
/* Documentation **/
DOCUMENTATION: "/documentation",
/* TBD ? */
NOTIFICATIONS_ENDPOINTS: "/lambda/notification-endpoints",
NOTIFICATIONS_ENDPOINTS_ADD: "/lambda/notification-endpoints/add",
NOTIFICATIONS_ENDPOINTS: "/settings/notification-endpoints",
NOTIFICATIONS_ENDPOINTS_ADD: "/settings/notification-endpoints/add",
NOTIFICATIONS_ENDPOINTS_ADD_SERVICE:
"/lambda/notification-endpoints/add/:service",
TIERS: "/tiers",
TIERS_ADD: "/tiers/add",
TIERS_ADD_SERVICE: "/tiers/add/:service",
"/settings/notification-endpoints/add/:service",
TIERS: "/settings/tiers",
TIERS_ADD: "/settings/tiers/add",
TIERS_ADD_SERVICE: "/settings/tiers/add/:service",
/* Operator */
TENANTS: "/tenants",

View File

@@ -35,6 +35,7 @@ import {
} from "../../../../common/SecureComponent/permissions";
import SecureComponent from "../../../../common/SecureComponent/SecureComponent";
import RBIconButton from "../BucketDetails/SummaryItems/RBIconButton";
import clsx from "clsx";
const styles = (theme: Theme) =>
createStyles({
@@ -195,7 +196,7 @@ const BucketListItem = ({
};
return (
<Grid container className={classes.root}>
<Grid container className={clsx(classes.root, "bucket-item")}>
<Grid item xs={12}>
<Grid container justifyContent={"space-between"}>
<Grid item xs={12} sm={7}>

View File

@@ -1273,5 +1273,5 @@ export const TableRowPredefStyles: any = {
color: "#ACACAC",
backgroundColor: "#FDFDFD",
fontStyle: "italic",
}
}
},
};

View File

@@ -37,6 +37,7 @@ import get from "lodash/get";
import ScreenTitle from "../../Common/ScreenTitle/ScreenTitle";
import withSuspense from "../../Common/Components/withSuspense";
import { IAM_PAGES } from "../../../../common/SecureComponent/permissions";
const ConfigurationForm = withSuspense(
React.lazy(() => import("./ConfigurationForm"))
@@ -64,7 +65,7 @@ const styles = (theme: Theme) =>
});
const getRoutePath = (path: string) => {
return `/settings/${path}`;
return `${IAM_PAGES.SETTINGS}/${path}`;
};
const ConfigurationOptions = ({ classes, match }: IConfigurationOptions) => {
@@ -95,12 +96,12 @@ const ConfigurationOptions = ({ classes, match }: IConfigurationOptions) => {
<Route
exact
key={`configItem-${element.configuration_label}`}
path={`/settings/${element.configuration_id}`}
path={`${IAM_PAGES.SETTINGS}/${element.configuration_id}`}
component={ConfigurationForm}
/>
))}
<Route exact path="/settings">
<Redirect to="/settings/region" />
<Route exact path={IAM_PAGES.SETTINGS}>
<Redirect to={`${IAM_PAGES.SETTINGS}/region`} />
</Route>
</Switch>
</Router>

View File

@@ -231,7 +231,7 @@ const HealthInfo = ({
return (
<Fragment>
<PageHeader label="Diagnostic" />
<PageHeader label="Health" />
<PageLayout>
<Grid item xs={12} className={classes.boxy}>
<TestWrapper title={title} advancedVisible={false}>
@@ -286,6 +286,7 @@ const HealthInfo = ({
)}
<Grid item xs={12} className={classes.diagNew}>
<Button
id="start-new-diagnostic"
type="submit"
variant="contained"
color="primary"

View File

@@ -27,15 +27,9 @@ import {
menuItemMiniStyles,
menuItemTextStyles,
} from "./MenuStyleUtils";
import { DocumentationIcon, SettingsIcon } from "../../../icons";
import { DocumentationIcon } from "../../../icons";
import MenuItem from "./MenuItem";
import { NavLink, useLocation } from "react-router-dom";
import {
CONSOLE_UI_RESOURCE,
IAM_PAGES,
IAM_SCOPES,
} from "../../../common/SecureComponent/permissions";
import SecureComponent from "../../../common/SecureComponent/SecureComponent";
import { useLocation } from "react-router-dom";
const ConsoleMenuList = ({
menuItems,
@@ -137,40 +131,6 @@ const ConsoleMenuList = ({
}}
className={`${stateClsName} group-wrapper bottom-list`}
>
<SecureComponent
scopes={[IAM_SCOPES.ADMIN_CONFIG_UPDATE]}
resource={CONSOLE_UI_RESOURCE}
>
<ListItem
key={IAM_PAGES.SETTINGS}
button
to={IAM_PAGES.SETTINGS}
disableRipple
component={NavLink}
className={`$ ${stateClsName} bottom-menu-item`}
sx={{
...menuItemContainerStyles,
...menuItemMiniStyles,
marginBottom: "3px",
}}
>
<ListItemIcon
sx={{
...menuItemIconStyles,
}}
>
<SettingsIcon />
</ListItemIcon>
<ListItemText
primary="Settings"
sx={{
...menuItemTextStyles,
}}
className={stateClsName}
/>
</ListItem>
</SecureComponent>
<ListItem
button
onClick={(

View File

@@ -70,8 +70,8 @@ import { hasPermission } from "../../../common/SecureComponent/SecureComponent";
import MenuToggle from "./MenuToggle";
import ConsoleMenuList from "./ConsoleMenuList";
import RegisterMenuIcon from "../../../icons/SidebarMenus/RegisterMenuIcon";
import DiagnosticsMenuIcon from "../../../icons/SidebarMenus/DiagnosticsMenuIcon";
import InspectMenuIcon from "../../../icons/SidebarMenus/InspectMenuIcon";
import SettingsIcon from "../../../icons/SettingsIcon";
import WatchIcon from "../../../icons/WatchIcon";
const drawerWidth = 245;
@@ -196,20 +196,7 @@ const Menu = ({
to: IAM_PAGES.POLICIES,
icon: AccessMenuIcon,
},
{
component: NavLink,
to: IAM_PAGES.NOTIFICATIONS_ENDPOINTS,
name: "Notification Endpoints",
icon: LambdaIcon,
id: "lambda",
},
{
component: NavLink,
to: IAM_PAGES.TIERS,
name: "Tiers",
icon: TiersIcon,
id: "tiers",
},
{
name: "Monitoring",
id: "tools",
@@ -243,7 +230,13 @@ const Menu = ({
icon: TraceMenuIcon,
component: NavLink,
},
{
name: "Watch",
id: "watch",
component: NavLink,
icon: WatchIcon,
to: IAM_PAGES.TOOLS_WATCH,
},
{
name: "Drives",
id: "monitorDrives",
@@ -253,14 +246,6 @@ const Menu = ({
},
],
},
{
name: "Health",
id: "health",
component: NavLink,
icon: HealthMenuIcon,
to: IAM_PAGES.HEALTH,
children: [],
},
{
name: "Support",
id: "support",
@@ -274,10 +259,10 @@ const Menu = ({
to: IAM_PAGES.REGISTER_SUPPORT,
},
{
name: "Diagnostic",
name: "Health",
id: "diagnostics",
component: NavLink,
icon: DiagnosticsMenuIcon,
icon: HealthMenuIcon,
to: IAM_PAGES.TOOLS_DIAGNOSTICS,
},
{
@@ -287,6 +272,7 @@ const Menu = ({
icon: PerformanceMenuIcon,
to: IAM_PAGES.TOOLS_SPEEDTEST,
},
// {
// name: "Call Home",
// id: "callhome",
@@ -294,13 +280,13 @@ const Menu = ({
// icon: CallHomeMenuIcon,
// to: IAM_PAGES.CALL_HOME,
// },
{
name: "Inspect",
id: "inspect",
component: NavLink,
icon: InspectMenuIcon,
to: IAM_PAGES.TOOLS_WATCH,
},
// {
// name: "Inspect",
// id: "inspect",
// component: NavLink,
// icon: InspectMenuIcon,
// to: IAM_PAGES.TOOLS_WATCH,
// },
// {
// name: "Profile",
// id: "profile",
@@ -318,6 +304,34 @@ const Menu = ({
icon: LicenseIcon,
forceDisplay: true,
},
{
name: "Settings",
id: "settings",
icon: SettingsIcon,
children: [
{
component: NavLink,
to: IAM_PAGES.SETTINGS,
name: "Configurations",
id: "configurations",
icon: SettingsIcon,
},
{
component: NavLink,
to: IAM_PAGES.NOTIFICATIONS_ENDPOINTS,
name: "Notifications",
icon: LambdaIcon,
id: "lambda",
},
{
component: NavLink,
to: IAM_PAGES.TIERS,
name: "Tiers",
icon: TiersIcon,
id: "tiers",
},
],
},
];
let operatorMenus: IMenuItem[] = [

View File

@@ -187,7 +187,7 @@ const AddNotificationEndpoint = ({
return (
<Fragment>
<PageHeader label="Notification Endpoints" />
<PageHeader label="Notifications" />
<BackLink
to="/notification-endpoints/add"
label={" Back To Supported Services"}

View File

@@ -46,7 +46,7 @@ const NotificationTypeSelector = ({ classes }: INotificationTypeSelector) => {
<Fragment>
<PageHeader label="Notification Endpoints" />
<BackLink
to="/notification-endpoints"
to={IAM_PAGES.NOTIFICATIONS_ENDPOINTS}
label="Return to Configured Endpoints"
className={classes.link}
/>

View File

@@ -182,7 +182,7 @@ const Watch = ({
return (
<React.Fragment>
<PageHeader label="Inspect" />
<PageHeader label="Watch" />
<PageLayout>
<Grid item xs={12}>
<Grid item xs={12} className={classes.actionsTray}>

View File

@@ -1 +1 @@
1642704125
1642917498

View File

@@ -16,7 +16,20 @@
import * as roles from "../utils/roles";
import * as elements from "../utils/elements-menu";
import { monitoringElement, supportElement } from "../utils/elements-menu";
import {
bucketsElement,
dashboardElement,
groupsElement,
iamPoliciesElement,
identityElement,
monitoringElement,
notificationEndpointsElement,
serviceAcctsElement,
settingsElement,
supportElement,
tiersElement,
usersElement,
} from "../utils/elements-menu";
fixture("For user with Admin permissions")
.page("http://localhost:9090")
@@ -25,45 +38,32 @@ fixture("For user with Admin permissions")
});
test("All sidebar items exist", async (t) => {
const monitoring = elements.monitoringElement;
const identity = elements.identityElement;
const dashboardExists = elements.dashboardElement.exists;
const bucketsExist = elements.bucketsElement.exists;
const usersExist = elements.usersElement.exists;
const groupsExist = elements.groupsElement.exists;
const serviceAcctsExist = elements.serviceAcctsElement.exists;
const iamPoliciesExist = elements.iamPoliciesElement.exists;
const settingsExist = elements.settingsElement.exists;
const notificationEndpointsExist =
elements.notificationEndpointsElement.exists;
const tiersExist = elements.tiersElement.exists;
const toolsExist = elements.supportElement.exists;
const licenseExists = elements.licenseElement.exists;
await t
.expect(monitoring.exists)
.expect(monitoringElement.exists)
.ok()
.click(monitoring)
.expect(dashboardExists)
.click(monitoringElement)
.expect(dashboardElement.exists)
.ok()
.expect(bucketsExist)
.expect(bucketsElement.exists)
.ok()
.expect(identity.exists)
.expect(identityElement.exists)
.ok()
.click(identity)
.expect(usersExist)
.click(identityElement)
.expect(usersElement.exists)
.ok()
.expect(groupsExist)
.expect(groupsElement.exists)
.ok()
.expect(serviceAcctsExist)
.expect(serviceAcctsElement.exists)
.ok()
.expect(iamPoliciesExist)
.expect(iamPoliciesElement.exists)
.ok()
.expect(settingsExist)
.expect(settingsElement.exists)
.ok()
.expect(notificationEndpointsExist)
.click(settingsElement)
.expect(notificationEndpointsElement.exists)
.ok()
.expect(tiersExist)
.expect(tiersElement.exists)
.ok()
.expect(supportElement.exists)
.ok()

View File

@@ -19,6 +19,9 @@ import * as elements from "../utils/elements";
import * as functions from "../utils/functions";
import { bucketsElement, logoutItem } from "../utils/elements-menu";
import { Selector } from "testcafe";
import * as constants from "../utils/constants";
import { manageButtonFor } from "../utils/functions";
fixture("For user with Bucket Assign Policy permissions")
.page("http://localhost:9090")
@@ -34,14 +37,15 @@ test("Buckets sidebar item exists", async (t) => {
test.before(async (t) => {
// Create a bucket
await functions.setUpBucket(t);
await functions.setUpBucket(t, "bucketassign");
})("A readonly policy can be assigned to a bucket", async (t) => {
const manageButton = manageButtonFor("bucketassign");
await t
// We need to log back in after we use the admin account to create bucket,
// using the specific role we use in this module
.useRole(roles.bucketAssignPolicy)
.navigateTo("http://localhost:9090/buckets")
.click(elements.manageButton)
.click(manageButton)
.click(elements.bucketAccessRulesTab)
.click(elements.addAccessRuleButton)
.typeText(elements.bucketsPrefixInput, "readonlytest")
@@ -51,9 +55,10 @@ test.before(async (t) => {
});
test("A writeonly policy can be assigned to a bucket", async (t) => {
const manageButton = manageButtonFor("bucketassign");
await t
.navigateTo("http://localhost:9090/buckets")
.click(elements.manageButton)
.click(manageButton)
.click(elements.bucketAccessRulesTab)
.click(elements.addAccessRuleButton)
.typeText(elements.bucketsPrefixInput, "writeonlytest")
@@ -63,9 +68,10 @@ test("A writeonly policy can be assigned to a bucket", async (t) => {
});
test("A readwrite policy can be assigned to a bucket", async (t) => {
const manageButton = manageButtonFor("bucketassign");
await t
.navigateTo("http://localhost:9090/buckets")
.click(elements.manageButton)
.click(manageButton)
.click(elements.bucketAccessRulesTab)
.click(elements.addAccessRuleButton)
.typeText(elements.bucketsPrefixInput, "readwritetest")
@@ -75,14 +81,12 @@ test("A readwrite policy can be assigned to a bucket", async (t) => {
});
test("Previously assigned policy to a bucket can be deleted", async (t) => {
const manageButton = manageButtonFor("bucketassign");
await t
.navigateTo("http://localhost:9090/buckets")
.click(elements.manageButton)
.click(manageButton)
.click(elements.bucketAccessRulesTab)
.click(elements.deleteIconButtonAlt)
.click(elements.deleteButton)
.click(logoutItem);
}).after(async (t) => {
// Cleanup created bucket
await functions.cleanUpBucket(t);
});

View File

@@ -18,6 +18,7 @@ import * as roles from "../utils/roles";
import * as elements from "../utils/elements";
import * as functions from "../utils/functions";
import { bucketsElement, logoutItem } from "../utils/elements-menu";
import { testBucketBrowseButtonFor } from "../utils/functions";
fixture("For user with Bucket Read permissions")
.page("http://localhost:9090")
@@ -32,9 +33,10 @@ test("Buckets sidebar item exists", async (t) => {
test.before(async (t) => {
// Create a bucket
await functions.setUpBucket(t);
await functions.setUpBucket(t, "bucketread");
})("Browse button exists", async (t) => {
const browseExists = elements.testBucketBrowseButton.exists;
const testBucketBrowseButton = testBucketBrowseButtonFor("bucketread");
const browseExists = testBucketBrowseButton.exists;
// We need to log back in after we use the admin account to create bucket,
// using the specific role we use in this module
await t.useRole(roles.bucketRead).expect(browseExists).ok();
@@ -46,22 +48,24 @@ test("Bucket access is set to R", async (t) => {
test
.before(async (t) => {
const testBucketBrowseButton = testBucketBrowseButtonFor("bucketread");
await t
.useRole(roles.admin)
.navigateTo("http://localhost:9090/buckets")
.click(elements.testBucketBrowseButton)
.click(testBucketBrowseButton)
// Upload object to bucket
.setFilesToUpload(elements.uploadInput, "../uploads/test.txt")
.click(logoutItem);
})("Object list table is enabled", async (t) => {
const bucketsTableExists = elements.table.exists;
const testBucketBrowseButton = testBucketBrowseButtonFor("bucketread");
await t
.useRole(roles.bucketRead)
.click(elements.testBucketBrowseButton)
.click(testBucketBrowseButton)
.expect(bucketsTableExists)
.ok();
})
.after(async (t) => {
// Cleanup created bucket and corresponding uploads
await functions.cleanUpBucketAndUploads(t);
await functions.cleanUpBucketAndUploads(t, "bucketread");
});

View File

@@ -18,6 +18,7 @@ import * as roles from "../utils/roles";
import * as elements from "../utils/elements";
import * as functions from "../utils/functions";
import { bucketsElement } from "../utils/elements-menu";
import { testBucketBrowseButtonFor } from "../utils/functions";
fixture("For user with Bucket Write permissions")
.page("http://localhost:9090")
@@ -32,9 +33,10 @@ test("Buckets sidebar item exists", async (t) => {
test.before(async (t) => {
// Create a bucket
await functions.setUpBucket(t);
await functions.setUpBucket(t, "bucketwrite");
})("Browse button exists", async (t) => {
const browseExists = elements.testBucketBrowseButton.exists;
const testBucketBrowseButton = testBucketBrowseButtonFor("bucketwrite");
const browseExists = testBucketBrowseButton.exists;
await t
// We need to log back in after we use the admin account to create bucket,
// using the specific role we use in this module
@@ -53,29 +55,32 @@ test("Bucket access is set to W", async (t) => {
test("Upload button exists", async (t) => {
const uploadExists = elements.uploadButton.exists;
const testBucketBrowseButton = testBucketBrowseButtonFor("bucketwrite");
await t
.navigateTo("http://localhost:9090/buckets")
.click(elements.testBucketBrowseButton)
.click(testBucketBrowseButton)
.expect(uploadExists)
.ok();
});
test("Object can be uploaded to a bucket", async (t) => {
const testBucketBrowseButton = testBucketBrowseButtonFor("bucketwrite");
await t
.navigateTo("http://localhost:9090/buckets")
.click(elements.testBucketBrowseButton)
.click(testBucketBrowseButton)
// Upload object to bucket
.setFilesToUpload(elements.uploadInput, "../uploads/test.txt");
});
test("Object list table is disabled", async (t) => {
const disabledBucketsTableExists = elements.bucketsTableDisabled.exists;
const testBucketBrowseButton = testBucketBrowseButtonFor("bucketwrite");
await t
.navigateTo("http://localhost:9090/buckets")
.click(elements.testBucketBrowseButton)
.click(testBucketBrowseButton)
.expect(disabledBucketsTableExists)
.ok();
}).after(async (t) => {
// Cleanup created bucket and corresponding uploads
await functions.cleanUpBucketAndUploads(t);
await functions.cleanUpBucketAndUploads(t, "bucketwrite");
});

View File

@@ -25,12 +25,7 @@ fixture("For user with Diagnostics permissions")
});
test("Support sidebar item exists", async (t) => {
await t
.expect(supportElement.exists)
.ok()
.click(supportElement)
.expect(supportElement.exists)
.ok();
await t.expect(supportElement.exists).ok();
});
test("Diagnostics link exists in Tools page", async (t) => {
@@ -65,7 +60,8 @@ test("Download button exists after Diagnostic is completed", async (t) => {
await t
.navigateTo("http://localhost:9090/support/diagnostics")
.click(elements.startDiagnosticButton)
.expect(downloadExists).ok();
.expect(downloadExists)
.ok();
});
test("Download button is clickable after Diagnostic is completed", async (t) => {
@@ -76,12 +72,10 @@ test("Download button is clickable after Diagnostic is completed", async (t) =>
});
test("Start New Diagnostic button exists after Diagnostic is completed", async (t) => {
const startNewDiagnosticButtonExists =
elements.startNewDiagnosticButton.exists;
await t
.navigateTo("http://localhost:9090/support/diagnostics")
.click(elements.startDiagnosticButton)
.expect(startNewDiagnosticButtonExists)
.expect(elements.startNewDiagnosticButton.exists)
.ok();
});

View File

@@ -21,9 +21,25 @@ import * as functions from "../utils/functions";
import { Selector } from "testcafe";
import { groupsElement, identityElement } from "../utils/elements-menu";
const groupsListItem = Selector(".ReactVirtualized__Table__rowColumn").withText(
constants.TEST_GROUP_NAME
);
const groupsListItemFor = (modifier) => {
return Selector(".ReactVirtualized__Table__rowColumn").withText(
`${constants.TEST_GROUP_NAME}-${modifier}`
);
};
const createGroup = async (t, modifier) => {
await t
.useRole(roles.groups)
.navigateTo("http://localhost:9090/identity/groups")
.click(elements.createGroupButton)
.typeText(
elements.groupNameInput,
`${constants.TEST_GROUP_NAME}-${modifier}`
)
.typeText(elements.filterUserInput, constants.TEST_USER_NAME)
.click(elements.groupUserCheckbox)
.click(elements.saveButton);
};
fixture("For user with Groups permissions")
.page("http://localhost:9090")
@@ -55,11 +71,10 @@ test("Create Group button is clickable", async (t) => {
});
test("Group Name input exists in the Create Group modal", async (t) => {
const groupNameInputExists = elements.groupNameInput.exists;
await t
.navigateTo("http://localhost:9090/identity/groups")
.click(elements.createGroupButton)
.expect(groupNameInputExists)
.expect(elements.groupNameInput.exists)
.ok();
});
@@ -92,17 +107,19 @@ test.before(async (t) => {
);
test("Groups table exists", async (t) => {
const groupsTableExists = elements.table.exists;
await t
.navigateTo("http://localhost:9090/identity/groups")
.expect(groupsTableExists)
.expect(elements.table.exists)
.ok();
});
test("Created Group can be disabled and enabled back", async (t) => {
test.before(async (t) => {
// A user must be created as we need to choose a user from the dropdown
await createGroup(t, "disable-enable");
})("Created Group can be disabled and enabled back", async (t) => {
await t
.navigateTo("http://localhost:9090/identity/groups")
.click(groupsListItem)
.click(groupsListItemFor("disable-enable"))
.click(elements.switchInput)
.expect(elements.groupStatusText.innerText)
.eql("Disabled")
@@ -111,10 +128,13 @@ test("Created Group can be disabled and enabled back", async (t) => {
.eql("Enabled");
});
test("Created Group can be viewed and deleted", async (t) => {
test.before(async (t) => {
// A user must be created as we need to choose a user from the dropdown
await createGroup(t, "view-delete");
})("Created Group can be viewed and deleted", async (t) => {
await t
.navigateTo("http://localhost:9090/identity/groups")
.click(groupsListItem)
.click(groupsListItemFor("view-delete"))
.click(elements.editMembersButton)
.typeText(elements.filterUserInput, constants.TEST_USER_NAME)
.click(elements.groupUserCheckbox)

View File

@@ -22,6 +22,7 @@ import {
monitoringElement,
supportElement,
} from "../utils/elements-menu";
import { bucketDropdownOptionFor } from "../utils/elements";
fixture("For user with Heal permissions")
.page("http://localhost:9090")
@@ -46,25 +47,35 @@ test("Heal page can be opened", async (t) => {
await t.navigateTo("http://localhost:9090/tools/heal");
});
test.before(async (t) => {
// Create a bucket
await functions.setUpBucket(t);
})("Start button exists", async (t) => {
const startButtonExists = elements.startButton.exists;
await t
.useRole(roles.heal)
.navigateTo("http://localhost:9090/tools/heal")
.expect(startButtonExists)
.ok();
});
test
.before(async (t) => {
// Create a bucket
await functions.setUpBucket(t, "heal");
})("Start button exists", async (t) => {
const startButtonExists = elements.startButton.exists;
await t
.useRole(roles.heal)
.navigateTo("http://localhost:9090/tools/heal")
.expect(startButtonExists)
.ok();
})
.after(async (t) => {
// Cleanup created bucket
await functions.cleanUpBucket(t, "heal");
});
test("Start button can be clicked", async (t) => {
await t
.navigateTo("http://localhost:9090/tools/heal")
.click(elements.bucketNameInput)
.click(elements.bucketDropdownOption)
.click(elements.startButton);
}).after(async (t) => {
// Cleanup created bucket
await functions.cleanUpBucket(t);
});
test
.before(async (t) => {
// Create a bucket
await functions.setUpBucket(t, "heal2");
})("Start button can be clicked", async (t) => {
await t
.navigateTo("http://localhost:9090/tools/heal")
.click(elements.bucketNameInput)
.click(bucketDropdownOptionFor("heal"))
.click(elements.startButton);
})
.after(async (t) => {
// Cleanup created bucket
await functions.cleanUpBucket(t, "heal2");
});

View File

@@ -16,7 +16,10 @@
import * as roles from "../utils/roles";
import * as elements from "../utils/elements";
import { notificationEndpointsElement } from "../utils/elements-menu";
import {
notificationEndpointsElement,
settingsElement,
} from "../utils/elements-menu";
fixture("For user with Notification Endpoints permissions")
.page("http://localhost:9090")
@@ -25,20 +28,24 @@ fixture("For user with Notification Endpoints permissions")
});
test("Notification Endpoints sidebar item exists", async (t) => {
const notificationEndpointsExist = notificationEndpointsElement.exists;
await t.expect(notificationEndpointsExist).ok();
await t
.expect(settingsElement.exists)
.ok()
.click(settingsElement)
.expect(notificationEndpointsElement.exists)
.ok();
});
test("Add Notification Target button exists", async (t) => {
const addNotifTargetButtonExists = elements.addNotifTargetButton.exists;
await t
.navigateTo("http://localhost:9090/lambda/notification-endpoints")
.navigateTo("http://localhost:9090/settings/notification-endpoints")
.expect(addNotifTargetButtonExists)
.ok();
});
test("Add Notification Target button is clickable", async (t) => {
await t
.navigateTo("http://localhost:9090/lambda/notification-endpoints")
.navigateTo("http://localhost:9090/settings/notification-endpoints")
.click(elements.addNotifTargetButton);
});

View File

@@ -16,7 +16,7 @@
import * as roles from "../utils/roles";
import * as elements from "../utils/elements";
import { settingsElement } from "../utils/elements-menu";
import { configurationsElement, settingsElement } from "../utils/elements-menu";
fixture("For user with Settings permissions")
.page("http://localhost:9090")
@@ -25,14 +25,18 @@ fixture("For user with Settings permissions")
});
test("Settings sidebar item exists", async (t) => {
const settingsExist = settingsElement.exists;
await t.expect(settingsExist).ok();
await t
.expect(settingsElement.exists)
.ok()
.click(settingsElement)
.expect(configurationsElement.exists)
.ok();
});
test("Settings window exists in Settings page", async (t) => {
const settingsWindowExists = elements.settingsWindow.exists;
await t
.navigateTo("http://localhost:9090/settings")
.navigateTo("http://localhost:9090/settings/configurations")
.expect(settingsWindowExists)
.ok();
});
@@ -51,7 +55,7 @@ test("All vertical tab items exist", async (t) => {
elements.settingsLoggerWebhookTab.exists;
const settingsAuditWebhookTabExists = elements.settingsAuditWebhookTab.exists;
await t
.navigateTo("http://localhost:9090/settings")
.navigateTo("http://localhost:9090/settings/configurations")
.expect(settingsRegionTabExists)
.ok()
.expect(settingsCacheTabExists)

View File

@@ -16,7 +16,7 @@
import * as roles from "../utils/roles";
import * as elements from "../utils/elements";
import { tiersElement } from "../utils/elements-menu";
import { settingsElement, tiersElement } from "../utils/elements-menu";
fixture("For user with Tiers permissions")
.page("http://localhost:9090")
@@ -25,20 +25,24 @@ fixture("For user with Tiers permissions")
});
test("Tiers sidebar item exists", async (t) => {
const tiersExist = tiersElement.exists;
await t.expect(tiersExist).ok();
await t
.expect(settingsElement.exists)
.ok()
.click(settingsElement)
.expect(tiersElement.exists)
.ok();
});
test("Add Tier button exists", async (t) => {
const createTierButtonExists = elements.createTierButton.exists;
await t
.navigateTo("http://localhost:9090/tiers")
.navigateTo("http://localhost:9090/settings/tiers")
.expect(createTierButtonExists)
.ok();
});
test("Add Tier button is clickable", async (t) => {
await t
.navigateTo("http://localhost:9090/tiers")
.navigateTo("http://localhost:9090/settings/tiers")
.click(elements.createTierButton);
});

View File

@@ -18,10 +18,11 @@ import * as roles from "../utils/roles";
import * as elements from "../utils/elements";
import * as functions from "../utils/functions";
import {
inspectElement,
watchElement,
monitoringElement,
supportElement,
} from "../utils/elements-menu";
import { bucketDropdownOptionFor } from "../utils/elements";
fixture("For user with Watch permissions")
.page("http://localhost:9090")
@@ -29,38 +30,38 @@ fixture("For user with Watch permissions")
await t.useRole(roles.watch);
});
test("Support sidebar item exists", async (t) => {
await t.expect(supportElement.exists).ok();
test("Monitoring sidebar item exists", async (t) => {
await t.expect(monitoringElement.exists).ok();
});
test("Watch link exists in Support page", async (t) => {
await t
.expect(supportElement.exists)
.expect(monitoringElement.exists)
.ok()
.click(supportElement)
.expect(inspectElement.exists)
.click(monitoringElement)
.expect(watchElement.exists)
.ok();
});
test("Watch page can be opened", async (t) => {
await t.navigateTo("http://localhost:9090/support/inspect");
await t.navigateTo("http://localhost:9090/tools/watch");
});
test
.before(async (t) => {
// Create a bucket
await functions.setUpBucket(t);
await functions.setUpBucket(t, "watch");
})("Start button can be clicked", async (t) => {
await t
// We need to log back in after we use the admin account to create bucket,
// using the specific role we use in this module
.useRole(roles.watch)
.navigateTo("http://localhost:9090/support/inspect")
.navigateTo("http://localhost:9090/tools/watch")
.click(elements.bucketNameInput)
.click(elements.bucketDropdownOption)
.click(bucketDropdownOptionFor("watch"))
.click(elements.startButton);
})
.after(async (t) => {
// Cleanup created bucket
await functions.cleanUpBucket(t);
await functions.cleanUpBucket(t, "watch");
});

View File

@@ -42,6 +42,9 @@ export const traceElement = monitoringChildren
export const drivesElement = monitoringChildren
.find("a")
.withAttribute("href", "/tools/heal");
export const watchElement = monitoringChildren
.find("a")
.withAttribute("href", "/tools/watch");
export const bucketsElement = sidebarItem.withAttribute("href", "/buckets");
@@ -64,12 +67,21 @@ export const iamPoliciesElement = sidebarItem.withAttribute(
"href",
"/access/policies"
);
export const settingsElement = sidebarItem.withAttribute("href", "/settings");
export const notificationEndpointsElement = sidebarItem.withAttribute(
"href",
"/lambda/notification-endpoints"
);
export const tiersElement = sidebarItem.withAttribute("href", "/tiers");
export const settingsElement = Selector(".MuiPaper-root")
.find("ul")
.child("#settings");
export const settingsChildren = Selector("#settings-children");
export const configurationsElement = settingsChildren
.find("a")
.withAttribute("href", "/settings/configurations");
export const notificationEndpointsElement = settingsChildren
.find("a")
.withAttribute("href", "/settings/notification-endpoints");
export const tiersElement = settingsChildren
.find("a")
.withAttribute("href", "/settings/tiers");
export const supportElement = Selector(".MuiPaper-root")
.find("ul")
@@ -88,9 +100,6 @@ export const performanceElement = supportChildren
export const callHomeElement = supportChildren
.find("a")
.withAttribute("href", "/support/call-home");
export const inspectElement = supportChildren
.find("a")
.withAttribute("href", "/support/inspect");
export const profileElement = supportChildren
.find("a")
.withAttribute("href", "/support/profile");

View File

@@ -24,16 +24,7 @@ export const loginSubmitButton = Selector("form button");
export const closeAlertButton = Selector(
'button[class*="ModalError-closeButton"]'
);
export const manageButton = Selector("h1")
.withText(constants.TEST_BUCKET_NAME)
.parent(4)
.find("button:enabled")
.withText("Manage");
export const testBucketBrowseButton = Selector("h1")
.withText(constants.TEST_BUCKET_NAME)
.parent(4)
.find("button:enabled")
.withText("Browse");
export const uploadButton = Selector("span")
.withAttribute("aria-label", "Upload file")
.child("button:enabled");
@@ -74,9 +65,7 @@ export const addAccessRuleButton =
Selector("button:enabled").withText("Add Access Rule");
export const startDiagnosticButton =
Selector("button:enabled").withText("Start Diagnostic");
export const startNewDiagnosticButton = Selector("button:enabled").withText(
"Start New Diagnostic"
);
export const startNewDiagnosticButton = Selector("#start-new-diagnostic");
export const downloadButton = Selector("button:enabled").withText("Download");
export const startButton = Selector("button:enabled").withText("Start");
export const stopButton = Selector("button:enabled").withText("Stop");
@@ -132,10 +121,12 @@ export const groupUserCheckbox = Selector(".ReactVirtualized__Table__row span")
//----------------------------------------------------
// Dropdowns and options
//----------------------------------------------------
export const bucketDropdownOption = Selector("li").withAttribute(
"data-value",
constants.TEST_BUCKET_NAME
);
export const bucketDropdownOptionFor = (modifier) => {
return Selector("li").withAttribute(
"data-value",
`${constants.TEST_BUCKET_NAME}-${modifier}`
);
};
//----------------------------------------------------
// Text
@@ -174,47 +165,47 @@ export const settingsWindow = Selector("#settings-container");
//----------------------------------------------------
export const settingsRegionTab = Selector(".MuiTab-root").withAttribute(
"href",
"/settings/region"
"/settings/configurations/region"
);
export const settingsCacheTab = Selector(".MuiTab-root").withAttribute(
"href",
"/settings/cache"
"/settings/configurations/cache"
);
export const settingsCompressionTab = Selector(".MuiTab-root").withAttribute(
"href",
"/settings/compression"
"/settings/configurations/compression"
);
export const settingsApiTab = Selector(".MuiTab-root").withAttribute(
"href",
"/settings/api"
"/settings/configurations/api"
);
export const settingsHealTab = Selector(".MuiTab-root").withAttribute(
"href",
"/settings/heal"
"/settings/configurations/heal"
);
export const settingsScannerTab = Selector(".MuiTab-root").withAttribute(
"href",
"/settings/scanner"
"/settings/configurations/scanner"
);
export const settingsEtcdTab = Selector(".MuiTab-root").withAttribute(
"href",
"/settings/etcd"
"/settings/configurations/etcd"
);
export const settingsOpenIdTab = Selector(".MuiTab-root").withAttribute(
"href",
"/settings/identity_openid"
"/settings/configurations/identity_openid"
);
export const settingsLdapTab = Selector(".MuiTab-root").withAttribute(
"href",
"/settings/identity_ldap"
"/settings/configurations/identity_ldap"
);
export const settingsLoggerWebhookTab = Selector(".MuiTab-root").withAttribute(
"href",
"/settings/logger_webhook"
"/settings/configurations/logger_webhook"
);
export const settingsAuditWebhookTab = Selector(".MuiTab-root").withAttribute(
"href",
"/settings/audit_webhook"
"/settings/configurations/audit_webhook"
);
//----------------------------------------------------

View File

@@ -20,17 +20,35 @@ import * as constants from "./constants";
import { Selector } from "testcafe";
import { logoutItem } from "./elements-menu";
export const setUpBucket = (t) => {
export const setUpBucket = (t, modifier) => {
if (!modifier) {
modifier = "a";
}
return t
.useRole(roles.admin)
.navigateTo("http://localhost:9090/buckets")
.click(elements.createBucketButton)
.typeText(elements.bucketNameInput, constants.TEST_BUCKET_NAME)
.typeText(
elements.bucketNameInput,
`${constants.TEST_BUCKET_NAME}-${modifier}`
)
.click(elements.createBucketButton)
.click(logoutItem);
};
export const cleanUpBucket = (t) => {
export const manageButtonFor = (modifier) => {
return Selector("h1")
.withText(`${constants.TEST_BUCKET_NAME}-${modifier}`)
.parent(4)
.find("button:enabled")
.withText("Manage");
};
export const cleanUpBucket = (t, modifier) => {
if (!modifier) {
modifier = "a";
}
const manageButton = manageButtonFor(modifier);
return (
t
// useRole doesn't work here so we would need to enter the commands manually
@@ -39,14 +57,30 @@ export const cleanUpBucket = (t) => {
.typeText("#secretKey", "minioadmin")
.click(elements.loginSubmitButton)
.navigateTo("http://localhost:9090/buckets")
.click(elements.manageButton)
.click(manageButton)
.click(elements.deleteBucketButton)
.click(elements.deleteButton)
.click(logoutItem)
);
};
export const cleanUpBucketAndUploads = (t) => {
export const testBucketBrowseButtonFor = (modifier) => {
if (!modifier) {
modifier = "a";
}
return Selector("h1")
.withText(`${constants.TEST_BUCKET_NAME}-${modifier}`)
.parent(4)
.find("button:enabled")
.withText("Browse");
};
export const cleanUpBucketAndUploads = (t, modifier) => {
if (!modifier) {
modifier = "a";
}
const testBucketBrowseButton = testBucketBrowseButtonFor(modifier);
return (
t
// useRole doesn't work here so we would need to enter the commands manually
@@ -55,7 +89,7 @@ export const cleanUpBucketAndUploads = (t) => {
.typeText("#secretKey", "minioadmin")
.click(elements.loginSubmitButton)
.navigateTo("http://localhost:9090/buckets")
.click(elements.testBucketBrowseButton)
.click(testBucketBrowseButton)
.click(elements.deleteIconButtonAlt)
.click(elements.deleteButton)
.click(elements.configureBucketButton)

View File

@@ -3725,6 +3725,11 @@ bser@2.1.1:
dependencies:
node-int64 "^0.4.0"
buffer-equal-constant-time@1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819"
integrity sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=
buffer-from@^1.0.0:
version "1.1.2"
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5"
@@ -4942,6 +4947,13 @@ duplexer@^0.1.2:
resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6"
integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==
ecdsa-sig-formatter@1.0.11:
version "1.0.11"
resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf"
integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==
dependencies:
safe-buffer "^5.0.1"
ee-first@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
@@ -5108,6 +5120,11 @@ es6-iterator@~2.0.3:
es5-ext "^0.10.35"
es6-symbol "^3.1.1"
es6-promise@^4.2.8:
version "4.2.8"
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a"
integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==
es6-symbol@^3.1.1, es6-symbol@~3.1.3:
version "3.1.3"
resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18"
@@ -5770,6 +5787,11 @@ forwarded@0.2.0:
resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811"
integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==
fp-ts@^2.9.5:
version "2.11.8"
resolved "https://registry.yarnpkg.com/fp-ts/-/fp-ts-2.11.8.tgz#411cde116c446d568f5597b03352d8b3f98e8f82"
integrity sha512-WQT6rP6Jt3TxMdQB3IKzvfZKLuldumntgumLhIUhvPrukTHdWNI4JgEHY04Bd0LIOR9IQRpB+7RuxgUU0Vhmcg==
fraction.js@^4.1.2:
version "4.1.2"
resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.1.2.tgz#13e420a92422b6cf244dff8690ed89401029fbe8"
@@ -6394,6 +6416,16 @@ internmap@^1.0.0:
resolved "https://registry.yarnpkg.com/internmap/-/internmap-1.0.1.tgz#0017cc8a3b99605f0302f2b198d272e015e5df95"
integrity sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==
io-ts-types@^0.5.15:
version "0.5.16"
resolved "https://registry.yarnpkg.com/io-ts-types/-/io-ts-types-0.5.16.tgz#e9eed75371e217c97050cc507915e8eedc250946"
integrity sha512-h9noYVfY9rlbmKI902SJdnV/06jgiT2chxG6lYDxaYNp88HscPi+SBCtmcU+m0E7WT5QSwt7sIMj93+qu0FEwQ==
io-ts@^2.2.14:
version "2.2.16"
resolved "https://registry.yarnpkg.com/io-ts/-/io-ts-2.2.16.tgz#597dffa03db1913fc318c9c6df6931cb4ed808b2"
integrity sha512-y5TTSa6VP6le0hhmIyN0dqEXkrZeJLeC5KApJq6VLci3UEKF80lZ+KuoUs02RhBxNWlrqSNxzfI7otLX1Euv8Q==
ip@^1.1.0, ip@^1.1.3:
version "1.1.5"
resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a"
@@ -6683,6 +6715,14 @@ isexe@^2.0.0:
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=
isomorphic-fetch@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-3.0.0.tgz#0267b005049046d2421207215d45d6a262b8b8b4"
integrity sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA==
dependencies:
node-fetch "^2.6.1"
whatwg-fetch "^3.4.1"
istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz#189e7909d0a39fa5a3dfad5b03f71947770191d3"
@@ -7307,6 +7347,22 @@ jsonpointer@^5.0.0:
resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-5.0.0.tgz#f802669a524ec4805fa7389eadbc9921d5dc8072"
integrity sha512-PNYZIdMjVIvVgDSYKTT63Y+KZ6IZvGRNNWcxwD+GNnUz1MKPfv30J8ueCjdwcN0nDx2SlshgyB7Oy0epAzVRRg==
jsonwebtoken@^8.5.1:
version "8.5.1"
resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz#00e71e0b8df54c2121a1f26137df2280673bcc0d"
integrity sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==
dependencies:
jws "^3.2.2"
lodash.includes "^4.3.0"
lodash.isboolean "^3.0.3"
lodash.isinteger "^4.0.4"
lodash.isnumber "^3.0.3"
lodash.isplainobject "^4.0.6"
lodash.isstring "^4.0.1"
lodash.once "^4.0.0"
ms "^2.1.1"
semver "^5.6.0"
jss-plugin-camel-case@^10.8.2:
version "10.9.0"
resolved "https://registry.yarnpkg.com/jss-plugin-camel-case/-/jss-plugin-camel-case-10.9.0.tgz#4921b568b38d893f39736ee8c4c5f1c64670aaf7"
@@ -7385,6 +7441,23 @@ jss@10.9.0, jss@^10.8.2:
array-includes "^3.1.3"
object.assign "^4.1.2"
jwa@^1.4.1:
version "1.4.1"
resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.4.1.tgz#743c32985cb9e98655530d53641b66c8645b039a"
integrity sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==
dependencies:
buffer-equal-constant-time "1.0.1"
ecdsa-sig-formatter "1.0.11"
safe-buffer "^5.0.1"
jws@^3.2.2:
version "3.2.2"
resolved "https://registry.yarnpkg.com/jws/-/jws-3.2.2.tgz#001099f3639468c9414000e99995fa52fb478304"
integrity sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==
dependencies:
jwa "^1.4.1"
safe-buffer "^5.0.1"
kind-of@^6.0.2:
version "6.0.3"
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd"
@@ -7520,11 +7593,41 @@ lodash.debounce@^4.0.8:
resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168=
lodash.includes@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f"
integrity sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=
lodash.isboolean@^3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6"
integrity sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=
lodash.isequal@^4.0.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA=
lodash.isinteger@^4.0.4:
version "4.0.4"
resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343"
integrity sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=
lodash.isnumber@^3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz#3ce76810c5928d03352301ac287317f11c0b1ffc"
integrity sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=
lodash.isplainobject@^4.0.6:
version "4.0.6"
resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb"
integrity sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=
lodash.isstring@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451"
integrity sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=
lodash.memoize@^4.1.2:
version "4.1.2"
resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe"
@@ -7535,6 +7638,11 @@ lodash.merge@^4.6.2:
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==
lodash.once@^4.0.0:
version "4.1.1"
resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac"
integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=
lodash.sortby@^4.7.0:
version "4.7.0"
resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438"
@@ -7769,6 +7877,11 @@ moment@^2.10.2, moment@^2.10.3, moment@^2.14.1, moment@^2.29.1:
resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3"
integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==
monocle-ts@^2.3.5:
version "2.3.12"
resolved "https://registry.yarnpkg.com/monocle-ts/-/monocle-ts-2.3.12.tgz#73e7d59841b3843bf76eb840735a9641fdd3bd93"
integrity sha512-mf753m69aRNApcL2KCKfLRwfWbraeqQfRRgm3a8D+5lvkhCcMtVp8/vnM04Cmhsd6YXJeInMeQFFETrd7jWYww==
ms@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
@@ -7832,6 +7945,11 @@ neo-async@^2.6.2:
resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f"
integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==
newtype-ts@^0.3.4:
version "0.3.5"
resolved "https://registry.yarnpkg.com/newtype-ts/-/newtype-ts-0.3.5.tgz#5c113d34a04938d9e90061437638260ea965c490"
integrity sha512-v83UEQMlVR75yf1OUdoSFssjitxzjZlqBAjiGQ4WJaML8Jdc68LJ+BaSAXUmKY4bNzp7hygkKLYTsDi14PxI2g==
next-tick@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c"
@@ -7845,6 +7963,13 @@ no-case@^3.0.4:
lower-case "^2.0.2"
tslib "^2.0.3"
node-fetch@^2.6.1:
version "2.6.7"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad"
integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==
dependencies:
whatwg-url "^5.0.0"
node-forge@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.2.0.tgz#850cec9230f62f9a7cd8ddd08dc74b4be52573ad"
@@ -10469,16 +10594,17 @@ test-exclude@^6.0.0:
glob "^7.1.4"
minimatch "^3.0.4"
testcafe-browser-tools@2.0.16:
version "2.0.16"
resolved "https://registry.yarnpkg.com/testcafe-browser-tools/-/testcafe-browser-tools-2.0.16.tgz#8a82ea2f9560d72015c3c488bb83f6678016273f"
integrity sha512-JljbS0FboABksIMEH1L7P4ZdI82AQ8saWb/7WsxkDCOtDuHID5ZSEb/w9tqLN1+4BQaCgS5veN3lWUnfb0saEA==
testcafe-browser-tools@2.0.21:
version "2.0.21"
resolved "https://registry.yarnpkg.com/testcafe-browser-tools/-/testcafe-browser-tools-2.0.21.tgz#0e15e15dea4b5132b345386047f3a17acf9b10d9"
integrity sha512-dsaUgUY4i/VLKSexh0w8ZyvDGWd3+LfoEysN/nFCUufseiwGvvbBpsNSAV7XZN12GpExG3mCilaQDuJNBKs4CQ==
dependencies:
array-find "^1.0.0"
debug "^4.3.1"
dedent "^0.7.0"
del "^5.1.0"
execa "^3.3.0"
fs-extra "^10.0.0"
graceful-fs "^4.1.11"
linux-platform-info "^0.0.3"
lodash "^4.17.15"
@@ -10491,10 +10617,10 @@ testcafe-browser-tools@2.0.16:
read-file-relative "^1.2.0"
which-promise "^1.0.0"
testcafe-hammerhead@24.5.7:
version "24.5.7"
resolved "https://registry.yarnpkg.com/testcafe-hammerhead/-/testcafe-hammerhead-24.5.7.tgz#8d4efb45ee7543841c88452de17cd5929418bff0"
integrity sha512-4pY6GQQaCZAlOolWB2vaYZ/MIpgtmOrZeh4BVbENkbh6DDiPeOxvC0K6yZS5JfINRau5S9mzuNkm2FS7G0urSA==
testcafe-hammerhead@24.5.13:
version "24.5.13"
resolved "https://registry.yarnpkg.com/testcafe-hammerhead/-/testcafe-hammerhead-24.5.13.tgz#7eeca7f8f68b2d20ad93214ee0e93b49fb140e0b"
integrity sha512-81P9to2pXBCOy+jnyEaPcjrfKk3wOv7JmZSX3KQp0MxF12X9u6Tg0JEeTMYvnEfCeNhLRYDipAZvI+t9nfx0KA==
dependencies:
acorn-hammerhead "0.5.0"
asar "^2.0.1"
@@ -10573,6 +10699,22 @@ testcafe-legacy-api@5.1.2:
strip-bom "^2.0.0"
testcafe-hammerhead ">=19.4.0"
testcafe-reporter-dashboard@0.2.5:
version "0.2.5"
resolved "https://registry.yarnpkg.com/testcafe-reporter-dashboard/-/testcafe-reporter-dashboard-0.2.5.tgz#aa5e2b5d40d98044e7de69ae8c14cfc29f764fe6"
integrity sha512-vbK8XrpbcFAEgnfWJOfqAnlmj/wt5pXXER/OSYI9RzSw+uwu8voLWbKcUAcnjltk0AM4c0wvI0DhjKmops2y2Q==
dependencies:
es6-promise "^4.2.8"
fp-ts "^2.9.5"
io-ts "^2.2.14"
io-ts-types "^0.5.15"
isomorphic-fetch "^3.0.0"
jsonwebtoken "^8.5.1"
monocle-ts "^2.3.5"
newtype-ts "^0.3.4"
semver "^5.6.0"
uuid "3.3.3"
testcafe-reporter-json@^2.1.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/testcafe-reporter-json/-/testcafe-reporter-json-2.2.0.tgz#bb061e054489abdb62add745dd979896b618ea91"
@@ -10593,15 +10735,15 @@ testcafe-reporter-spec@^2.1.1:
resolved "https://registry.yarnpkg.com/testcafe-reporter-spec/-/testcafe-reporter-spec-2.1.1.tgz#8156fced0f5132486559ad560bc80676469275ec"
integrity sha1-gVb87Q9RMkhlWa1WC8gGdkaSdew=
testcafe-reporter-xunit@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/testcafe-reporter-xunit/-/testcafe-reporter-xunit-2.1.0.tgz#e6d66c572ce15af266706af0fd610b2a841dd443"
integrity sha1-5tZsVyzhWvJmcGrw/WELKoQd1EM=
testcafe-reporter-xunit@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/testcafe-reporter-xunit/-/testcafe-reporter-xunit-2.2.1.tgz#674b6551bec88829d4ed08af43e7838793cf714e"
integrity sha512-ge1msi8RyNVyK0QrsmC79zedV7jHasKpBPeOUZd/ORpbYLeYDnprjIeOuIukw0knnTieeYsOK29/ZD+UI7/tdw==
testcafe@^1.17.1:
version "1.17.1"
resolved "https://registry.yarnpkg.com/testcafe/-/testcafe-1.17.1.tgz#1f29ecaaba4a4eaf3b4b662f6f21f8b5614a6615"
integrity sha512-G+IqL28PE9wzNKcLjLCjX3z3/KXpzNs0FNC63Y7dXcXx23qlx+yz+Abyh91CIzeiwtXDZX+xMXDYYLtPQLfhlQ==
testcafe@^1.18.2:
version "1.18.2"
resolved "https://registry.yarnpkg.com/testcafe/-/testcafe-1.18.2.tgz#7d769454245a1d889922c8c3a148a2eeff42adf2"
integrity sha512-A9cPNtf4v4gacvaGX5mBmT6ctCmXmYQxYJ51TOSRfnApxVcfjuLSwZNC3p49G/6zuVhe6Xh/pwQJt7iZOdLcaQ==
dependencies:
"@babel/core" "^7.12.1"
"@babel/plugin-proposal-async-generator-functions" "^7.12.1"
@@ -10678,14 +10820,15 @@ testcafe@^1.17.1:
semver "^5.6.0"
source-map-support "^0.5.16"
strip-bom "^2.0.0"
testcafe-browser-tools "2.0.16"
testcafe-hammerhead "24.5.7"
testcafe-browser-tools "2.0.21"
testcafe-hammerhead "24.5.13"
testcafe-legacy-api "5.1.2"
testcafe-reporter-dashboard "0.2.5"
testcafe-reporter-json "^2.1.0"
testcafe-reporter-list "^2.1.0"
testcafe-reporter-minimal "^2.1.0"
testcafe-reporter-spec "^2.1.1"
testcafe-reporter-xunit "^2.1.0"
testcafe-reporter-xunit "^2.2.1"
time-limit-promise "^1.0.2"
tmp "0.0.28"
tree-kill "^1.2.2"
@@ -10806,6 +10949,11 @@ tr46@^2.1.0:
dependencies:
punycode "^2.1.1"
tr46@~0.0.3:
version "0.0.3"
resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=
tree-kill@^1.2.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc"
@@ -11050,6 +11198,11 @@ utils-merge@1.0.1:
resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=
uuid@3.3.3:
version "3.3.3"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.3.tgz#4568f0216e78760ee1dbf3a4d2cf53e224112866"
integrity sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==
uuid@^8.3.2:
version "8.3.2"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
@@ -11125,6 +11278,11 @@ webauth@^1.1.0:
resolved "https://registry.yarnpkg.com/webauth/-/webauth-1.1.0.tgz#64704f6b8026986605bc3ca629952e6e26fdd100"
integrity sha1-ZHBPa4AmmGYFvDymKZUubib90QA=
webidl-conversions@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=
webidl-conversions@^4.0.2:
version "4.0.2"
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad"
@@ -11278,7 +11436,7 @@ whatwg-encoding@^1.0.5:
dependencies:
iconv-lite "0.4.24"
whatwg-fetch@^3.6.2:
whatwg-fetch@^3.4.1, whatwg-fetch@^3.6.2:
version "3.6.2"
resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz#dced24f37f2624ed0281725d51d0e2e3fe677f8c"
integrity sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA==
@@ -11288,6 +11446,14 @@ whatwg-mimetype@^2.3.0:
resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf"
integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==
whatwg-url@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d"
integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0=
dependencies:
tr46 "~0.0.3"
webidl-conversions "^3.0.0"
whatwg-url@^7.0.0:
version "7.1.0"
resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-7.1.0.tgz#c2c492f1eca612988efd3d2266be1b9fc6170d06"