Automate end-to-end permission testing (#1383)

Automate permission testing
This commit is contained in:
Kaan Kabalak
2022-01-14 17:04:40 -08:00
committed by GitHub
parent 0ba5db58ec
commit 479fa34542
44 changed files with 3713 additions and 87 deletions

47
.github/workflows/permissions.yml vendored Normal file
View File

@@ -0,0 +1,47 @@
name: "Front-End Permission Tests"
on:
pull_request:
branches:
- master
push:
branches:
- master
jobs:
permissions:
name: Front-End Permission Tests
runs-on: ${{ matrix.os }}
strategy:
matrix:
go-version: [1.17.x]
os: [ubuntu-latest]
steps:
- name: Set up Go ${{ matrix.go-version }} on ${{ matrix.os }}
uses: actions/setup-go@v2
with:
go-version: ${{ matrix.go-version }}
id: go
- name: Check out code into the Go module directory
uses: actions/checkout@v2
- name: Build Console on ${{ matrix.os }}
env:
GO111MODULE: on
GOOS: linux
run: |
make console
- name: Start Console, front-end app and initialize users/policies
run: |
(./console server && sleep 180) & (cd portal-ui && yarn && yarn start && sleep 180) & (make initialize-permissions && sleep 180)
- name: Run TestCafe Tests
uses: DevExpress/testcafe-action@latest
with:
args: '"chrome:headless" portal-ui/tests/permissions/ --skip-js-errors'
- name: Clean up users & policies
run: |
make cleanup-permissions

View File

@@ -68,6 +68,19 @@ test-integration:
@(GO111MODULE=on go test -race -v github.com/minio/console/integration/...)
@(docker stop minio)
test-permissions:
@(docker run -d --name minio --rm -p 9000:9000 quay.io/minio/minio:latest server /data{1...4})
@(env bash $(PWD)/portal-ui/tests/scripts/permissions.sh)
@(docker stop minio)
initialize-permissions:
@(docker run -d --name minio --rm -p 9000:9000 quay.io/minio/minio:latest server /data{1...4})
@(env bash $(PWD)/portal-ui/tests/scripts/initialize-env.sh)
cleanup-permissions:
@(env bash $(PWD)/portal-ui/tests/scripts/cleanup-env.sh)
@(docker stop minio)
test:
@(GO111MODULE=on go test -race -v github.com/minio/console/restapi/...)

View File

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

View File

@@ -0,0 +1 @@
1642030641

View File

@@ -0,0 +1,62 @@
// This file is part of MinIO Console Server
// Copyright (c) 2022 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import * as roles from "../utils/roles";
import * as elements from "../utils/elements";
fixture("For user with Admin permissions")
.page("http://localhost:5005")
.beforeEach(async (t) => {
await t.useRole(roles.admin);
});
test("All sidebar items exist", async (t) => {
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.toolsElement.exists;
const licenseExists = elements.licenseElement.exists;
await t
.expect(dashboardExists)
.ok()
.expect(bucketsExist)
.ok()
.expect(usersExist)
.ok()
.expect(groupsExist)
.ok()
.expect(serviceAcctsExist)
.ok()
.expect(iamPoliciesExist)
.ok()
.expect(settingsExist)
.ok()
.expect(notificationEndpointsExist)
.ok()
.expect(tiersExist)
.ok()
.expect(toolsExist)
.ok()
.expect(licenseExists)
.ok();
});

View File

@@ -0,0 +1,86 @@
// This file is part of MinIO Console Server
// Copyright (c) 2022 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import * as roles from "../utils/roles";
import * as elements from "../utils/elements";
import * as functions from "../utils/functions";
fixture("For user with Bucket Assign Policy permissions")
.page("http://localhost:5005")
.beforeEach(async (t) => {
await t.useRole(roles.bucketAssignPolicy);
});
// Bucket assign policy permissions
test("Buckets sidebar item exists", async (t) => {
const bucketsExist = elements.bucketsElement.exists;
await t.expect(bucketsExist).ok();
});
test.before(async (t) => {
// Create a bucket
await functions.setUpBucket(t);
})("A readonly policy can be assigned to a bucket", 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.bucketAssignPolicy)
.navigateTo("http://localhost:5005/buckets")
.click(elements.manageButton)
.click(elements.bucketAccessRulesTab)
.click(elements.addAccessRuleButton)
.typeText(elements.bucketsPrefixInput, "readonlytest")
.click(elements.bucketsAccessInput)
.click(elements.bucketsAccessReadOnlyInput)
.click(elements.saveButton);
});
test("A writeonly policy can be assigned to a bucket", async (t) => {
await t
.navigateTo("http://localhost:5005/buckets")
.click(elements.manageButton)
.click(elements.bucketAccessRulesTab)
.click(elements.addAccessRuleButton)
.typeText(elements.bucketsPrefixInput, "writeonlytest")
.click(elements.bucketsAccessInput)
.click(elements.bucketsAccessWriteOnlyInput)
.click(elements.saveButton);
});
test("A readwrite policy can be assigned to a bucket", async (t) => {
await t
.navigateTo("http://localhost:5005/buckets")
.click(elements.manageButton)
.click(elements.bucketAccessRulesTab)
.click(elements.addAccessRuleButton)
.typeText(elements.bucketsPrefixInput, "readwritetest")
.click(elements.bucketsAccessInput)
.click(elements.bucketsAccessReadWriteInput)
.click(elements.saveButton);
});
test("Previously assigned policy to a bucket can be deleted", async (t) => {
await t
.navigateTo("http://localhost:5005/buckets")
.click(elements.manageButton)
.click(elements.bucketAccessRulesTab)
.click(elements.deleteIconButtonAlt)
.click(elements.deleteButton)
.click(elements.logoutItem);
}).after(async (t) => {
// Cleanup created bucket
await functions.cleanUpBucket(t);
});

View File

@@ -0,0 +1,66 @@
// This file is part of MinIO Console Server
// Copyright (c) 2022 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import * as roles from "../utils/roles";
import * as elements from "../utils/elements";
import * as functions from "../utils/functions";
fixture("For user with Bucket Read permissions")
.page("http://localhost:5005")
.beforeEach(async (t) => {
await t.useRole(roles.bucketRead);
});
test("Buckets sidebar item exists", async (t) => {
const bucketsExist = elements.bucketsElement.exists;
await t.expect(bucketsExist).ok();
});
test.before(async (t) => {
// Create a bucket
await functions.setUpBucket(t);
})("Browse button exists", async (t) => {
const browseExists = elements.browseButton.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();
});
test("Bucket access is set to R", async (t) => {
await t.expect(elements.bucketAccessText.innerText).eql("Access: R");
});
test
.before(async (t) => {
await t
.useRole(roles.admin)
.navigateTo("http://localhost:5005/buckets")
.click(elements.browseButton)
// Upload object to bucket
.setFilesToUpload(elements.uploadInput, "../uploads/test.txt")
.click(elements.logoutItem);
})("Object list table is enabled", async (t) => {
const bucketsTableExists = elements.table.exists;
await t
.useRole(roles.bucketRead)
.click(elements.browseButton)
.expect(bucketsTableExists)
.ok();
})
.after(async (t) => {
// Cleanup created bucket and corresponding uploads
await functions.cleanUpBucketAndUploads(t);
});

View File

