Skip to content

Commit

Permalink
Adopting Playwright
Browse files Browse the repository at this point in the history
  • Loading branch information
cniackz committed Mar 11, 2023
1 parent 4cceee8 commit 096b85b
Show file tree
Hide file tree
Showing 14 changed files with 1,075 additions and 1,159 deletions.
1,209 changes: 67 additions & 1,142 deletions .github/workflows/jobs.yaml

Large diffs are not rendered by default.

10 changes: 10 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
# Playwright Data
portal-ui/storage/
portal-ui/playwright/.auth/admin.json

# Report from Playwright
portal-ui/playwright-report/

# Coverage from Playwright
portal-ui/.nyc_output/

# Binaries for programs and plugins
*.exe
*.exe~
Expand Down
9 changes: 9 additions & 0 deletions portal-ui/config-overrides.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,12 @@ module.exports = function override(config, env) {
config = rewireReactHotLoader(config, env);
return config;
};

const { override, addBabelPlugins } = require("customize-cra");

console.log("add babel plugin");

module.exports = override(
process.env.USE_BABEL_PLUGIN_ISTANBUL &&
addBabelPlugins("babel-plugin-istanbul")
);
33 changes: 33 additions & 0 deletions portal-ui/e2e/auth.setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// This file is part of MinIO Console Server
// Copyright (c) 2023 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 { test as setup } from "@playwright/test";
import { minioadminFile } from "./consts";

setup("authenticate as admin", async ({ page }) => {
// Perform authentication steps. Replace these actions with your own.
await page.goto("http://localhost:5005");
await page.getByPlaceholder("Username").click();
await page.getByPlaceholder("Username").fill("minioadmin");
await page.getByPlaceholder("Password").click();
await page.getByPlaceholder("Password").fill("minioadmin");
await page.getByRole("button", { name: "Login" }).click();

// we need to give the browser time to store the cookies
await page.waitForTimeout(1000);
// End of authentication steps.

await page.context().storageState({ path: minioadminFile });
});
49 changes: 49 additions & 0 deletions portal-ui/e2e/buckets.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// This file is part of MinIO Console Server
// Copyright (c) 2023 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 { expect } from "@playwright/test";
import { generateUUID, test } from "./fixtures/baseFixture";
import { minioadminFile } from "./consts";

test.use({ storageState: minioadminFile });

test.beforeEach(async ({ page }) => {
await page.goto("http://localhost:5005/");
});

test("create a new bucket", async ({ page }) => {
await page.getByRole("link", { name: "Buckets Buckets" }).click();
await page.getByRole("button", { name: "Create Bucket" }).click();
await page.getByLabel("Bucket Name*").click();

const bucketName = `new-bucket-${generateUUID()}`;

await page.getByLabel("Bucket Name*").fill(bucketName);
await page.getByRole("button", { name: "Create Bucket" }).click();
await expect(page.locator(`#manageBucket-${bucketName}`)).toBeTruthy();
});

test("invalid bucket name", async ({ page }) => {
await page.getByRole("link", { name: "Buckets Buckets" }).click();
await page.getByRole("button", { name: "Create Bucket" }).click();
await page.getByLabel("Bucket Name*").click();
await page.getByLabel("Bucket Name*").fill("invalid name");
await page.getByRole("button", { name: "View Bucket Naming Rules" }).click();
await expect(
page.getByText(
"Bucket names can consist only of lowercase letters, numbers, dots (.), and hyphe"
)
).toBeTruthy();
});
17 changes: 17 additions & 0 deletions portal-ui/e2e/consts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// This file is part of MinIO Console Server
// Copyright (c) 2023 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/>.

export const minioadminFile = "playwright/.auth/admin.json";
61 changes: 61 additions & 0 deletions portal-ui/e2e/fixtures/baseFixture.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// This file is part of MinIO Console Server
// Copyright (c) 2023 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 fs from "fs";
import * as path from "path";
import * as crypto from "crypto";
import { test as baseTest } from "@playwright/test";

const istanbulCLIOutput = path.join(process.cwd(), ".nyc_output");

export function generateUUID(): string {
return crypto.randomBytes(16).toString("hex");
}

export const test = baseTest.extend({
context: async ({ context }, use) => {
await context.addInitScript(() =>
window.addEventListener("beforeunload", () =>
(window as any).collectIstanbulCoverage(
JSON.stringify((window as any).__coverage__)
)
)
);
await fs.promises.mkdir(istanbulCLIOutput, { recursive: true });
await context.exposeFunction(
"collectIstanbulCoverage",
(coverageJSON: string) => {
if (coverageJSON)
fs.writeFileSync(
path.join(
istanbulCLIOutput,
`playwright_coverage_${generateUUID()}.json`
),
coverageJSON
);
}
);
await use(context);
for (const page of context.pages()) {
await page.evaluate(() =>
(window as any).collectIstanbulCoverage(
JSON.stringify((window as any).__coverage__)
)
);
}
},
});

export const expect = test.expect;
37 changes: 37 additions & 0 deletions portal-ui/e2e/groups.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// This file is part of MinIO Console Server
// Copyright (c) 2023 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 { expect } from "@playwright/test";
import { generateUUID, test } from "./fixtures/baseFixture";
import { minioadminFile } from "./consts";

