Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RBAC E2E Tests #1241

Merged
merged 11 commits into from
Jun 19, 2024
46 changes: 23 additions & 23 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
"build": "node ./scripts/build.js -- --profile",
"build-local-test": "cross-env REACT_APP_BUSINESS=true REACT_APP_CONSOLE_GIT_SHA=abc123 REACT_APP_CONSOLE_GIT_REF=local REACT_APP_BUILD_TIMESTAMP=32503680000 REACT_APP_DEV_HINT=true node ./scripts/build.js",
"install:browsers": "npx playwright install --with-deps",
"e2e-test": "playwright test",
"e2e-test": "playwright test tests/console/ -c playwright.config.ts",
"e2e-test-enterprise": "playwright test tests/console-enterprise/ -c playwright.enterprise.config.ts",
"test": "react-scripts test",
"eject": "react-scripts eject",
"test-interpreter-code": "ts-node --project src/utils/interpreter/tsconfig.json src/utils/interpreter/findFunction.test.ts",
Expand All @@ -32,7 +33,7 @@
"@connectrpc/connect-web": "^1.1.2",
"@heroicons/react": "^1.0.6",
"@monaco-editor/react": "^4.6",
"@playwright/test": "^1.42.0",
"@playwright/test": "^1.44.1",
"@primer/octicons-react": "^17",
"@redpanda-data/ui": "^3.48.0",
"@textea/json-viewer": "^1.24.4",
Expand Down
6 changes: 5 additions & 1 deletion frontend/playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,12 @@ import { defineConfig, devices } from '@playwright/test';
* See https://playwright.dev/docs/test-configuration.
*/
export default defineConfig({
expect: {
timeout: 10000,
},
testDir: './tests',
/* Run tests in files in parallel */
fullyParallel: true,
fullyParallel: false, // TODO enable this in the future
/* Fail the build on CI if you accidentally left test.only in the source code. */
forbidOnly: !!process.env.CI,
/* Retry on CI only */
Expand All @@ -23,6 +26,7 @@ export default defineConfig({
reporter: 'html',
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
navigationTimeout: 10 * 1000,
viewport: { width: 1920, height: 1080 },
headless: !!process.env.CI,
/* Base URL to use in actions like `await page.goto('/')`. */
Expand Down
77 changes: 77 additions & 0 deletions frontend/playwright.enterprise.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { defineConfig, devices } from '@playwright/test';

/**
* Read environment variables from file.
* https://github.com/motdotla/dotenv
*/
// require('dotenv').config();

/**
* See https://playwright.dev/docs/test-configuration.
*/
export default defineConfig({
expect: {
timeout: 15000,
},
testDir: './tests',
/* Run tests in files in parallel */
fullyParallel: false, // TODO enable this in the future
/* Fail the build on CI if you accidentally left test.only in the source code. */
forbidOnly: !!process.env.CI,
/* Retry on CI only */
retries: process.env.CI ? 2 : 0,
/* Opt out of parallel tests on CI. */
workers: process.env.CI ? 1 : undefined,
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: 'html',
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
navigationTimeout: 15 * 1000,
viewport: { width: 1920, height: 1080 },
headless: !!process.env.CI,
/* Base URL to use in actions like `await page.goto('/')`. */
baseURL: process.env.REACT_APP_ORIGIN ??
'http://localhost:3000',

/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: 'on-first-retry',
},

/* Configure projects for major browsers */
projects: [
{ name: 'authenticate', testMatch: /auth\.setup\.ts/ },

{
name: 'Console Enterprise',
testMatch: 'tests/console-enterprise/**/*',
use: {
...devices['Desktop Chrome'],
// Use prepared auth state.
storageState: 'playwright/.auth/user.json',
// baseURL: '// console console-enterprise URL'
},
dependencies: ['authenticate']
},
],

/* Run your local dev server before starting the tests */
webServer: [{
cwd: process.env.CI ? '../../backend/cmd' : '../../console-enterprise/backend/cmd',
command: process.env.CI ?
'go run . --config.filepath=../../console-oss/frontend/tests/config/console.enterprise.config.yaml' :
'go run . --config.filepath=../../../console/frontend/tests/config/console.enterprise.config.yaml',
url: 'http://localhost:9090/admin/startup',
reuseExistingServer: !process.env.CI,
stdout: 'pipe',
stderr: 'pipe',
timeout: 120 * 1000
},
{
command: 'npm run start2',
url: 'http://localhost:3000',
timeout: 120 * 1000,
reuseExistingServer: !process.env.CI,
stdout: 'pipe',
stderr: 'pipe',
}]
});
2 changes: 2 additions & 0 deletions frontend/src/components/pages/acls/Acl.List.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ const PrincipalsTab = observer(() => {
<Section>
<Tooltip isDisabled={Features.createUser} label="The cluster does not support this feature" placement="top" hasArrow>
<Button variant="outline"
data-testid="create-user-button"
isDisabled={!Features.createUser}
onClick={() => appGlobal.history.push('/security/users/create')}>
Create user
Expand Down Expand Up @@ -299,6 +300,7 @@ const RolesTab = observer(() => {

<Section>
<Button
data-testid="create-role-button"
variant="outline"
onClick={() => appGlobal.history.push('/security/roles/create')}
>Create role</Button>
Expand Down
10 changes: 6 additions & 4 deletions frontend/src/components/pages/acls/RoleForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ export const RoleForm = observer(({ initialData }: RoleFormProps) => {
<Box>
<FormField label="Role name" isInvalid={roleNameAlreadyExist} errorText="Role name already exist">
<Input
data-testid="create-role__role-name"
pattern="[a-zA-Z0-9_\-]+"
isDisabled={editMode}
isRequired
Expand All @@ -152,6 +153,7 @@ export const RoleForm = observer(({ initialData }: RoleFormProps) => {

<Button
alignSelf="self-end"
data-testid="roles-allow-all-operations"
variant="outline"
onClick={() => {
if (formState.topicACLs.length == 0) formState.topicACLs.push(createEmptyTopicAcl());
Expand Down Expand Up @@ -181,7 +183,7 @@ export const RoleForm = observer(({ initialData }: RoleFormProps) => {
/>
</FormField>

<Flex flexDirection="column" gap={4}>
<Flex flexDirection="column" gap={4} data-testid="create-role-topics-section">
<Heading>Topics</Heading>
{formState.topicACLs.map((topicACL, index) =>
<ResourceACLsEditor key={index} resourceType="Topic" resource={topicACL} setIsFormValid={setIsFormValid} onDelete={() => {
Expand All @@ -198,7 +200,7 @@ export const RoleForm = observer(({ initialData }: RoleFormProps) => {
</Flex>


<Flex flexDirection="column" gap={4}>
<Flex flexDirection="column" gap={4} data-testid="create-role-consumer-groups-section">
<Heading>Consumer Groups</Heading>
{formState.consumerGroupsACLs.map((acl, index) =>
<ResourceACLsEditor key={index} resourceType="Topic" resource={acl} setIsFormValid={setIsFormValid} onDelete={() => {
Expand All @@ -213,7 +215,7 @@ export const RoleForm = observer(({ initialData }: RoleFormProps) => {
</Box>
</Flex>

<Flex flexDirection="column" gap={4}>
<Flex flexDirection="column" gap={4} data-testid="create-role-transactional-ids-section">
<Heading>Transactional IDs</Heading>
{formState.transactionalIDACLs.map((acl, index) =>
<ResourceACLsEditor key={index} resourceType="Topic" resource={acl} setIsFormValid={setIsFormValid} onDelete={() => {
Expand All @@ -228,7 +230,7 @@ export const RoleForm = observer(({ initialData }: RoleFormProps) => {
</Box>
</Flex>

<Flex flexDirection="column" gap={4}>
<Flex flexDirection="column" gap={4} data-testid="create-role-cluster-section">
<Heading>Cluster</Heading>
<HStack>
<Box flexGrow={1}>
Expand Down
12 changes: 6 additions & 6 deletions frontend/tests/auth.setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ setup('authenticate', async ({ page }) => {
await page.goto('/');

// check if there is an error modal, closed it if needed
const errorOKButton = page.getByTestId('login-error__ok-button')
if(errorOKButton) {
await errorOKButton.click()
}
// const errorOKButton = page.getByTestId('login-error__ok-button')
// if(errorOKButton) {
// await errorOKButton.click()
// }
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for some reason this always seems to fail for me?


await page.getByTestId('auth-username-input').fill('username');
await page.getByTestId('auth-password-input').fill('password');
await page.getByTestId('auth-username-input').fill('e2euser');
await page.getByTestId('auth-password-input').fill('very-secret');
await page.getByTestId('auth-submit').click();

await expect(page.getByTestId('versionTitle')).toBeVisible();
Expand Down
40 changes: 40 additions & 0 deletions frontend/tests/config/console.enterprise.config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
serveFrontend: false
kafka:
brokers: ["localhost:19092"]
schemaRegistry:
enabled: true
urls: ["http://localhost:18081"]
protobuf:
enabled: true
schemaRegistry:
enabled: true
refreshInterval: 5m
redpanda:
adminApi:
enabled: true
urls: ["http://localhost:19644"]
connect:
enabled: true
clusters:
- name: local-connect-cluster
url: http://localhost:18083
- name: local-connect-cluster2
url: http://localhost:18083
server:
listenPort: 9090
allowedOrigins: ["http://localhost:3000", "http://localhost:3001"]
login:
enabled: true
jwtSecret: e2etestjwtsecret
useSecureCookies: false
useCookieChunking: true
plain:
enabled: true
credentials:
- username: "e2euser"
password: "very-secret"
licenseFilepath: ../../frontend/tests/config/redpanda.license
enterprise:
rbac:
enabled: true
roleBindingsFilepath: ../../frontend/tests/config/role-bindings.yaml
2 changes: 1 addition & 1 deletion frontend/tests/config/docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ volumes:
redpanda: null
services:
redpanda:
image: docker.redpanda.com/redpandadata/redpanda:v23.3.8
image: redpandadata/redpanda:v24.1.1
container_name: redpanda
command:
- redpanda start
Expand Down
9 changes: 8 additions & 1 deletion frontend/tests/connector.utils.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { Page, test, expect } from '@playwright/test';
import { ACCESS_KEY, S3_BUCKET_NAME, SECRET_ACCESS_KEY } from './connector.spec';
import { ACCESS_KEY, S3_BUCKET_NAME, SECRET_ACCESS_KEY } from './console/connector.spec';

export const createConnector = async(page: Page, { clusterName, connectorName }: { clusterName: string, connectorName: string}) => {
return await test.step('Create connector', async () => {
await page.goto(`/connect-clusters/${clusterName}`)
await page.waitForURL(`/connect-clusters/${clusterName}`, {
timeout: 5000
})
await page
.getByRole('button', {name: 'Create connector', exact: true})
.click();
Expand Down Expand Up @@ -34,6 +37,10 @@ export const createConnector = async(page: Page, { clusterName, connectorName }:
await expect(page.getByRole('button', {name: 'Create'})).toBeVisible();
await expect(page.getByRole('button', {name: 'Create'})).toBeEnabled();
await page.getByRole('button', {name: 'Create'}).click();

await page.waitForURL(`/connect-clusters/${clusterName}/${connectorName}`, {
timeout: 15000
})
});
}

Expand Down
Loading
Loading