@@ -0,0 +1,80 @@
// This file is part of MinIO Console Server
// Copyright (c) 2022 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import * as roles from "../utils/roles";
import * as elements from "../utils/elements";
import * as functions from "../utils/functions";
fixture("For user with Bucket Write permissions")
.page("http://localhost:5005")
.beforeEach(async (t) => {
await t.useRole(roles.bucketWrite);
});
test("Buckets sidebar item exists", async (t) => {
const bucketsExist = elements.bucketsElement.with({ boundTestRun: t }).exists;
await t.expect(bucketsExist).ok();
});
test.before(async (t) => {
// Create a bucket
await functions.setUpBucket(t);
})("Browse button exists", async (t) => {
const browseExists = elements.browseButton.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
.useRole(roles.bucketWrite)
.navigateTo("http://localhost:5005/buckets")
.expect(browseExists)
.ok();
});
test("Bucket access is set to W", async (t) => {
await t
.navigateTo("http://localhost:5005/buckets")
.expect(elements.bucketAccessText.innerText)
.eql("Access: W");
});
test("Upload button exists", async (t) => {
const uploadExists = elements.uploadButton.exists;
await t
.navigateTo("http://localhost:5005/buckets")
.click(elements.browseButton)
.expect(uploadExists)
.ok();
});
test("Object can be uploaded to a bucket", async (t) => {
await t
.navigateTo("http://localhost:5005/buckets")
.click(elements.browseButton)
// Upload object to bucket
.setFilesToUpload(elements.uploadInput, "../uploads/test.txt");
});
test("Object list table is disabled", async (t) => {
const disabledBucketsTableExists = elements.bucketsTableDisabled.exists;
await t
.navigateTo("http://localhost:5005/buckets")
.click(elements.browseButton)
.expect(disabledBucketsTableExists)
.ok();
}).after(async (t) => {
// Cleanup created bucket and corresponding uploads
await functions.cleanUpBucketAndUploads(t);
});

View File

@@ -0,0 +1,31 @@
// This file is part of MinIO Console Server
// Copyright (c) 2022 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import * as roles from "../utils/roles";
import * as elements from "../utils/elements";
fixture("For user with Dashboard permissions")
.page("http://localhost:5005")
.beforeEach(async (t) => {
await t.useRole(roles.dashboard);
});
test("Dashboard sidebar item exists", async (t) => {
const dashboardExists = elements.dashboardElement.exists;
await t.expect(dashboardExists).ok();
});
// TODO: Display extended metrics

View File

@@ -0,0 +1,84 @@
// This file is part of MinIO Console Server
// Copyright (c) 2022 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import * as roles from "../utils/roles";
import * as elements from "../utils/elements";
fixture("For user with Diagnostics permissions")
.page("http://localhost:9090")
.beforeEach(async (t) => {
await t.useRole(roles.diagnostics);
});
test("Tools sidebar item exists", async (t) => {
const toolsExist = elements.toolsElement.exists;
await t.expect(toolsExist).ok();
});
test("Diagnostics link exists in Tools page", async (t) => {
const diagnosticsLinkExists = elements.diagnosticsLink.exists;
await t.click(elements.toolsElement).expect(diagnosticsLinkExists).ok();
});
test("Diagnostics page can be opened", async (t) => {
await t.navigateTo("http://localhost:9090/tools/diagnostics");
});
test("Start Diagnostic button exists", async (t) => {
const startDiagnosticExists = elements.startDiagnosticButton.exists;
await t
.navigateTo("http://localhost:9090/tools/diagnostics")
.expect(startDiagnosticExists)
.ok();
});
test("Start Diagnostic button can be clicked", async (t) => {
await t
.navigateTo("http://localhost:9090/tools/diagnostics")
.click(elements.startDiagnosticButton);
});
// TODO: Fix test failing sporadically on GitHub Actions
// test("Download button exists after Diagnostic is completed", async (t) => {
// const downloadExists = elements.downloadButton.exists;
// await t
// .navigateTo("http://localhost:9090/tools/diagnostics")
// .click(elements.startDiagnosticButton)
// .expect(downloadExists).ok();
// });
// test("Download button is clickable after Diagnostic is completed", async (t) => {
// await t
// .navigateTo("http://localhost:9090/tools/diagnostics")
// .click(elements.startDiagnosticButton)
// .click(elements.downloadButton);
// });
test("Start New Diagnostic button exists after Diagnostic is completed", async (t) => {
const startNewDiagnosticButtonExists = elements.startNewDiagnosticButton.exists;
await t
.navigateTo("http://localhost:9090/tools/diagnostics")
.click(elements.startDiagnosticButton)
.expect(startNewDiagnosticButtonExists).ok();
});
test("Start New Diagnostic button is clickable after Diagnostic is completed", async (t) => {
await t
.navigateTo("http://localhost:9090/tools/diagnostics")
.click(elements.startDiagnosticButton)
.click(elements.startNewDiagnosticButton);
});

View File

@@ -0,0 +1,119 @@
// This file is part of MinIO Console Server
// Copyright (c) 2022 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import * as roles from "../utils/roles";
import * as elements from "../utils/elements";
import * as constants from "../utils/constants";
import * as functions from "../utils/functions";
import { Selector } from "testcafe";
const groupsListItem = Selector(".ReactVirtualized__Table__rowColumn").withText(
constants.TEST_GROUP_NAME
);
fixture("For user with Groups permissions")
.page("http://localhost:5005")
.beforeEach(async (t) => {
await t.useRole(roles.groups);
});
test("Groups sidebar item exists", async (t) => {
const groupsExist = elements.groupsElement.exists;
await t.expect(groupsExist).ok();
});
test("Create Group button exists", async (t) => {
const createGroupButtonExists = elements.createGroupButton.exists;
await t
.navigateTo("http://localhost:5005/groups")
.expect(createGroupButtonExists)
.ok();
});
test("Create Group button is clickable", async (t) => {
await t
.navigateTo("http://localhost:5005/groups")
.click(elements.createGroupButton);
});
test("Group Name input exists in the Create Group modal", async (t) => {
const groupNameInputExists = elements.groupNameInput.exists;
await t
.navigateTo("http://localhost:5005/groups")
.click(elements.createGroupButton)
.expect(groupNameInputExists)
.ok();
});
test("Users table exists in the Create Group modal", async (t) => {
const createGroupUserTableExists = elements.table.exists;
await t
.navigateTo("http://localhost:5005/groups")
.click(elements.createGroupButton)
.expect(createGroupUserTableExists)
.ok();
});
test.before(async (t) => {
// A user must be created as we need to choose a user from the dropdown
await functions.createUser(t);
})(
"Create Group modal can be submitted after inputs are entered",
async (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
await t
.useRole(roles.groups)
.navigateTo("http://localhost:5005/groups")
.click(elements.createGroupButton)
.typeText(elements.groupNameInput, constants.TEST_GROUP_NAME)
.typeText(elements.filterUserInput, constants.TEST_USER_NAME)
.click(elements.groupUserCheckbox)
.click(elements.saveButton);
}
);
test("Groups table exists", async (t) => {
const groupsTableExists = elements.table.exists;
await t
.navigateTo("http://localhost:5005/groups")
.expect(groupsTableExists)
.ok();
});
test("Created Group can be disabled and enabled back", async (t) => {
await t
.navigateTo("http://localhost:5005/groups")
.click(groupsListItem)
.click(elements.switchInput)
.expect(elements.groupStatusText.innerText)
.eql("Disabled")
.click(elements.switchInput)
.expect(elements.groupStatusText.innerText)
.eql("Enabled");
});
test("Created Group can be viewed and deleted", async (t) => {
await t
.navigateTo("http://localhost:5005/groups")
.click(groupsListItem)
.click(elements.editMembersButton)
.typeText(elements.filterUserInput, constants.TEST_USER_NAME)
.click(elements.groupUserCheckbox)
.click(elements.saveButton)
.click(elements.deleteGroupIconButton)
.click(elements.deleteButton);
});

View File

@@ -0,0 +1,62 @@
// This file is part of MinIO Console Server
// Copyright (c) 2022 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import * as roles from "../utils/roles";
import * as elements from "../utils/elements";
import * as functions from "../utils/functions";
fixture("For user with Heal permissions")
.page("http://localhost:9090")
.beforeEach(async (t) => {
await t.useRole(roles.heal);
});
test("Tools sidebar item exists", async (t) => {
const toolsExist = elements.toolsElement.exists;
await t.expect(toolsExist).ok();
});
test("Heal link exists in Tools page", async (t) => {
const healLinkExists = elements.healLink.exists;
await t.click(elements.toolsElement).expect(healLinkExists).ok();
});
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("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);
});