test.use({ storageState: minioadminFile });

test.beforeEach(async ({ page }) => {
await page.goto("http://localhost:5005/");
});

test("Add a new group", async ({ page }) => {
await page.getByRole("button", { name: "Identity Identity" }).click();
await page.getByRole("link", { name: "Groups Groups" }).click();
await page.getByRole("button", { name: "Create Group" }).click();

const groupName = `new-group-${generateUUID()}`;

await page.getByLabel("Group Name").fill(groupName);
await page.getByRole("button", { name: "Save" }).click();
await expect(page.getByRole("gridcell", { name: groupName })).toBeTruthy();
});
12 changes: 12 additions & 0 deletions portal-ui/e2e/login.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { test, expect } from "@playwright/test";

test("Basic `minioadmin` Login", async ({ page, context }) => {
await page.goto("http://localhost:5005");
await page.getByPlaceholder("Username").click();
await page.getByPlaceholder("Username").fill("minioadmin");
await page.getByPlaceholder("Password").click();
await page.getByPlaceholder("Password").fill("minioadmin");
await page.getByRole("button", { name: "Login" }).click();
await context.storageState({ path: "storage/minioadmin.json" });
await expect(page.getByRole("main").getByText("Object Browser")).toBeTruthy();
});
45 changes: 45 additions & 0 deletions portal-ui/e2e/policies.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// This file is part of MinIO Console Server
// Copyright (c) 2023 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 { expect } from "@playwright/test";
import { generateUUID, test } from "./fixtures/baseFixture";
import { minioadminFile } from "./consts";

test.use({ storageState: minioadminFile });

test.beforeEach(async ({ page }) => {
await page.goto("http://localhost:5005/");
});

test("Can create a policy", async ({ page }) => {
await page.getByRole("link", { name: "Policies Policies" }).click();
await page.getByRole("button", { name: "Create Policy" }).click();
await page.getByLabel("Policy Name").click();

const policyName = `policy-${generateUUID()}`;

await page.getByLabel("Policy Name").fill(policyName);
await page.locator("#code_wrapper").click();
await page.locator("#code_wrapper").click();
await page.locator("#code_wrapper").click();
await page.locator("#code_wrapper").press("Meta+a");
await page
.locator("#code_wrapper")
.fill(
'{\n "Version": "2012-10-17",\n "Statement": [\n {\n "Effect": "Allow",\n "Action": [\n "s3:*"\n ],\n "Resource": [\n "arn:aws:s3:::bucket1/*",\n "arn:aws:s3:::bucket2/*",\n "arn:aws:s3:::bucket3/*",\n "arn:aws:s3:::bucket4/*"\n ]\n },\n {\n "Effect": "Deny",\n "Action": [\n "s3:DeleteBucket"\n ],\n "Resource": [\n "arn:aws:s3:::*"\n ]\n }\n ]\n}\n'
);
await page.getByRole("button", { name: "Save" }).click();
await expect(page.getByRole("gridcell", { name: policyName })).toBeTruthy();
});
22 changes: 16 additions & 6 deletions portal-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@
"start": "PORT=5005 react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
"eject": "react-scripts eject",
"playwright": "PORT=5005 USE_BABEL_PLUGIN_ISTANBUL=1 react-app-rewired start"
},
"eslintConfig": {
"extends": "react-app",
Expand All @@ -61,11 +62,9 @@
},
"proxy": "http://localhost:9090/",
"devDependencies": {
"@types/luxon": "^3.2.0",
"@types/react-window": "^1.8.5",
"@types/react-window-infinite-loader": "^1.0.6",
"@types/recharts": "^1.8.24",
"@playwright/test": "^1.31.2",
"@types/lodash": "^4.14.191",
"@types/luxon": "^3.2.0",
"@types/minio": "^7.0.17",
"@types/node": "18.14.6",
"@types/react": "18.0.28",
Expand All @@ -74,10 +73,19 @@
"@types/react-grid-layout": "^1.1.1",
"@types/react-redux": "^7.1.25",
"@types/react-virtualized": "^9.21.21",
"@types/react-window": "^1.8.5",
"@types/react-window-infinite-loader": "^1.0.6",
"@types/recharts": "^1.8.24",
"@types/superagent": "^4.1.16",
"@types/webpack-env": "^1.14.1",
"@types/websocket": "^1.0.0",
"babel-plugin-istanbul": "^6.1.1",
"customize-cra": "^1.0.0",
"nyc": "^15.1.0",
"playwright": "^1.31.2",
"prettier": "2.8.4",
"react-app-rewire-hot-loader": "^2.0.1",
"react-app-rewired": "^2.2.1",
"react-scripts": "5.0.1",
"testcafe": "^2.3.0",
"typescript": "^4.4.3"
Expand All @@ -96,5 +104,7 @@
"react-scripts/**/debug": "^3.1.0",
"recharts/**/d3-color": "^3.1.0",
"websocket/debug": "^3.1.0"
}
},
"main": "index.js",
"license": "MIT"
}
Loading

0 comments on commit 096b85b

Please sign in to comment.