Implemented AGPL MinIO Object Browser simplified Console (#3509)

Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>
This commit is contained in:
Alex
2025-03-11 03:30:53 -06:00
committed by GitHub
parent 33a7fbb205
commit 63c6d8952b
718 changed files with 1287 additions and 111051 deletions

View File

@@ -1 +1 @@
1657924012
1737352766

View File

@@ -1,142 +0,0 @@
// 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";
import { groupsElement, identityElement } from "../utils/elements-menu";
import { IAM_PAGES } from "../../src/common/SecureComponent/permissions";
const groupsListItemFor = (modifier: string) => {
return Selector(".ReactVirtualized__Table__rowColumn").withText(
`${constants.TEST_GROUP_NAME}-${modifier}`,
);
};
const appBaseUrl = "http://localhost:9090";
let groupsPageUrl = `${appBaseUrl}${IAM_PAGES.GROUPS}`;
let groupsAddPageUrl = `${appBaseUrl}${IAM_PAGES.GROUPS_ADD}`;
const createGroup = async (t: TestController, modifier: string) => {
await t
.useRole(roles.groups)
.navigateTo(groupsAddPageUrl)
.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(appBaseUrl)
.beforeEach(async (t) => {
await t.useRole(roles.groups);
});
test("Create Group button exists", async (t) => {
const createGroupButtonExists = elements.createGroupButton.exists;
await t
.navigateTo(groupsPageUrl)
.expect(createGroupButtonExists)
.ok()
.wait(2000);
});
test("Groups sidebar item exists", async (t) => {
await t
.expect(identityElement.exists)
.ok()
.click(identityElement)
.expect(groupsElement.exists)
.ok()
.wait(2000);
});
test("Create Group button is clickable", async (t) => {
await t
.navigateTo(groupsPageUrl)
.click(elements.createGroupButton)
.expect(true)
.ok()
.wait(2000);
});
test("Group Name input exists in the Create Group page", async (t) => {
await t
.navigateTo(groupsPageUrl)
.click(elements.createGroupButton)
.expect(elements.groupNameInput.exists)
.ok()
.wait(2000);
});
test("Users table exists in the Create Groups page", async (t) => {
const createGroupUserTableExists = elements.table.exists;
await t
.navigateTo(groupsPageUrl)
.click(elements.createGroupButton)
.expect(createGroupUserTableExists)
.ok()
.wait(2000);
});
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 page 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(groupsAddPageUrl)
.typeText(elements.groupNameInput, constants.TEST_GROUP_NAME)
.typeText(elements.filterUserInput, constants.TEST_USER_NAME)
.click(elements.groupUserCheckbox)
.click(elements.saveButton)
.wait(2000);
});
test.before(async (t) => {
// A user must be created as we need to choose a user from the dropdown
await functions.createUser(t);
await createGroup(t, "groups-table");
})("Groups table exists", async (t) => {
await t
.navigateTo(groupsPageUrl)
.expect(elements.table.exists)
.ok()
.wait(2000);
});
test.before(async (t) => {
// A user must be created as we need to choose a user from the dropdown
await functions.createUser(t);
await createGroup(t, "disable-enable");
})("Created Group can be disabled and enabled back", async (t) => {
await t
.navigateTo(groupsPageUrl)
.click(groupsListItemFor("disable-enable"))
.click(elements.switchInput)
.expect(elements.groupStatusText.innerText)
.eql("Disabled")
.click(elements.switchInput)
.expect(elements.groupStatusText.innerText)
.eql("Enabled");
});

View File

@@ -1,43 +0,0 @@
// 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 { notificationEndpointsElement } from "../utils/elements-menu";
fixture("For user with Notification Endpoints permissions")
.page("http://localhost:9090")
.beforeEach(async (t) => {
await t.useRole(roles.notificationEndpoints);
});
test("Notification Endpoints sidebar item exists", async (t) => {
await t.expect(notificationEndpointsElement.exists).ok();
});
test("Add Notification Target button exists", async (t) => {
const addNotifTargetButtonExists = elements.addEventDestination.exists;
await t
.navigateTo("http://localhost:9090/settings/event-destinations")
.expect(addNotifTargetButtonExists)
.ok();
});
test("Add Notification Target button is clickable", async (t) => {
await t
.navigateTo("http://localhost:9090/settings/event-destinations")
.click(elements.addEventDestination);
});

View File