View File

@@ -0,0 +1,105 @@
// This file is part of MinIO Console Server
// Copyright (c) 2022 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import * as roles from "../utils/roles";
import * as elements from "../utils/elements";
import * as constants from "../utils/constants";
import { Selector } from "testcafe";
const iamPolicyListItem = Selector(
".ReactVirtualized__Table__rowColumn"
).withText(constants.TEST_IAM_POLICY_NAME);
const iamPolicyDelete = iamPolicyListItem
.nextSibling()
.child("button")
.withAttribute("aria-label", "delete");
fixture("For user with IAM Policies permissions")
.page("http://localhost:5005")
.beforeEach(async (t) => {
await t.useRole(roles.iamPolicies);
});
test("IAM Policies sidebar item exists", async (t) => {
const iamPoliciesExist = elements.iamPoliciesElement.exists;
await t.expect(iamPoliciesExist).ok();
});
test("Create Policy button exists", async (t) => {
const createPolicyButtonExists = elements.createPolicyButton.exists;
await t
.navigateTo("http://localhost:5005/policies")
.expect(createPolicyButtonExists)
.ok();
});
test("Create Policy button is clickable", async (t) => {
await t
.navigateTo("http://localhost:5005/policies")
.click(elements.createPolicyButton);
});
test("Policy Name input exists in the Create Policy modal", async (t) => {
const policyNameInputExists = elements.createPolicyName.exists;
await t
.navigateTo("http://localhost:5005/policies")
.click(elements.createPolicyButton)
.expect(policyNameInputExists)
.ok();
});
test("Policy textfield exists in the Create Policy modal", async (t) => {
const policyTextfieldExists = elements.createPolicyTextfield.exists;
await t
.navigateTo("http://localhost:5005/policies")
.click(elements.createPolicyButton)
.expect(policyTextfieldExists)
.ok();
});
test("Create Policy modal can be submitted after inputs are entered", async (t) => {
await t
.navigateTo("http://localhost:5005/policies")
.click(elements.createPolicyButton)
.typeText(elements.createPolicyName, constants.TEST_IAM_POLICY_NAME)
.typeText(elements.createPolicyTextfield, constants.TEST_IAM_POLICY, { paste: true })
.click(elements.saveButton);
}).after(async (t) => {
// Clean up created policy
await t
.navigateTo("http://localhost:5005/policies")
.typeText(elements.searchResourceInput, constants.TEST_IAM_POLICY_NAME)
.click(iamPolicyDelete)
.click(elements.deleteButton);
});
test("Created Policy can be viewed and deleted", async (t) => {
const iamPolicyListItemExists = iamPolicyListItem.exists;
await t
.navigateTo("http://localhost:5005/policies")
.click(elements.createPolicyButton)
.typeText(elements.createPolicyName, constants.TEST_IAM_POLICY_NAME)
.typeText(elements.createPolicyTextfield, constants.TEST_IAM_POLICY, { paste: true })
.click(elements.saveButton)
.typeText(elements.searchResourceInput, constants.TEST_IAM_POLICY_NAME)
.expect(iamPolicyListItemExists)
.ok()
.click(iamPolicyDelete)
.click(elements.deleteButton)
.expect(iamPolicyListItemExists)
.notOk();
});

View File

@@ -0,0 +1,47 @@
// This file is part of MinIO Console Server
// Copyright (c) 2022 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import * as roles from "../utils/roles";
import * as elements from "../utils/elements";
fixture("For user with Logs permissions")
.page("http://localhost:5005")
.beforeEach(async (t) => {
await t.useRole(roles.logs);
});
test("Tools sidebar item exists", async (t) => {
const toolsExist = elements.toolsElement.exists;
await t.expect(toolsExist).ok();
});
test("Logs link exists in Tools page", async (t) => {
const logsLinkExists = elements.logsLink.exists;
await t.click(elements.toolsElement).expect(logsLinkExists).ok();
});
test("Logs page can be opened", async (t) => {
await t
.navigateTo("http://localhost:5005/tools/logs");
});
test("Log window exists in Logs page", async (t) => {
const logWindowExists = elements.logWindow.exists;
await t
.navigateTo("http://localhost:5005/tools/logs")
.expect(logWindowExists)
.ok();
});

View File

@@ -0,0 +1,44 @@
// This file is part of MinIO Console Server
// Copyright (c) 2022 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import * as roles from "../utils/roles";
import * as elements from "../utils/elements";
fixture("For user with Notification Endpoints permissions")
.page("http://localhost:5005")
.beforeEach(async (t) => {
await t.useRole(roles.notificationEndpoints);
});
test("Notification Endpoints sidebar item exists", async (t) => {
const notificationEndpointsExist =
elements.notificationEndpointsElement.exists;
await t.expect(notificationEndpointsExist).ok();
});
test("Add Notification Target button exists", async (t) => {
const addNotifTargetButtonExists = elements.addNotifTargetButton.exists;
await t
.navigateTo("http://localhost:5005/notification-endpoints")
.expect(addNotifTargetButtonExists)
.ok();
});
test("Add Notification Target button is clickable", async (t) => {
await t
.navigateTo("http://localhost:5005/notification-endpoints")
.click(elements.addNotifTargetButton);
});

View File

@@ -0,0 +1,76 @@
// This file is part of MinIO Console Server
// Copyright (c) 2022 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import * as roles from "../utils/roles";
import * as elements from "../utils/elements";
fixture("For user with Settings permissions")
.page("http://localhost:5005")
.beforeEach(async (t) => {
await t.useRole(roles.settings);
});
test("Settings sidebar item exists", async (t) => {
const settingsExist = elements.settingsElement.exists;
await t.expect(settingsExist).ok();
});
test("Settings window exists in Settings page", async (t) => {
const settingsWindowExists = elements.settingsWindow.exists;
await t
.navigateTo("http://localhost:5005/settings")
.expect(settingsWindowExists)
.ok();
});
test("All vertical tab items exist", async (t) => {
const settingsRegionTabExists = elements.settingsRegionTab.exists;
const settingsCacheTabExists = elements.settingsCacheTab.exists;
const settingsCompressionTabExists = elements.settingsCompressionTab.exists;
const settingsApiTabExists = elements.settingsApiTab.exists;
const settingsHealTabExists = elements.settingsHealTab.exists;
const settingsScannerTabExists = elements.settingsScannerTab.exists;
const settingsEtcdTabExists = elements.settingsEtcdTab.exists;
const settingsOpenIdTabExists = elements.settingsOpenIdTab.exists;
const settingsLdapTabExists = elements.settingsLdapTab.exists;
const settingsLoggerWebhookTabExists =
elements.settingsLoggerWebhookTab.exists;
const settingsAuditWebhookTabExists = elements.settingsAuditWebhookTab.exists;
await t
.navigateTo("http://localhost:5005/settings")
.expect(settingsRegionTabExists)
.ok()
.expect(settingsCacheTabExists)
.ok()
.expect(settingsCompressionTabExists)
.ok()
.expect(settingsApiTabExists)
.ok()
.expect(settingsHealTabExists)
.ok()
.expect(settingsScannerTabExists)
.ok()
.expect(settingsEtcdTabExists)
.ok()
.expect(settingsOpenIdTabExists)
.ok()
.expect(settingsLdapTabExists)
.ok()
.expect(settingsLoggerWebhookTabExists)
.ok()
.expect(settingsAuditWebhookTabExists)
.ok();
});

View File

@@ -0,0 +1,43 @@
// This file is part of MinIO Console Server
// Copyright (c) 2022 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import * as roles from "../utils/roles";
import * as elements from "../utils/elements";
fixture("For user with Tiers permissions")
.page("http://localhost:5005")
.beforeEach(async (t) => {
await t.useRole(roles.tiers);
});
test("Tiers sidebar item exists", async (t) => {
const tiersExist = elements.tiersElement.exists;
await t.expect(tiersExist).ok();
});
test("Add Tier button exists", async (t) => {
const createTierButtonExists = elements.createTierButton.exists;
await t
.navigateTo("http://localhost:5005/tiers")
.expect(createTierButtonExists)
.ok();
});
test("Add Tier button is clickable", async (t) => {
await t
.navigateTo("http://localhost:5005/tiers")
.click(elements.createTierButton);
});

View File

@@ -0,0 +1,60 @@
// This file is part of MinIO Console Server
// Copyright (c) 2022 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import * as roles from "../utils/roles";
import * as elements from "../utils/elements";
fixture("For user with Trace permissions")
.page("http://localhost:9090")
.beforeEach(async (t) => {
await t.useRole(roles.trace);
});
test("Tools sidebar item exists", async (t) => {
const toolsExist = elements.toolsElement.exists;
await t.expect(toolsExist).ok();
});
test("Trace link exists in Tools page", async (t) => {
const traceLinkExists = elements.traceLink.exists;
await t.click(elements.toolsElement).expect(traceLinkExists).ok();
});
test("Trace page can be opened", async (t) => {
await t
.navigateTo("http://localhost:9090/tools/trace");
});
test("Start button can be clicked", async (t) => {
await t
.navigateTo("http://localhost:9090/tools/trace")
.click(elements.startButton);
});
test("Stop button appears after Start button has been clicked", async (t) => {
const stopButtonExists = elements.stopButton.exists;
await t
.navigateTo("http://localhost:9090/tools/trace")
.click(elements.startButton)
.expect(stopButtonExists).ok();
});
test("Stop button can be clicked after Start button has been clicked", async (t) => {
await t
.navigateTo("http://localhost:9090/tools/trace")
.click(elements.startButton)
.click(elements.stopButton);
});

View File

@@ -0,0 +1,102 @@
// This file is part of MinIO Console Server
// Copyright (c) 2022 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import * as roles from "../utils/roles";
import * as elements from "../utils/elements";
import * as constants from "../utils/constants";
import { Selector } from "testcafe";
const userListItem = Selector(".ReactVirtualized__Table__rowColumn").withText(
constants.TEST_USER_NAME
);
const userDeleteIconButton = userListItem
.nextSibling()
.child("button")
.withAttribute("aria-label", "delete");
fixture("For user with Users permissions")
.page("http://localhost:5005")
.beforeEach(async (t) => {
await t.useRole(roles.users);
});
test("Users sidebar item exists", async (t) => {
const usersExist = elements.usersElement.exists;
await t.expect(usersExist).ok();
});
test("Create User button exists", async (t) => {
const createUserButtonExists = elements.createUserButton.exists;
await t
.navigateTo("http://localhost:5005/users")
.expect(createUserButtonExists)
.ok();
});
test("Create User button is clickable", async (t) => {
await t
.navigateTo("http://localhost:5005/users")
.click(elements.createUserButton);
});
test("Access Key input exists in the Create User modal", async (t) => {
const accessKeyInputExists = elements.usersAccessKeyInput.exists;
await t
.navigateTo("http://localhost:5005/users")
.click(elements.createUserButton)
.expect(accessKeyInputExists)
.ok();
});
test("Secret Key input exists in the Create User modal", async (t) => {
const secretKeyInputExists = elements.usersSecretKeyInput.exists;
await t
.navigateTo("http://localhost:5005/users")
.click(elements.createUserButton)
.expect(secretKeyInputExists)
.ok();
});
test("Create User modal can be submitted after inputs are entered", async (t) => {
await t
.navigateTo("http://localhost:5005/users")
.click(elements.createUserButton)
.typeText(elements.usersAccessKeyInput, constants.TEST_USER_NAME)
.typeText(elements.usersSecretKeyInput, constants.TEST_PASSWORD)
.click(elements.saveButton);
});
test("Users table exists", async (t) => {
const usersTableExists = elements.table.exists;
await t
.navigateTo("http://localhost:5005/users")
.expect(usersTableExists)
.ok();
});
test("Created User can be viewed and deleted", async (t) => {
const userListItemExists = userListItem.exists;
await t
.navigateTo("http://localhost:5005/users")
.typeText(elements.searchResourceInput, constants.TEST_USER_NAME)
.expect(userListItemExists)
.ok()
.click(userDeleteIconButton)
.click(elements.deleteButton)
.expect(userListItemExists)
.notOk();
});

View File

@@ -0,0 +1,56 @@
// This file is part of MinIO Console Server
// Copyright (c) 2022 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import * as roles from "../utils/roles";
import * as elements from "../utils/elements";
import * as functions from "../utils/functions";
fixture("For user with Watch permissions")
.page("http://localhost:9090")
.beforeEach(async (t) => {
await t.useRole(roles.watch);
});
test("Tools sidebar item exists", async (t) => {
const toolsExist = elements.toolsElement.exists;
await t.expect(toolsExist).ok();
});
test("Watch link exists in Tools page", async (t) => {
const watchLinkExists = elements.watchLink.exists;
await t.click(elements.toolsElement).expect(watchLinkExists).ok();
});
test("Watch page can be opened", async (t) => {
await t.navigateTo("http://localhost:9090/tools/watch");
});
test.before(async (t) => {
// Create a bucket
await functions.setUpBucket(t);
})("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/tools/watch")
.click(elements.bucketNameInput)
.click(elements.bucketDropdownOption)
.click(elements.startButton);
}).after(async (t) => {
// Cleanup created bucket
await functions.cleanUpBucket(t);
});

View File

@@ -0,0 +1,18 @@
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"s3:PutBucketPolicy",
"s3:DeleteBucketPolicy",
"s3:GetBucketPolicy",
"s3:ListBucket"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::*"
],
"Sid": ""
}
]
}

View File

@@ -0,0 +1,20 @@
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"s3:ListMultipartUploadParts",
"s3:ListBucketMultipartUploads",
"s3:ListBucket",
"s3:HeadBucket",
"s3:GetObject",
"s3:GetBucketLocation"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::*"
],
"Sid": ""
}
]
}

View File

@@ -0,0 +1,19 @@
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"s3:AbortMultipartUpload",
"s3:CreateBucket",
"s3:PutObject",
"s3:DeleteObject",
"s3:DeleteBucket"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::*"
],
"Sid": ""
}
]
}

View File

@@ -0,0 +1,11 @@
{
"Version": "2012-10-17",
"Statement": [{
"Action": [
"admin:ServerInfo"
],
"Effect": "Allow",
"Sid": ""
}
]
}

View File

@@ -0,0 +1,11 @@
{
"Version": "2012-10-17",
"Statement": [{
"Action": [
"admin:OBDInfo"
],
"Effect": "Allow",
"Sid": ""
}
]
}

View File

@@ -0,0 +1,18 @@
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"admin:ListGroups",
"admin:AddUserToGroup",
"admin:EnableGroup",
"admin:DisableGroup",
"admin:RemoveUserFromGroup",
"admin:GetGroup",
"admin:ListUsers"
],
"Effect": "Allow",
"Sid": ""
}
]
}

View File

@@ -0,0 +1,16 @@
{
"Version": "2012-10-17",
"Statement": [
{
"Action": ["admin:Heal"],
"Effect": "Allow",
"Sid": ""
},
{
"Action": ["s3:ListBucket"],
"Effect": "Allow",
"Resource": ["arn:aws:s3:::*"],
"Sid": ""
}
]
}

View File

@@ -0,0 +1,15 @@
{
"Version": "2012-10-17",
"Statement": [{
"Action": [
"admin:GetPolicy",
"admin:DeletePolicy",
"admin:CreatePolicy",
"admin:AttachUserOrGroupPolicy",
"admin:ListUserPolicies"
],
"Effect": "Allow",
"Sid": ""
}
]
}