@@ -62,9 +62,6 @@ fixture("For user with Bucket Prefix permissions")
test("Bucket page can be opened", async (t) => {
await t.navigateTo(bucketsScreenUrl);
});
test("Buckets sidebar item exists", async (t) => {
await t.expect(bucketsSidebarEl.exists).ok();
});
/**
* Without the fix UI crashes with

View File

@@ -17,38 +17,11 @@
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";
import { Selector } from "testcafe";
import * as constants from "../utils/constants";
import { acknowledgeButton } from "../utils/elements";
fixture("For user with Bucket Write permissions").page("http://localhost:9090");
test("Buckets sidebar item exists", async (t) => {
const bucketsExist = bucketsElement.with({ boundTestRun: t }).exists;
await t.useRole(roles.bucketWrite).expect(bucketsExist).ok();
});
test
.before(async (t) => {
// Create a bucket
await functions.setUpBucket(t, "bucketwritew");
})("Bucket access is set to W", async (t) => {
await new Promise((resolve) => setTimeout(resolve, 2000));
await t
.useRole(roles.bucketWrite)
.navigateTo("http://localhost:9090/buckets")
.expect(
Selector(`#access-${constants.TEST_BUCKET_NAME}-bucketwritew`)
.innerText,
)
.eql("Access: W");
})
.after(async (t) => {
// Cleanup created bucket and corresponding uploads
await functions.cleanUpBucketAndUploads(t, "bucketwritew");
});
test
.before(async (t) => {
// Create a bucket
@@ -58,7 +31,8 @@ test
const testBucketBrowseButton = testBucketBrowseButtonFor("bucketwrite2");
await t
.useRole(roles.bucketWrite)
.navigateTo("http://localhost:9090/browser")
.click(acknowledgeButton)
.typeText(elements.filterBuckets, "bucketwrite2")
.click(testBucketBrowseButton)
.expect(uploadExists)
.ok();
@@ -73,11 +47,11 @@ test
// Create a bucket
await functions.setUpBucket(t, "bucketwrite3");
})("Object can be uploaded to a bucket", async (t) => {
const testBucketBrowseButton = testBucketBrowseButtonFor("bucketwrite3");
await t
.useRole(roles.bucketWrite)
.navigateTo("http://localhost:9090/browser")
.click(testBucketBrowseButton)
.click(acknowledgeButton)
.typeText(elements.filterBuckets, "bucketwrite3")
.click(testBucketBrowseButtonFor("bucketwrite3"))
// Upload object to bucket
.setFilesToUpload(elements.uploadInput, "../uploads/test.txt");
})
@@ -93,7 +67,8 @@ test
})("Object list table is disabled", async (t) => {
await t
.useRole(roles.bucketWrite)
.navigateTo("http://localhost:9090/browser")
.click(acknowledgeButton)
.typeText(elements.filterBuckets, "bucketwrite4")
.click(testBucketBrowseButtonFor("bucketwrite4"))
.expect(elements.bucketsTableDisabled.exists)
.ok();

View File

@@ -1,37 +0,0 @@
// 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 { dashboardElement, monitoringElement } from "../utils/elements-menu";
fixture("For user with Dashboard permissions")
.page("http://localhost:9090")
.beforeEach(async (t) => {
await t.useRole(roles.dashboard);
});
test("Dashboard sidebar item exists", async (t) => {
const dashboardExists = dashboardElement.exists;
await t
.expect(monitoringElement.exists)
.ok()
.click(monitoringElement)
.expect(dashboardExists)
.ok();
});
// TODO: Display extended metrics

View File

@@ -18,6 +18,8 @@ import * as roles from "../utils/roles";
import { Selector } from "testcafe";
import * as functions from "../utils/functions";
import { testBucketBrowseButtonFor } from "../utils/functions";
import * as elements from "../utils/elements";
import { acknowledgeButton } from "../utils/elements";
fixture("Delete Objects With Prefix Only policy").page(
"http://localhost:9090/",
@@ -43,7 +45,8 @@ test
})("Delete button is disabled for object inside bucket", async (t) => {
await t
.useRole(roles.deleteObjectWithPrefixOnly)
.navigateTo(`http://localhost:9090/browser`)
.click(acknowledgeButton)
.typeText(elements.filterBuckets, bucket1)
.click(test1BucketBrowseButton)
.click(
Selector(".ReactVirtualized__Table__rowColumn").withText("test.txt"),
@@ -69,7 +72,8 @@ test
async (t) => {
await t
.useRole(roles.deleteObjectWithPrefixOnly)
.navigateTo(`http://localhost:9090/browser`)
.click(acknowledgeButton)
.typeText(elements.filterBuckets, bucket2)
.click(test2BucketBrowseButton)
.click(
Selector(".ReactVirtualized__Table__rowColumn").withText(
@@ -103,7 +107,8 @@ test
async (t) => {
await t
.useRole(roles.deleteObjectWithPrefixOnly)
.navigateTo(`http://localhost:9090/browser`)
.click(acknowledgeButton)
.typeText(elements.filterBuckets, bucket3)
.click(test3BucketBrowseButton)
.click(
Selector(".ReactVirtualized__Table__rowColumn").withText(

View File

@@ -1,70 +0,0 @@
// 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 { configurationsElement } from "../utils/elements-menu";
fixture("For user with Settings permissions")
.page("http://localhost:9090")
.beforeEach(async (t) => {
await t.useRole(roles.settings);
});
test("Settings sidebar item exists", async (t) => {
await t.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/configurations")
.expect(settingsWindowExists)
.ok();
});
test("All vertical tab items exist", async (t) => {
const settingsRegionTabExists = elements.settingsRegionTab.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 settingsLoggerWebhookTabExists =
elements.settingsLoggerWebhookTab.exists;
const settingsAuditWebhookTabExists = elements.settingsAuditWebhookTab.exists;
const settingsAuditKafkaTabExists = elements.settingsAuditKafkaTab.exists;
await t
.navigateTo("http://localhost:9090/settings/configurations")
.expect(settingsRegionTabExists)
.ok()
.expect(settingsCompressionTabExists)
.ok()
.expect(settingsApiTabExists)
.ok()
.expect(settingsHealTabExists)
.ok()
.expect(settingsScannerTabExists)
.ok()
.expect(settingsEtcdTabExists)
.ok()
.expect(settingsLoggerWebhookTabExists)
.ok()
.expect(settingsAuditWebhookTabExists)
.ok()
.expect(settingsAuditKafkaTabExists)
.ok();
});

View File

@@ -1,62 +0,0 @@
// 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-menu";
import {
bucketsElement,
dashboardElement,
groupsElement,
iamPoliciesElement,
identityElement,
monitoringElement,
notificationEndpointsElement,
serviceAcctsElement,
usersElement,
} from "../utils/elements-menu";
fixture("For user with Admin permissions")
.page("http://localhost:9090")
.beforeEach(async (t) => {
await t.useRole(roles.admin);
});
test("All sidebar items exist", async (t) => {
const licenseExists = elements.licenseElement.exists;
await t
.expect(monitoringElement.exists)
.ok()
.click(monitoringElement)
.expect(dashboardElement.exists)
.ok()
.expect(bucketsElement.exists)
.ok()
.expect(identityElement.exists)
.ok()
.click(identityElement)
.expect(usersElement.exists)
.ok()
.expect(groupsElement.exists)
.ok()
.expect(serviceAcctsElement.exists)
.ok()
.expect(iamPoliciesElement.exists)
.ok()
.expect(notificationEndpointsElement.exists)
.ok()
.expect(licenseExists)
.ok();
});

View File

@@ -1,125 +0,0 @@
// 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";
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")
.beforeEach(async (t) => {
await t.useRole(roles.bucketAssignPolicy);
});
// Bucket assign policy permissions
test("Buckets sidebar item exists", async (t) => {
const bucketsExist = bucketsElement.exists;
await t.expect(bucketsExist).ok();
});
test
.before(async (t) => {
// Create a bucket
await functions.setUpBucket(t, "bucketassign1");
})("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:9090/buckets")
.click(manageButtonFor("bucketassign1"))
.click(elements.bucketAccessRulesTab)
.click(elements.addAccessRuleButton)
.typeText(elements.bucketsPrefixInput, "readonlytest")
.click(elements.bucketsAccessInput)
.click(elements.bucketsAccessReadOnlyInput)
.click(elements.saveButton);
})
.after(async (t) => {
// Cleanup created bucket
await functions.cleanUpBucket(t, "bucketassign1");
});
test
.before(async (t) => {
// Create a bucket
await functions.setUpBucket(t, "bucketassign3");
})("A writeonly 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:9090/buckets")
.click(manageButtonFor("bucketassign3"))
.click(elements.bucketAccessRulesTab)
.click(elements.addAccessRuleButton)
.typeText(elements.bucketsPrefixInput, "writeonlytest")
.click(elements.bucketsAccessInput)
.click(elements.bucketsAccessWriteOnlyInput)
.click(elements.saveButton);
})
.after(async (t) => {
// Cleanup created bucket
await functions.cleanUpBucket(t, "bucketassign3");
});
test
.before(async (t) => {
// Create a bucket
await functions.setUpBucket(t, "bucketassign4");
})("A readwrite 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:9090/buckets")
.click(manageButtonFor("bucketassign4"))
.click(elements.bucketAccessRulesTab)
.click(elements.addAccessRuleButton)
.typeText(elements.bucketsPrefixInput, "readwritetest")
.click(elements.bucketsAccessInput)
.click(elements.bucketsAccessReadWriteInput)
.click(elements.saveButton);
})
.after(async (t) => {
// Cleanup created bucket
await functions.cleanUpBucket(t, "bucketassign4");
});
// test
// .before(async (t) => {
// // Create a bucket
// await functions.setUpBucket(t, "bucketassign5");
// })("Previously assigned policy to a bucket can be deleted", async (t) => {
// await new Promise((resolve) => setTimeout(resolve, 2000));
// await t
// .useRole(roles.bucketAssignPolicy)
// .navigateTo("http://localhost:9090/buckets")
// .click(manageButtonFor("bucketassign5"))
// .click(elements.bucketAccessRulesTab)
// .click(elements.deleteIconButtonAlt)
// .click(elements.deleteButton)
// .click(logoutItem);
// })
// .after(async (t) => {
// // Cleanup created bucket
// await functions.cleanUpBucket(t, "bucketassign5");
// });

View File

@@ -19,6 +19,7 @@ import * as elements from "../utils/elements";
import * as functions from "../utils/functions";
import { testBucketBrowseButtonFor } from "../utils/functions";
import { Selector } from "testcafe";
import { acknowledgeButton } from "../utils/elements";
fixture("For user with Bucket Read & Write permissions").page(
"http://localhost:9090",
@@ -31,7 +32,8 @@ test
await functions.setVersioned(t, "bucketdelete3");
await t
.useRole(roles.bucketReadWrite)
.navigateTo("http://localhost:9090/browser")
.click(acknowledgeButton)
.typeText(elements.filterBuckets, "bucketdelete3")
.click(testBucketBrowseButtonFor("bucketdelete3"))
// Upload object to bucket
.setFilesToUpload(elements.uploadInput, "../uploads/test.txt")
@@ -47,7 +49,8 @@ test
);
await t
.useRole(roles.bucketReadWrite)
.navigateTo("http://localhost:9090/browser")
.click(acknowledgeButton)
.typeText(elements.filterBuckets, "bucketdelete3")
.click(testBucketBrowseButtonFor("bucketdelete3"))
.click(
"div.ReactVirtualized__Grid.ReactVirtualized__Table__Grid > div > div:nth-child(1)",

View File

@@ -19,6 +19,7 @@ import * as elements from "../utils/elements";
import * as functions from "../utils/functions";
import { testBucketBrowseButtonFor } from "../utils/functions";
import { Selector } from "testcafe";
import { acknowledgeButton } from "../utils/elements";
fixture("For user with Bucket Read & Write permissions").page(
"http://localhost:9090",
@@ -31,7 +32,8 @@ test
await functions.setVersioned(t, "bucketobjecttags");
await t
.useRole(roles.bucketObjectTags)
.navigateTo("http://localhost:9090/browser")
.click(acknowledgeButton)
.typeText(elements.filterBuckets, "bucketobjecttags")
.click(testBucketBrowseButtonFor("bucketobjecttags"))
// Upload object to bucket
.setFilesToUpload(elements.uploadInput, "../uploads/test.txt")
@@ -39,7 +41,8 @@ test
})("Tags can be created and deleted", async (t) => {
await t
.useRole(roles.bucketObjectTags)
.navigateTo("http://localhost:9090/browser")
.click(acknowledgeButton)
.typeText(elements.filterBuckets, "bucketobjecttags")
.click(testBucketBrowseButtonFor("bucketobjecttags"))
.click(
"div.ReactVirtualized__Grid.ReactVirtualized__Table__Grid > div > div:nth-child(1)",
@@ -69,7 +72,8 @@ test
await functions.setVersioned(t, "bucketcannottag");
await t
.useRole(roles.bucketCannotTag)
.navigateTo("http://localhost:9090/browser")
.click(acknowledgeButton)
.typeText(elements.filterBuckets, "bucketcannottag")
.click(testBucketBrowseButtonFor("bucketcannottag"))
// Upload object to bucket
.setFilesToUpload(elements.uploadInput, "../uploads/test.txt")
@@ -77,7 +81,8 @@ test
})("User should not be able to create tag", async (t) => {
await t
.useRole(roles.bucketCannotTag)
.navigateTo("http://localhost:9090/browser")
.click(acknowledgeButton)
.typeText(elements.filterBuckets, "bucketcannottag")
.click(testBucketBrowseButtonFor("bucketcannottag"))
.click(
"div.ReactVirtualized__Grid.ReactVirtualized__Table__Grid > div > div:nth-child(1)",

View File

@@ -17,10 +17,9 @@
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 { logoutItem } from "../utils/elements-menu";
import { testBucketBrowseButtonFor } from "../utils/functions";
import { Selector } from "testcafe";
import * as constants from "../utils/constants";
import { acknowledgeButton } from "../utils/elements";
fixture("For user with Bucket Read permissions")
.page("http://localhost:9090")
@@ -28,11 +27,6 @@ fixture("For user with Bucket Read permissions")
await t.useRole(roles.bucketRead);
});
test("Buckets sidebar item exists", async (t) => {
const bucketsExist = bucketsElement.exists;
await t.expect(bucketsExist).ok();
});
test
.before(async (t) => {
// Create a bucket
@@ -41,7 +35,8 @@ test
await new Promise((resolve) => setTimeout(resolve, 2000));
await t
.useRole(roles.bucketRead)
.navigateTo("http://localhost:9090/browser")
.click(acknowledgeButton)
.typeText(elements.filterBuckets, "bucketread1")
.expect(testBucketBrowseButtonFor("bucketread1").exists)
.ok();
})
@@ -50,32 +45,14 @@ test
await functions.cleanUpBucket(t, "bucketread1");
});
test
.before(async (t) => {
// Create a bucket
await functions.setUpBucket(t, "bucketread2");
})("Bucket access is set to R", async (t) => {
await new Promise((resolve) => setTimeout(resolve, 2000));
await t
.useRole(roles.bucketRead)
.navigateTo("http://localhost:9090/buckets")
.expect(
Selector(`#access-${constants.TEST_BUCKET_NAME}-bucketread2`).innerText,
)
.eql("Access: R");
})
.after(async (t) => {
// Cleanup created bucket and corresponding uploads
await functions.cleanUpBucket(t, "bucketread2");
});
test
.before(async (t) => {
// Create a bucket
await functions.setUpBucket(t, "aread3");
await t
.useRole(roles.admin)
.navigateTo("http://localhost:9090/browser")
.click(acknowledgeButton)
.typeText(elements.filterBuckets, "aread3")
.click(testBucketBrowseButtonFor("aread3"))
// Upload object to bucket
.setFilesToUpload(elements.uploadInput, "../uploads/test.txt")
@@ -84,7 +61,8 @@ test
await new Promise((resolve) => setTimeout(resolve, 2000));
await t
.useRole(roles.bucketRead)
.navigateTo("http://localhost:9090/browser")
.click(acknowledgeButton)
.typeText(elements.filterBuckets, "aread3")
.wait(2000)
.click(testBucketBrowseButtonFor("aread3"))
.wait(2000)

View File

@@ -23,6 +23,7 @@ import {
} from "../utils/functions";
import { bucketsElement, logoutItem } from "../utils/elements-menu";
import { Selector } from "testcafe";
import { acknowledgeButton } from "../utils/elements";
const TEST_BUCKET_NAME_SPECIFIC = "specific-bucket";
@@ -30,127 +31,16 @@ fixture("For user with permissions that only allow specific Buckets").page(
"http://localhost:9090",
);
test("Buckets sidebar item exists", async (t) => {
const bucketsExist = bucketsElement.with({ boundTestRun: t }).exists;
await t.useRole(roles.bucketSpecific).expect(bucketsExist).ok();
});
// Bucket assign policy tests
test
.before(async (t) => {
// Create a bucket
await functions.setUpNamedBucket(t, `${TEST_BUCKET_NAME_SPECIFIC}-1`);
})("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.bucketSpecific)
.navigateTo("http://localhost:9090/buckets")
.click(namedManageButtonFor(`${TEST_BUCKET_NAME_SPECIFIC}-1`))
.click(elements.bucketAccessRulesTab)
.click(elements.addAccessRuleButton)
.typeText(elements.bucketsPrefixInput, "readonlytest")
.click(elements.bucketsAccessInput)
.click(elements.bucketsAccessReadOnlyInput)
.click(elements.saveButton);
})
.after(async (t) => {
// Cleanup created bucket
await functions.cleanUpNamedBucket(t, `${TEST_BUCKET_NAME_SPECIFIC}-1`);
});
test
.before(async (t) => {
// Create a bucket
await functions.setUpNamedBucket(t, `${TEST_BUCKET_NAME_SPECIFIC}-2`);
})("A writeonly 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.bucketSpecific)
.navigateTo("http://localhost:9090/buckets")
.click(namedManageButtonFor(`${TEST_BUCKET_NAME_SPECIFIC}-2`))
.click(elements.bucketAccessRulesTab)
.click(elements.addAccessRuleButton)
.typeText(elements.bucketsPrefixInput, "writeonlytest")
.click(elements.bucketsAccessInput)
.click(elements.bucketsAccessWriteOnlyInput)
.click(elements.saveButton);
})
.after(async (t) => {
// Cleanup created bucket
await functions.cleanUpNamedBucket(t, `${TEST_BUCKET_NAME_SPECIFIC}-2`);
});
test
.before(async (t) => {
// Create a bucket
await functions.setUpNamedBucket(t, `${TEST_BUCKET_NAME_SPECIFIC}-3`);
})("A readwrite 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.bucketSpecific)
.navigateTo("http://localhost:9090/buckets")
.click(namedManageButtonFor(`${TEST_BUCKET_NAME_SPECIFIC}-3`))
.click(elements.bucketAccessRulesTab)
.click(elements.addAccessRuleButton)
.typeText(elements.bucketsPrefixInput, "readwritetest")
.click(elements.bucketsAccessInput)
.click(elements.bucketsAccessReadWriteInput)
.click(elements.saveButton);
})
.after(async (t) => {
// Cleanup created bucket
await functions.cleanUpNamedBucket(t, `${TEST_BUCKET_NAME_SPECIFIC}-3`);
});
// Bucket read tests
test
.before(async (t) => {
// Create a bucket
await functions.setUpNamedBucket(t, `${TEST_BUCKET_NAME_SPECIFIC}-4`);
})("Browse button exists", async (t) => {
await new Promise((resolve) => setTimeout(resolve, 2000));
await t
.useRole(roles.bucketRead)
.navigateTo("http://localhost:9090/browser")
.expect(
namedTestBucketBrowseButtonFor(`${TEST_BUCKET_NAME_SPECIFIC}-4`).exists,
)
.ok();
})
.after(async (t) => {
// Cleanup created bucket and corresponding uploads
await functions.cleanUpNamedBucket(t, `${TEST_BUCKET_NAME_SPECIFIC}-4`);
});
test
.before(async (t) => {
// Create a bucket
await functions.setUpNamedBucket(t, `${TEST_BUCKET_NAME_SPECIFIC}-5`);
})("Bucket access is set to R", async (t) => {
await new Promise((resolve) => setTimeout(resolve, 2000));
await t
.useRole(roles.bucketRead)
.navigateTo("http://localhost:9090/buckets")
.expect(Selector(`#access-${TEST_BUCKET_NAME_SPECIFIC}-5`).innerText)
.eql("Access: R");
})
.after(async (t) => {
// Cleanup created bucket and corresponding uploads
await functions.cleanUpNamedBucket(t, `${TEST_BUCKET_NAME_SPECIFIC}-5`);
});
test
.before(async (t) => {
// Create a bucket
await functions.setUpNamedBucket(t, `${TEST_BUCKET_NAME_SPECIFIC}-6`);
await t
.useRole(roles.admin)
.navigateTo("http://localhost:9090/browser")
.click(acknowledgeButton)
.typeText(elements.filterBuckets, `${TEST_BUCKET_NAME_SPECIFIC}-6`)
.click(namedTestBucketBrowseButtonFor(`${TEST_BUCKET_NAME_SPECIFIC}-6`))
// Upload object to bucket
.setFilesToUpload(elements.uploadInput, "../uploads/test.txt")
@@ -159,7 +49,8 @@ test
await new Promise((resolve) => setTimeout(resolve, 2000));
await t
.useRole(roles.bucketRead)
.navigateTo("http://localhost:9090/browser")
.click(acknowledgeButton)
.typeText(elements.filterBuckets, `${TEST_BUCKET_NAME_SPECIFIC}-6`)
.click(namedTestBucketBrowseButtonFor(`${TEST_BUCKET_NAME_SPECIFIC}-6`))
.expect(elements.table.exists)
.ok();
@@ -184,7 +75,8 @@ test
);
await t
.useRole(roles.bucketSpecific)
.navigateTo("http://localhost:9090/browser")
.click(acknowledgeButton)
.typeText(elements.filterBuckets, `${TEST_BUCKET_NAME_SPECIFIC}-7`)
.expect(testBucketBrowseButton.exists)
.ok();
})
@@ -196,26 +88,6 @@ test
);
});
test
.before(async (t) => {
// Create a bucket
await functions.setUpNamedBucket(t, `${TEST_BUCKET_NAME_SPECIFIC}-8`);
})("Bucket access is set to R/W", async (t) => {
await new Promise((resolve) => setTimeout(resolve, 2000));
await t
.useRole(roles.bucketSpecific)
.navigateTo("http://localhost:9090/buckets")
.expect(Selector(`#access-${TEST_BUCKET_NAME_SPECIFIC}-8`).innerText)
.eql("Access: R/W");
})
.after(async (t) => {
// Cleanup created bucket and corresponding uploads
await functions.cleanUpNamedBucketAndUploads(
t,
`${TEST_BUCKET_NAME_SPECIFIC}-8`,
);
});
test
.before(async (t) => {
// Create a bucket
@@ -227,7 +99,8 @@ test
);
await t
.useRole(roles.bucketSpecific)
.navigateTo("http://localhost:9090/browser")
.click(acknowledgeButton)
.typeText(elements.filterBuckets, `${TEST_BUCKET_NAME_SPECIFIC}-9`)
.click(testBucketBrowseButton)
.expect(uploadExists)
.ok();
@@ -250,7 +123,8 @@ test
);
await t
.useRole(roles.bucketSpecific)
.navigateTo("http://localhost:9090/browser")
.click(acknowledgeButton)
.typeText(elements.filterBuckets, `${TEST_BUCKET_NAME_SPECIFIC}-10`)
.click(testBucketBrowseButton)
// Upload object to bucket
.setFilesToUpload(elements.uploadInput, "../uploads/test.txt");
@@ -270,7 +144,8 @@ test
})("Object list table is disabled", async (t) => {
await t
.useRole(roles.bucketSpecific)
.navigateTo("http://localhost:9090/browser")
.click(acknowledgeButton)
.typeText(elements.filterBuckets, `${TEST_BUCKET_NAME_SPECIFIC}-11`)
.click(namedTestBucketBrowseButtonFor(`${TEST_BUCKET_NAME_SPECIFIC}-11`))
.expect(elements.bucketsTableDisabled.exists)
.ok();

View File

@@ -1,58 +0,0 @@
// 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 { logsElement, monitoringElement } from "../utils/elements-menu";
fixture("For user with Logs permissions")
.page("http://localhost:9090")
.beforeEach(async (t) => {
await t.useRole(roles.logs);
});
test("Tools sidebar item exists", async (t) => {
await t.expect(monitoringElement.exists).ok();
});
test("Logs link exists in Tools page", async (t) => {
await t
.expect(monitoringElement.exists)
.ok()
.click(monitoringElement)
.expect(logsElement.exists)
.ok();
});
test("Logs page can be opened", async (t) => {
await t.navigateTo("http://localhost:9090/tools/logs");
});
test("Log window exists in Logs page", async (t) => {
const logWindowExists = elements.logWindow.exists;
await t
.navigateTo("http://localhost:9090/tools/logs")
.expect(logWindowExists)
.ok();
});
test("Node selector exists in Logs page", async (t) => {
const nodeSelectorExists = elements.nodeSelector.exists;
await t
.navigateTo("http://localhost:9090/tools/logs")
.expect(nodeSelectorExists)
.ok();
});

View File

@@ -18,6 +18,8 @@ import * as roles from "../utils/roles";
import { Selector } from "testcafe";
import * as functions from "../utils/functions";
import { namedTestBucketBrowseButtonFor } from "../utils/functions";
import * as elements from "../utils/elements";
import { acknowledgeButton } from "../utils/elements";
fixture("Test resources policy").page("http://localhost:9090/");
@@ -48,7 +50,8 @@ test
async (t) => {
await t
.useRole(roles.admin)
.navigateTo(`http://localhost:9090/browser`)
.click(acknowledgeButton)
.typeText(elements.filterBuckets, bucket1)
.click(test1BucketBrowseButton)
.click(Selector(".ReactVirtualized__Table__rowColumn").withText("abc"))
.click(Selector("#delete-element-click"))

View File

@@ -18,6 +18,8 @@ import * as roles from "../utils/roles";
import { Selector } from "testcafe";
import * as functions from "../utils/functions";
import { namedTestBucketBrowseButtonFor } from "../utils/functions";
import * as elements from "../utils/elements";
import { acknowledgeButton } from "../utils/elements";
fixture("Test error visibility in Object Browser Navigation").page(
"http://localhost:9090/",
@@ -59,7 +61,8 @@ test
async (t) => {
await t
.useRole(roles.conditions3)
.navigateTo(`http://localhost:9090/browser`)
.click(acknowledgeButton)
.typeText(elements.filterBuckets, bucketName)
.click(bucketBrowseButton)
.click(Selector(".ReactVirtualized__Table__rowColumn").withText("home"))
.click(
@@ -100,7 +103,8 @@ test
async (t) => {
await t
.useRole(roles.conditions4)
.navigateTo(`http://localhost:9090/browser`)
.click(acknowledgeButton)
.typeText(elements.filterBuckets, bucketName2)
.click(bucketBrowseButton2)
.click(Selector("label").withText("Show deleted objects"))
.wait(1500)

View File

@@ -18,6 +18,8 @@ import * as roles from "../utils/roles";
import { Selector } from "testcafe";
import * as functions from "../utils/functions";
import { namedTestBucketBrowseButtonFor } from "../utils/functions";
import * as elements from "../utils/elements";
import { acknowledgeButton } from "../utils/elements";
fixture("Test Preview page in Console").page("http://localhost:9090/");
@@ -25,13 +27,6 @@ const bucketName = "preview";
export const file = Selector(".ReactVirtualized__Table__rowColumn").withText(
"internode.png",
);
export const fileScript = Selector(
".ReactVirtualized__Table__rowColumn",
).withText("filescript.pdf");
export const pdfFile = Selector(".ReactVirtualized__Table__rowColumn").withText(
"file1.pdf",
);
const bucketNameAction = namedTestBucketBrowseButtonFor(bucketName);
@@ -47,7 +42,8 @@ test
})("File can be previewed", async (t) => {
await t
.useRole(roles.admin)
.navigateTo(`http://localhost:9090/browser`)
.click(acknowledgeButton)
.typeText(elements.filterBuckets, bucketName)
.click(bucketNameAction)
.click(file)
.click(Selector(".objectActions button").withText("Preview"))
@@ -57,52 +53,3 @@ test
.after(async (t) => {
await functions.cleanUpNamedBucketAndUploads(t, bucketName);
});
test
.before(async (t) => {
await functions.setUpNamedBucket(t, bucketName);
await functions.uploadNamedObjectToBucket(
t,
bucketName,
"file1.pdf",
"web-app/tests/uploads/file1.pdf",
);
})("PDF File can be previewed", async (t) => {
await t
.useRole(roles.admin)
.navigateTo(`http://localhost:9090/browser`)
.click(bucketNameAction)
.click(pdfFile)
.click(Selector(".objectActions button").withText("Preview"))
.expect(Selector(".react-pdf__Page__canvas").exists)
.ok();
})
.after(async (t) => {
await functions.cleanUpNamedBucketAndUploads(t, bucketName);
});
test
.before(async (t) => {
await functions.setUpNamedBucket(t, bucketName);
await functions.uploadNamedObjectToBucket(
t,
bucketName,
"filescript.pdf",
"web-app/tests/uploads/filescript.pdf",
);
})("PDF with Alert doesn't execute script", async (t) => {
await t
.useRole(roles.admin)
.navigateTo(`http://localhost:9090/browser`)
.click(bucketNameAction)
.click(fileScript)
.click(Selector(".objectActions button").withText("Preview"))
.setNativeDialogHandler(() => false);
const history = await t.getNativeDialogHistory();
await t.expect(history.length).eql(0);
})
.after(async (t) => {
await functions.cleanUpNamedBucketAndUploads(t, bucketName);
});

View File

@@ -21,6 +21,8 @@ import {
cleanUpNamedBucketAndUploads,
namedTestBucketBrowseButtonFor,
} from "../utils/functions";
import * as elements from "../utils/elements";
import { acknowledgeButton } from "../utils/elements";
fixture("Test resources policy").page("http://localhost:9090/");
@@ -66,7 +68,8 @@ test
async (t) => {
await t
.useRole(roles.conditions2)
.navigateTo(`http://localhost:9090/browser`)
.click(acknowledgeButton)
.typeText(elements.filterBuckets, bucket1)
.click(test1BucketBrowseButton)
.wait(1500)
.click(
@@ -122,7 +125,8 @@ test
})("User can browse from first level as policy has wildcard", async (t) => {
await t
.useRole(roles.conditions1)
.navigateTo(`http://localhost:9090/browser`)
.click(acknowledgeButton)
.typeText(elements.filterBuckets, bucket1)
.click(test1BucketBrowseButton)
.wait(1500)
.click(
@@ -186,7 +190,8 @@ test
})("User can browse from sub levels as policy has wildcard", async (t) => {
await t
.useRole(roles.conditions3)
.navigateTo(`http://localhost:9090/browser`)
.click(acknowledgeButton)
.typeText(elements.filterBuckets, bucket3)
.click(test3BucketBrowseButton)
.wait(1500)
.click(Selector(".ReactVirtualized__Table__rowColumn").withText("home"))
@@ -206,6 +211,7 @@ test
.expect(file.exists)
.ok()
.navigateTo(`http://localhost:9090/browser`)
.click(acknowledgeButton)
.click(test3BucketBrowseButton)
.wait(1500)
.click(Selector(".ReactVirtualized__Table__rowColumn").withText("home"))

View File

@@ -18,6 +18,8 @@ import * as roles from "../utils/roles";
import { Selector } from "testcafe";
import * as functions from "../utils/functions";
import { namedTestBucketBrowseButtonFor } from "../utils/functions";
import * as elements from "../utils/elements";
import { acknowledgeButton } from "../utils/elements";
fixture("Test resources policy").page("http://localhost:9090/");
@@ -42,7 +44,8 @@ test
async (t) => {
await t
.useRole(roles.admin)
.navigateTo(`http://localhost:9090/browser`)
.click(acknowledgeButton)
.typeText(elements.filterBuckets, bucketName)
.click(testBucketBrowseButton)
.wait(1500)
.click(Selector("label").withText("Show deleted objects"))

View File

@@ -1,117 +0,0 @@
// 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";
import { identityElement, usersElement } from "../utils/elements-menu";
import { IAM_PAGES } from "../../src/common/SecureComponent/permissions";
const userListItem = Selector(".ReactVirtualized__Table__rowColumn").withText(
constants.TEST_USER_NAME,
);
const policyListItem = Selector(".ReactVirtualized__Table__rowColumn").withText(
constants.TEST_ASSIGN_POLICY_NAME,
);
const userDeleteIconButton = userListItem
.child("checkbox")
.withAttribute("aria-label", "secondary checkbox");
const userCheckbox = Selector(".TableCheckbox span.checkbox");
fixture("For user with Users permissions")
.page("http://localhost:9090")
.beforeEach(async (t) => {
await t.useRole(roles.users);
});
test("Users sidebar item exists", async (t) => {
const usersExist = usersElement.exists;
await t
.expect(identityElement.exists)
.ok()
.click(identityElement)
.expect(usersExist)
.ok();
});
const appBaseUrl = "http://localhost:9090";
let usersPageUrl = `${appBaseUrl}${IAM_PAGES.USERS}`;
let usersAddPageUrl = `${appBaseUrl}${IAM_PAGES.USER_ADD}`;
test("Create User button exists", async (t) => {
const createUserButtonExists = elements.createUserButton.exists;
await t.navigateTo(usersPageUrl).expect(createUserButtonExists).ok();
});
test("Create User button is clickable", async (t) => {
await t.navigateTo(usersPageUrl).click(elements.createUserButton);
});
test("Create User Page to create a user", async (t) => {
const accessKeyInputExists = elements.usersAccessKeyInput.exists;
const secretKeyInputExists = elements.usersSecretKeyInput.exists;
await t
.navigateTo(usersAddPageUrl)
.expect(accessKeyInputExists)
.ok()
.expect(secretKeyInputExists)
.ok()
.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(usersPageUrl).expect(usersTableExists).ok();
});
test("IAM Policy can be set on User", async (t) => {
const userListItemExists = userListItem.exists;
const policyListItemExists = policyListItem.exists;
await t
.navigateTo(usersPageUrl)
.typeText(elements.searchResourceInput, constants.TEST_USER_NAME)
.expect(userListItemExists)
.ok()
.click(userListItem)
.click(elements.userPolicies)
.click(elements.assignPoliciesButton)
.typeText(elements.searchResourceInput, constants.TEST_ASSIGN_POLICY_NAME)
.click(userCheckbox)
.click(elements.saveButton)
.expect(policyListItemExists)
.ok();
});
test("Created User can be viewed and deleted", async (t) => {
const userListItemExists = userListItem.exists;
const deleteSelectedButton = Selector("button").withAttribute(
"id",
"delete-selected-users",
);
await t
.navigateTo(usersPageUrl)
.typeText(elements.searchResourceInput, constants.TEST_USER_NAME)
.expect(userListItemExists)
.ok()
.click(userCheckbox)
.click(deleteSelectedButton)
.click(elements.deleteButton)
.expect(userListItemExists)
.notOk();
});

View File

@@ -19,12 +19,10 @@ import * as elements from "../utils/elements";
import * as functions from "../utils/functions";
import {
namedTestBucketBrowseButtonFor,
setUpNamedBucket,
setVersionedBucket,
testBucketBrowseButtonFor,
} from "../utils/functions";
import { Selector } from "testcafe";
import { deniedError, file } from "../permissions-4/resourceTesting";
import { acknowledgeButton } from "../utils/elements";
fixture("Rewind Testing").page("http://localhost:9090");
@@ -38,7 +36,8 @@ test
await functions.setVersioned(t, "abucketrewind");
await t
.useRole(roles.bucketReadWrite)
.navigateTo("http://localhost:9090/browser")
.click(acknowledgeButton)
.typeText(elements.filterBuckets, "abucketrewind")
.click(testBucketBrowseButtonFor("abucketrewind"))
// Upload object to bucket
.setFilesToUpload(elements.uploadInput, "../uploads/test.txt")
@@ -51,7 +50,8 @@ test
})("Rewind works in bucket", async (t) => {
await t
.useRole(roles.bucketReadWrite)
.navigateTo("http://localhost:9090/browser")
.click(acknowledgeButton)
.typeText(elements.filterBuckets, "abucketrewind")
.click(testBucketBrowseButtonFor("abucketrewind"))
.expect(elements.table.exists)
.ok()
@@ -87,7 +87,8 @@ test
})("Rewind button enabled in bucket", async (t) => {
await t
.useRole(roles.rewindEnabled)
.navigateTo(`http://localhost:9090/browser`)
.click(acknowledgeButton)
.typeText(elements.filterBuckets, bucketname)
.click(test3BucketBrowseButton)
.wait(1500)
.click(
@@ -124,7 +125,8 @@ test
})("Rewind button disabled in bucket", async (t) => {
await t
.useRole(roles.rewindNotEnabled)
.navigateTo(`http://localhost:9090/browser`)
.click(acknowledgeButton)
.typeText(elements.filterBuckets, bucketname)
.click(test3BucketBrowseButton)
.wait(1500)
.click(

View File

@@ -1,122 +0,0 @@
// 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";
import {
iamPoliciesElement,
identityElement,
usersElement,
} from "../utils/elements-menu";
import { IAM_PAGES } from "../../src/common/SecureComponent/permissions";
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:9090")
.beforeEach(async (t) => {
await t.useRole(roles.iamPolicies);
});
test("IAM Policies sidebar item exists", async (t) => {
const iamPoliciesExist = iamPoliciesElement.exists;
await t
.expect(identityElement.exists)
.ok()
.click(identityElement)
.expect(iamPoliciesExist)
.ok();
});
test("Create Policy button exists", async (t) => {
const createPolicyButtonExists = elements.createPolicyButton.exists;
await t
.navigateTo(`http://localhost:9090${IAM_PAGES.POLICIES}`)
.expect(createPolicyButtonExists)
.ok();
});
test("Create Policy button is clickable", async (t) => {
await t
.navigateTo(`http://localhost:9090${IAM_PAGES.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:9090${IAM_PAGES.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:9090${IAM_PAGES.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:9090${IAM_PAGES.POLICIES}`)
.click(elements.createPolicyButton)
.typeText(elements.createPolicyName, constants.TEST_IAM_POLICY_NAME)
.typeText(elements.createPolicyTextfield, constants.TEST_IAM_POLICY, {
paste: true,
replace: true,
})
.click(elements.saveButton);
}).after(async (t) => {
// Clean up created policy
await t
.navigateTo(`http://localhost:9090${IAM_PAGES.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:9090${IAM_PAGES.POLICIES}`)
.click(elements.createPolicyButton)
.typeText(elements.createPolicyName, constants.TEST_IAM_POLICY_NAME)
.typeText(elements.createPolicyTextfield, constants.TEST_IAM_POLICY, {
paste: true,
replace: 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

@@ -17,6 +17,7 @@
import * as roles from "../utils/roles";
import * as elements from "../utils/elements";
import { Selector } from "testcafe";
import { acknowledgeButton } from "../utils/elements";
fixture("For user with Bucket Write to specific prefix permissions").page(
"http://localhost:9090",
@@ -27,9 +28,11 @@ test
"Upload File button is disable and Upload Folder button is enabled on bucket root path",
async (t) => {
const uploadButton = elements.uploadButton;
await t
.useRole(roles.bucketWritePrefixOnly)
.navigateTo("http://localhost:9090/browser/testcafe")
.click(acknowledgeButton)
.click(uploadButton)
.expect(
Selector("div")
@@ -52,9 +55,11 @@ test
"Upload File and Folder buttons are enabled on bucket prefix path",
async (t) => {
const uploadButton = elements.uploadButton;
await t
.useRole(roles.bucketWritePrefixOnly)
.navigateTo("http://localhost:9090/browser/testcafe/write")
.click(acknowledgeButton)
.click(uploadButton)
.expect(
Selector("div")

View File

@@ -80,6 +80,7 @@ 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 filterBuckets = Selector("#filter-buckets");
export const filterUserInput = searchResourceInput.withAttribute(
"placeholder",
"Filter Users",
@@ -207,3 +208,10 @@ export const locationEmpty = Selector("div").withAttribute(
// Login Window
//----------------------------------------------------
export const loginButton = Selector("button").withAttribute("id", "do-login");
//----------------------------------------------------
// Ackwnowledge Button
//----------------------------------------------------
export const acknowledgeButton = Selector("button").withAttribute(
"id",
"acknowledge-confirm",
);

View File

@@ -110,7 +110,7 @@ export const cleanUpBucket = (t, modifier) => {
};
export const namedTestBucketBrowseButtonFor = (name) => {
return Selector("span").withAttribute("id", `browse-${name}`);
return Selector("button").withAttribute("id", `manageBucket-${name}`);
};
export const testBucketBrowseButtonFor = (modifier) => {