View File

@@ -0,0 +1,11 @@
{
"Version": "2012-10-17",
"Statement": [{
"Action": [
"admin:ConsoleLog"
],
"Effect": "Allow",
"Sid": ""
}
]
}

View File

@@ -0,0 +1,11 @@
{
"Version": "2012-10-17",
"Statement": [{
"Action": [
"admin:ConfigUpdate"
],
"Effect": "Allow",
"Sid": ""
}
]
}

View File

@@ -0,0 +1,11 @@
{
"Version": "2012-10-17",
"Statement": [{
"Action": [
"admin:ConfigUpdate"
],
"Effect": "Allow",
"Sid": ""
}
]
}

View File

@@ -0,0 +1,12 @@
{
"Version": "2012-10-17",
"Statement": [{
"Action": [
"admin:ListTier",
"admin:SetTier"
],
"Effect": "Allow",
"Sid": ""
}
]
}

View File

@@ -0,0 +1,11 @@
{
"Version": "2012-10-17",
"Statement": [{
"Action": [
"admin:ServerTrace"
],
"Effect": "Allow",
"Sid": ""
}
]
}

View File

@@ -0,0 +1,21 @@
{
"Version": "2012-10-17",
"Statement": [{
"Action": [
"admin:ListUsers",
"admin:CreateUser",
"admin:DeleteUser",
"admin:GetUser",
"admin:EnableUser",
"admin:DisableUser",
"admin:ListUserPolicies",
"admin:ListGroups"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::*"
],
"Sid": ""
}
]
}

View File

@@ -0,0 +1,16 @@
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"s3:ListenBucketNotification",
"s3:ListBucket"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::*"
],
"Sid": ""
}
]
}

View File

@@ -0,0 +1,61 @@
add_alias() {
for i in $(seq 1 4); do
echo "... attempting to add alias $i"
until (mc alias set minio http://127.0.0.1:9000 minioadmin minioadmin); do
echo "...waiting... for 5secs" && sleep 5
done
done
}
remove_users() {
mc admin user remove minio bucketassignpolicy-$TIMESTAMP
mc admin user remove minio bucketread-$TIMESTAMP
mc admin user remove minio bucketwrite-$TIMESTAMP
mc admin user remove minio dashboard-$TIMESTAMP
mc admin user remove minio diagnostics-$TIMESTAMP
mc admin user remove minio groups-$TIMESTAMP
mc admin user remove minio heal-$TIMESTAMP
mc admin user remove minio iampolicies-$TIMESTAMP
mc admin user remove minio logs-$TIMESTAMP
mc admin user remove minio notificationendpoints-$TIMESTAMP
mc admin user remove minio settings-$TIMESTAMP
mc admin user remove minio tiers-$TIMESTAMP
mc admin user remove minio trace-$TIMESTAMP
mc admin user remove minio users-$TIMESTAMP
mc admin user remove minio watch-$TIMESTAMP
}
remove_policies() {
mc admin policy remove minio bucketassignpolicy-$TIMESTAMP
mc admin policy remove minio bucketread-$TIMESTAMP
mc admin policy remove minio bucketwrite-$TIMESTAMP
mc admin policy remove minio dashboard-$TIMESTAMP
mc admin policy remove minio diagnostics-$TIMESTAMP
mc admin policy remove minio groups-$TIMESTAMP
mc admin policy remove minio heal-$TIMESTAMP
mc admin policy remove minio iampolicies-$TIMESTAMP
mc admin policy remove minio logs-$TIMESTAMP
mc admin policy remove minio notificationendpoints-$TIMESTAMP
mc admin policy remove minio settings-$TIMESTAMP
mc admin policy remove minio tiers-$TIMESTAMP
mc admin policy remove minio trace-$TIMESTAMP
mc admin policy remove minio users-$TIMESTAMP
mc admin policy remove minio watch-$TIMESTAMP
}
__init__() {
export TIMESTAMP="$(cat portal-ui/tests/constants/timestamp.txt)"
export GOPATH=/tmp/gopath
export PATH=${PATH}:${GOPATH}/bin
go install github.com/minio/mc@latest
add_alias
}
main() {
remove_users
remove_policies
}
( __init__ "$@" && main "$@" )

View File

@@ -0,0 +1,81 @@
add_alias() {
for i in $(seq 1 4); do
echo "... attempting to add alias $i"
until (mc alias set minio http://127.0.0.1:9000 minioadmin minioadmin); do
echo "...waiting... for 5secs" && sleep 5
done
done
}
create_policies() {
mc admin policy add minio bucketassignpolicy-$TIMESTAMP portal-ui/tests/policies/bucketAssignPolicy.json
mc admin policy add minio bucketread-$TIMESTAMP portal-ui/tests/policies/bucketRead.json
mc admin policy add minio bucketwrite-$TIMESTAMP portal-ui/tests/policies/bucketWrite.json
mc admin policy add minio dashboard-$TIMESTAMP portal-ui/tests/policies/dashboard.json
mc admin policy add minio diagnostics-$TIMESTAMP portal-ui/tests/policies/diagnostics.json
mc admin policy add minio groups-$TIMESTAMP portal-ui/tests/policies/groups.json
mc admin policy add minio heal-$TIMESTAMP portal-ui/tests/policies/heal.json
mc admin policy add minio iampolicies-$TIMESTAMP portal-ui/tests/policies/iamPolicies.json
mc admin policy add minio logs-$TIMESTAMP portal-ui/tests/policies/logs.json
mc admin policy add minio notificationendpoints-$TIMESTAMP portal-ui/tests/policies/notificationEndpoints.json
mc admin policy add minio settings-$TIMESTAMP portal-ui/tests/policies/settings.json
mc admin policy add minio tiers-$TIMESTAMP portal-ui/tests/policies/tiers.json
mc admin policy add minio trace-$TIMESTAMP portal-ui/tests/policies/trace.json
mc admin policy add minio users-$TIMESTAMP portal-ui/tests/policies/users.json
mc admin policy add minio watch-$TIMESTAMP portal-ui/tests/policies/watch.json
}
create_users() {
mc admin user add minio bucketassignpolicy-$TIMESTAMP bucketassignpolicy
mc admin user add minio bucketread-$TIMESTAMP bucketread
mc admin user add minio bucketwrite-$TIMESTAMP bucketwrite
mc admin user add minio dashboard-$TIMESTAMP dashboard
mc admin user add minio diagnostics-$TIMESTAMP diagnostics
mc admin user add minio groups-$TIMESTAMP groups1234
mc admin user add minio heal-$TIMESTAMP heal1234
mc admin user add minio iampolicies-$TIMESTAMP iampolicies
mc admin user add minio logs-$TIMESTAMP logs1234
mc admin user add minio notificationendpoints-$TIMESTAMP notificationendpoints
mc admin user add minio settings-$TIMESTAMP settings
mc admin user add minio tiers-$TIMESTAMP tiers1234
mc admin user add minio trace-$TIMESTAMP trace1234
mc admin user add minio users-$TIMESTAMP users1234
mc admin user add minio watch-$TIMESTAMP watch1234
}
assign_policies() {
mc admin policy set minio bucketassignpolicy-$TIMESTAMP user=bucketassignpolicy-$TIMESTAMP
mc admin policy set minio bucketread-$TIMESTAMP user=bucketread-$TIMESTAMP
mc admin policy set minio bucketwrite-$TIMESTAMP user=bucketwrite-$TIMESTAMP
mc admin policy set minio dashboard-$TIMESTAMP user=dashboard-$TIMESTAMP
mc admin policy set minio diagnostics-$TIMESTAMP user=diagnostics-$TIMESTAMP
mc admin policy set minio groups-$TIMESTAMP user=groups-$TIMESTAMP
mc admin policy set minio heal-$TIMESTAMP user=heal-$TIMESTAMP
mc admin policy set minio iampolicies-$TIMESTAMP user=iampolicies-$TIMESTAMP
mc admin policy set minio logs-$TIMESTAMP user=logs-$TIMESTAMP
mc admin policy set minio notificationendpoints-$TIMESTAMP user=notificationendpoints-$TIMESTAMP
mc admin policy set minio settings-$TIMESTAMP user=settings-$TIMESTAMP
mc admin policy set minio tiers-$TIMESTAMP user=tiers-$TIMESTAMP
mc admin policy set minio trace-$TIMESTAMP user=trace-$TIMESTAMP
mc admin policy set minio users-$TIMESTAMP user=users-$TIMESTAMP
mc admin policy set minio watch-$TIMESTAMP user=watch-$TIMESTAMP
}
__init__() {
export TIMESTAMP=$(date "+%s")
echo $TIMESTAMP > portal-ui/tests/constants/timestamp.txt
export GOPATH=/tmp/gopath
export PATH=${PATH}:${GOPATH}/bin
go install github.com/minio/mc@latest
add_alias
}
main() {
create_policies
create_users
assign_policies
}
( __init__ "$@" && main "$@" )

View File

@@ -0,0 +1,127 @@
add_alias() {
for i in $(seq 1 4); do
echo "... attempting to add alias $i"
until (mc alias set minio http://127.0.0.1:9000 minioadmin minioadmin); do
echo "...waiting... for 5secs" && sleep 5
done
done
}
create_policies() {
mc admin policy add minio bucketassignpolicy-$TIMESTAMP portal-ui/tests/policies/bucketAssignPolicy.json
mc admin policy add minio bucketread-$TIMESTAMP portal-ui/tests/policies/bucketRead.json
mc admin policy add minio bucketwrite-$TIMESTAMP portal-ui/tests/policies/bucketWrite.json
mc admin policy add minio dashboard-$TIMESTAMP portal-ui/tests/policies/dashboard.json
mc admin policy add minio diagnostics-$TIMESTAMP portal-ui/tests/policies/diagnostics.json
mc admin policy add minio groups-$TIMESTAMP portal-ui/tests/policies/groups.json
mc admin policy add minio heal-$TIMESTAMP portal-ui/tests/policies/heal.json
mc admin policy add minio iampolicies-$TIMESTAMP portal-ui/tests/policies/iamPolicies.json
mc admin policy add minio logs-$TIMESTAMP portal-ui/tests/policies/logs.json
mc admin policy add minio notificationendpoints-$TIMESTAMP portal-ui/tests/policies/notificationEndpoints.json
mc admin policy add minio settings-$TIMESTAMP portal-ui/tests/policies/settings.json
mc admin policy add minio tiers-$TIMESTAMP portal-ui/tests/policies/tiers.json
mc admin policy add minio trace-$TIMESTAMP portal-ui/tests/policies/trace.json
mc admin policy add minio users-$TIMESTAMP portal-ui/tests/policies/users.json
mc admin policy add minio watch-$TIMESTAMP portal-ui/tests/policies/watch.json
}
create_users() {
mc admin user add minio bucketassignpolicy-$TIMESTAMP bucketassignpolicy
mc admin user add minio bucketread-$TIMESTAMP bucketread
mc admin user add minio bucketwrite-$TIMESTAMP bucketwrite
mc admin user add minio dashboard-$TIMESTAMP dashboard
mc admin user add minio diagnostics-$TIMESTAMP diagnostics
mc admin user add minio groups-$TIMESTAMP groups1234
mc admin user add minio heal-$TIMESTAMP heal1234
mc admin user add minio iampolicies-$TIMESTAMP iampolicies
mc admin user add minio logs-$TIMESTAMP logs1234
mc admin user add minio notificationendpoints-$TIMESTAMP notificationendpoints
mc admin user add minio settings-$TIMESTAMP settings
mc admin user add minio tiers-$TIMESTAMP tiers1234
mc admin user add minio trace-$TIMESTAMP trace1234
mc admin user add minio users-$TIMESTAMP users1234
mc admin user add minio watch-$TIMESTAMP watch1234
}
assign_policies() {
mc admin policy set minio bucketassignpolicy-$TIMESTAMP user=bucketassignpolicy-$TIMESTAMP
mc admin policy set minio bucketread-$TIMESTAMP user=bucketread-$TIMESTAMP
mc admin policy set minio bucketwrite-$TIMESTAMP user=bucketwrite-$TIMESTAMP
mc admin policy set minio dashboard-$TIMESTAMP user=dashboard-$TIMESTAMP
mc admin policy set minio diagnostics-$TIMESTAMP user=diagnostics-$TIMESTAMP
mc admin policy set minio groups-$TIMESTAMP user=groups-$TIMESTAMP
mc admin policy set minio heal-$TIMESTAMP user=heal-$TIMESTAMP
mc admin policy set minio iampolicies-$TIMESTAMP user=iampolicies-$TIMESTAMP
mc admin policy set minio logs-$TIMESTAMP user=logs-$TIMESTAMP
mc admin policy set minio notificationendpoints-$TIMESTAMP user=notificationendpoints-$TIMESTAMP
mc admin policy set minio settings-$TIMESTAMP user=settings-$TIMESTAMP
mc admin policy set minio tiers-$TIMESTAMP user=tiers-$TIMESTAMP
mc admin policy set minio trace-$TIMESTAMP user=trace-$TIMESTAMP
mc admin policy set minio users-$TIMESTAMP user=users-$TIMESTAMP
mc admin policy set minio watch-$TIMESTAMP user=watch-$TIMESTAMP
}
remove_users() {
mc admin user remove minio bucketassignpolicy-$TIMESTAMP
mc admin user remove minio bucketread-$TIMESTAMP
mc admin user remove minio bucketwrite-$TIMESTAMP
mc admin user remove minio dashboard-$TIMESTAMP
mc admin user remove minio diagnostics-$TIMESTAMP
mc admin user remove minio groups-$TIMESTAMP
mc admin user remove minio heal-$TIMESTAMP
mc admin user remove minio iampolicies-$TIMESTAMP
mc admin user remove minio logs-$TIMESTAMP
mc admin user remove minio notificationendpoints-$TIMESTAMP
mc admin user remove minio settings-$TIMESTAMP
mc admin user remove minio tiers-$TIMESTAMP
mc admin user remove minio trace-$TIMESTAMP
mc admin user remove minio users-$TIMESTAMP
mc admin user remove minio watch-$TIMESTAMP
}
remove_policies() {
mc admin policy remove minio bucketassignpolicy-$TIMESTAMP
mc admin policy remove minio bucketread-$TIMESTAMP
mc admin policy remove minio bucketwrite-$TIMESTAMP
mc admin policy remove minio dashboard-$TIMESTAMP
mc admin policy remove minio diagnostics-$TIMESTAMP
mc admin policy remove minio groups-$TIMESTAMP
mc admin policy remove minio heal-$TIMESTAMP
mc admin policy remove minio iampolicies-$TIMESTAMP
mc admin policy remove minio logs-$TIMESTAMP
mc admin policy remove minio notificationendpoints-$TIMESTAMP
mc admin policy remove minio settings-$TIMESTAMP
mc admin policy remove minio tiers-$TIMESTAMP
mc admin policy remove minio trace-$TIMESTAMP
mc admin policy remove minio users-$TIMESTAMP
mc admin policy remove minio watch-$TIMESTAMP
}
cleanup() {
remove_users
remove_policies
pkill console
kill -9 `lsof -i:5005 -t`
}
__init__() {
export TIMESTAMP=$(date "+%s")
echo $TIMESTAMP > portal-ui/tests/constants/timestamp.txt
export GOPATH=/tmp/gopath
export PATH=${PATH}:${GOPATH}/bin
go install github.com/minio/mc@latest
add_alias
create_policies
create_users
assign_policies
}
main() {
(yarn start &> /dev/null) & (./console server &> /dev/null) & (testcafe "chrome:headless" portal-ui/tests/permissions/ -q --skip-js-errors)
cleanup
}
( __init__ "$@" && main "$@" )

View File

@@ -0,0 +1 @@
test

View File

@@ -0,0 +1,41 @@
// This file is part of MinIO Console Server
// Copyright (c) 2022 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import { readFileSync } from "fs";
const data = readFileSync(__dirname + "/../constants/timestamp.txt", "utf-8");
const unixTimestamp = data.trim();
export const TEST_BUCKET_NAME = "testbucket-" + unixTimestamp;
export const TEST_GROUP_NAME = "testgroup-" + unixTimestamp;
export const TEST_USER_NAME = "testuser-" + unixTimestamp;
export const TEST_PASSWORD = "password";
export const TEST_IAM_POLICY_NAME = "testpolicy-" + unixTimestamp;
export const TEST_IAM_POLICY = JSON.stringify({
Version: "2012-10-17",
Statement: [
{
Action: ["admin:*"],
Effect: "Allow",
Sid: "",
},
{
Action: ["s3:*"],
Effect: "Allow",
Resource: ["arn:aws:s3:::*"],
Sid: "",
},
],
});

View File

@@ -0,0 +1,245 @@
// This file is part of MinIO Console Server
// Copyright (c) 2022 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import * as constants from "./constants";
import { Selector } from "testcafe";
//----------------------------------------------------
// General sidebar element
//----------------------------------------------------
export const sidebarItem = Selector(".MuiPaper-root").find("ul").child("a");
export const logoutItem = Selector(".MuiPaper-root").find("ul").child("div");
//----------------------------------------------------
// Specific sidebar elements
//----------------------------------------------------
export const dashboardElement = sidebarItem.withAttribute("href", "/dashboard");
export const bucketsElement = sidebarItem.withAttribute("href", "/buckets");
export const usersElement = sidebarItem.withAttribute("href", "/users");
export const groupsElement = sidebarItem.withAttribute("href", "/groups");
export const serviceAcctsElement = sidebarItem.withAttribute(
"href",
"/account"
);
export const iamPoliciesElement = sidebarItem.withAttribute(
"href",
"/policies"
);
export const settingsElement = sidebarItem.withAttribute("href", "/settings");
export const notificationEndpointsElement = sidebarItem.withAttribute(
"href",
"/notification-endpoints"
);
export const tiersElement = sidebarItem.withAttribute("href", "/tiers");
export const toolsElement = sidebarItem.withAttribute("href", "/tools");
export const licenseElement = sidebarItem.withAttribute("href", "/license");
//----------------------------------------------------
// Buttons
//----------------------------------------------------
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 browseButton = 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");
export const createPolicyButton = Selector("button:enabled").withText("Create Policy");
export const saveButton = Selector("button:enabled").withText("Save");
export const deleteButton = Selector("button:enabled").withExactText("Delete");
export const deleteIconButton = Selector("button:enabled").withAttribute(
"aria-label",
"Delete"
);
export const deleteIconButtonAlt = Selector("button:enabled").withAttribute(
"aria-label",
"delete"
);
export const configureBucketButton = Selector(
'span[class*="MuiIconButton-root"]'
).withAttribute("aria-label", "Configure Bucket");
export const addNotifTargetButton = Selector("button:enabled").withText(
"Add Notification Target"
);
export const createTierButton = Selector("button:enabled").withText("Create Tier");
export const createBucketButton = Selector("button:enabled").withText("Create Bucket");
export const deleteBucketButton = Selector("button:enabled").withText("Delete Bucket");
export const createUserButton = Selector("button:enabled").withText("Create User");
export const createGroupButton = Selector("button:enabled").withText("Create Group");
export const deleteGroupIconButton = Selector("span")
.withAttribute("aria-label", "Delete Group")
.find("button:enabled");
export const editMembersButton = Selector("button:enabled").withText("Edit Members");
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 downloadButton = Selector("button:enabled").withText("Download");
export const startButton = Selector("button:enabled").withText("Start");
export const stopButton = Selector("button:enabled").withText("Stop");
//----------------------------------------------------
// Links
//----------------------------------------------------
export const logsLink = Selector("a").withText("Logs");
export const watchLink = Selector("a").withText("Watch");
export const traceLink = Selector("a").withText("Trace");
export const healLink = Selector("a").withText("Heal");
export const diagnosticsLink = Selector("a").withText("Diagnostics");
//----------------------------------------------------
// Switches
//----------------------------------------------------
export const switchInput = Selector(".MuiSwitch-input");
//----------------------------------------------------
// Inputs
//----------------------------------------------------
export const bucketNameInput = Selector("#bucket-name");
export const bucketsPrefixInput = Selector("#prefix");
export const bucketsAccessInput = Selector(
'input[class*="MuiSelect-nativeInput"]'
);
export const bucketsAccessReadOnlyInput = Selector(
'li[class*="MuiMenuItem-root"]'
).withText("Readonly");
export const bucketsAccessWriteOnlyInput = Selector(
'li[class*="MuiMenuItem-root"]'
).withText("Writeonly");
export const bucketsAccessReadWriteInput = Selector(
'li[class*="MuiMenuItem-root"]'
).withText("Readwrite");
export const uploadInput = Selector("input").withAttribute("type", "file");
export const createPolicyName = Selector("#policy-name");
export const createPolicyTextfield = Selector(".cm-content");
export const usersAccessKeyInput = Selector("#accesskey-input");
export const usersSecretKeyInput = Selector("#standard-multiline-static");
export const groupNameInput = Selector("#group-name");
export const searchResourceInput = Selector("#search-resource");
export const filterUserInput = searchResourceInput.withAttribute("placeholder", "Filter Users");
export const groupUserCheckbox = Selector(".ReactVirtualized__Table__row span")
.withText(constants.TEST_USER_NAME)
.parent(1)
.find(".ReactVirtualized__Grid input")
.withAttribute("type", "checkbox");
//----------------------------------------------------
// Dropdowns and options
//----------------------------------------------------
export const bucketDropdownOption = Selector("li").withAttribute(
"data-value",
constants.TEST_BUCKET_NAME
);
//----------------------------------------------------
// Text
//----------------------------------------------------
export const bucketAccessText = Selector("h1")
.withText(constants.TEST_BUCKET_NAME)
.parent(1)
.find("p")
.nth(-1);
export const groupStatusText = Selector('span[class*="statusValue-"]');
//----------------------------------------------------
// Tables, table headers and content
//----------------------------------------------------
export const table = Selector(".ReactVirtualized__Table");
export const bucketsTableDisabled = Selector(
'div[class*="TableWrapper-disabled"]'
);
export const createGroupUserTable = Selector(
".MuiDialog-container .ReactVirtualized__Table"
);
//----------------------------------------------------
// Bucket page vertical tabs
//----------------------------------------------------
export const bucketAccessRulesTab =
Selector(".MuiTab-root").withText("Access Rules");
//----------------------------------------------------
// Settings window
//----------------------------------------------------
export const settingsWindow = Selector(
'div[class*="ConfigurationOptions-settingsOptionsContainer"]'
);
//----------------------------------------------------
// Settings page vertical tabs
//----------------------------------------------------
export const settingsRegionTab = Selector(".MuiTab-root").withAttribute(
"href",
"/settings/region"
);
export const settingsCacheTab = Selector(".MuiTab-root").withAttribute(
"href",
"/settings/cache"
);
export const settingsCompressionTab = Selector(".MuiTab-root").withAttribute(
"href",
"/settings/compression"
);
export const settingsApiTab = Selector(".MuiTab-root").withAttribute(
"href",
"/settings/api"
);
export const settingsHealTab = Selector(".MuiTab-root").withAttribute(
"href",
"/settings/heal"
);
export const settingsScannerTab = Selector(".MuiTab-root").withAttribute(
"href",
"/settings/scanner"
);
export const settingsEtcdTab = Selector(".MuiTab-root").withAttribute(
"href",
"/settings/etcd"
);
export const settingsOpenIdTab = Selector(".MuiTab-root").withAttribute(
"href",
"/settings/identity_openid"
);
export const settingsLdapTab = Selector(".MuiTab-root").withAttribute(
"href",
"/settings/identity_ldap"
);
export const settingsLoggerWebhookTab = Selector(".MuiTab-root").withAttribute(
"href",
"/settings/logger_webhook"
);
export const settingsAuditWebhookTab = Selector(".MuiTab-root").withAttribute(
"href",
"/settings/audit_webhook"
);
//----------------------------------------------------
// Log window
//----------------------------------------------------
export const logWindow = Selector('div[class*="logList"]');

View File

@@ -0,0 +1,92 @@
// This file is part of MinIO Console Server
// Copyright (c) 2022 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import * as roles from "./roles";
import * as elements from "./elements";
import * as constants from "./constants";
import { Selector } from "testcafe";
export const setUpBucket = (t) => {
return t
.useRole(roles.admin)
.navigateTo("http://localhost:5005/buckets")
.click(elements.createBucketButton)
.typeText(elements.bucketNameInput, constants.TEST_BUCKET_NAME)
.click(elements.createBucketButton)
.click(elements.logoutItem);
};
export const cleanUpBucket = (t) => {
return (
t
// useRole doesn't work here so we would need to enter the commands manually
.navigateTo("http://localhost:5005/login")
.typeText("#accessKey", "minioadmin")
.typeText("#secretKey", "minioadmin")
.click(elements.loginSubmitButton)
.navigateTo("http://localhost:5005/buckets")
.click(elements.manageButton)
.click(elements.deleteBucketButton)
.click(elements.deleteButton)
.click(elements.logoutItem)
);
};
export const cleanUpBucketAndUploads = (t) => {
return (
t
// useRole doesn't work here so we would need to enter the commands manually
.navigateTo("http://localhost:5005/login")
.typeText("#accessKey", "minioadmin")
.typeText("#secretKey", "minioadmin")
.click(elements.loginSubmitButton)
.navigateTo("http://localhost:5005/buckets")
.click(elements.browseButton)
.click(elements.deleteIconButtonAlt)
.click(elements.deleteButton)
.click(elements.configureBucketButton)
.click(elements.deleteBucketButton)
.click(elements.deleteButton)
.click(elements.logoutItem)
);
};
export const createUser = (t) => {
return t
.useRole(roles.admin)
.navigateTo("http://localhost:5005/users")
.click(elements.createUserButton)
.typeText(elements.usersAccessKeyInput, constants.TEST_USER_NAME)
.typeText(elements.usersSecretKeyInput, constants.TEST_PASSWORD)
.click(elements.saveButton);
};
export const cleanUpUser = (t) => {
const userListItem = Selector(".ReactVirtualized__Table__rowColumn").withText(
constants.TEST_USER_NAME
);
const userDeleteIconButton = userListItem
.nextSibling()
.child("button")
.withAttribute("aria-label", "delete");
return t
.useRole(roles.admin)
.navigateTo("http://localhost:5005/users")
.click(userDeleteIconButton)
.click(elements.deleteButton);
};

View File

@@ -0,0 +1,186 @@
import { readFileSync } from 'fs';
import { Role, Selector } from "testcafe";
const data = readFileSync(__dirname + '/../constants/timestamp.txt', 'utf-8');
const unixTimestamp = data.trim();
const loginUrl = "http://localhost:5005/login";
// diagnostics/watch/trace need to run in port 9090 (through the server) to work
const loginUrlServer = "http://localhost:9090/login";
const submitButton = Selector("form button");
export const admin = Role(
loginUrl,
async (t) => {
await t
.typeText("#accessKey", "minioadmin")
.typeText("#secretKey", "minioadmin")
.click(submitButton);
},
{ preserveUrl: true }
);
export const bucketAssignPolicy = Role(
loginUrl,
async (t) => {
await t
.typeText("#accessKey", "bucketassignpolicy-" + unixTimestamp)
.typeText("#secretKey", "bucketassignpolicy")
.click(submitButton);
},
{ preserveUrl: true }
);
export const bucketRead = Role(
loginUrl,
async (t) => {
await t
.typeText("#accessKey", "bucketread-" + unixTimestamp)
.typeText("#secretKey", "bucketread")
.click(submitButton);
},
{ preserveUrl: true }
);
export const bucketWrite = Role(
loginUrl,
async (t) => {
await t
.typeText("#accessKey", "bucketwrite-" + unixTimestamp)
.typeText("#secretKey", "bucketwrite")
.click(submitButton);
},
{ preserveUrl: true }
);
export const dashboard = Role(
loginUrl,
async (t) => {
await t
.typeText("#accessKey", "dashboard-" + unixTimestamp)
.typeText("#secretKey", "dashboard")
.click(submitButton);
},
{ preserveUrl: true }
);
export const diagnostics = Role(
loginUrlServer,
async (t) => {
await t
.typeText("#accessKey", "diagnostics-" + unixTimestamp)
.typeText("#secretKey", "diagnostics")
.click(submitButton);
},
{ preserveUrl: true }
);
export const groups = Role(
loginUrl,
async (t) => {
await t
.typeText("#accessKey", "groups-" + unixTimestamp)
.typeText("#secretKey", "groups1234")
.click(submitButton);
},
{ preserveUrl: true }
);
export const heal = Role(
loginUrlServer,
async (t) => {
await t
.typeText("#accessKey", "heal-" + unixTimestamp)
.typeText("#secretKey", "heal1234")
.click(submitButton);
},
{ preserveUrl: true }
);
export const iamPolicies = Role(
loginUrl,
async (t) => {
await t
.typeText("#accessKey", "iampolicies-" + unixTimestamp)
.typeText("#secretKey", "iampolicies")
.click(submitButton);
},
{ preserveUrl: true }
);
export const logs = Role(
loginUrl,
async (t) => {
await t
.typeText("#accessKey", "logs-" + unixTimestamp)
.typeText("#secretKey", "logs1234")
.click(submitButton);
},
{ preserveUrl: true }
);
export const notificationEndpoints = Role(
loginUrl,
async (t) => {
await t
.typeText("#accessKey", "notificationendpoints-" + unixTimestamp)
.typeText("#secretKey", "notificationendpoints")
.click(submitButton);
},
{ preserveUrl: true }
);
export const settings = Role(
loginUrl,
async (t) => {
await t
.typeText("#accessKey", "settings-" + unixTimestamp)
.typeText("#secretKey", "settings")
.click(submitButton);
},
{ preserveUrl: true }
);
export const tiers = Role(
loginUrl,
async (t) => {
await t
.typeText("#accessKey", "tiers-" + unixTimestamp)
.typeText("#secretKey", "tiers1234")
.click(submitButton);
},
{ preserveUrl: true }
);
export const trace = Role(
loginUrlServer,
async (t) => {
await t
.typeText("#accessKey", "trace-" + unixTimestamp)
.typeText("#secretKey", "trace1234")
.click(submitButton);
},
{ preserveUrl: true }
);
export const users = Role(
loginUrl,
async (t) => {
await t
.typeText("#accessKey", "users-" + unixTimestamp)
.typeText("#secretKey", "users1234")
.click(submitButton);
},
{ preserveUrl: true }
);
export const watch = Role(
loginUrlServer,
async (t) => {
await t
.typeText("#accessKey", "watch-" + unixTimestamp)
.typeText("#secretKey", "watch1234")
.click(submitButton);
},
{ preserveUrl: true }
);

File diff suppressed because it is too large Load Diff