Skip to content
Open
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ const ManageWorkspace = () => {
{ id: 'remove', label: 'Remove', onClick: () => handleCloseClick(workspace) }
]}
>
<button className="more-actions-btn">
<button data-testid="more-actions-btn" className="more-actions-btn">
<IconDots size={14} strokeWidth={1.5} />
</button>
</MenuDropdown>
Expand Down
117 changes: 71 additions & 46 deletions tests/workspace/manage-workspace/manage-workspace.spec.ts

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

All tests are passing when run in parallel with multiple workers. But when run using single worker (npm run test:e2e tests/workspace/manage-workspace/manage-workspace.spec.ts -- --workers=1) it fails due to stale state from the previous test case is not cleaned up.

Original file line number Diff line number Diff line change
@@ -1,68 +1,93 @@
import path from 'path';
import fs from 'fs';
import { test, expect, closeElectronApp } from '../../../playwright';
import { test, expect } from '../../../playwright';
import { createWorkspace } from '../../utils/page/actions';

const initUserDataPath = path.join(__dirname, '../create-workspace/init-user-data');
test.describe('Manage Workspace', () => {
test.beforeEach(async ({ page }) => {
await test.step('Create a workspace', async () => {
await createWorkspace(page, 'Custom Workspace');
});

function findCreatedWorkspaceDirs(location: string): string[] {
return fs.readdirSync(location).filter((e) => {
const fullPath = path.join(location, e);
return (
fs.statSync(fullPath).isDirectory()
&& e !== 'default-workspace'
&& fs.existsSync(path.join(fullPath, 'workspace.yml'))
);
await test.step('Open Manage Workspaces', async () => {
await page.locator('.workspace-name-container').click();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Please use data-testid

await page.locator('.dropdown-item').filter({ hasText: 'Manage workspaces' }).click();
await expect(page.getByText('Manage Workspace', { exact: true })).toBeVisible();
});
});
}

test.describe('Manage Workspace', () => {
test('should open terminal from the workspace actions menu', async ({ launchElectronApp, createTmpDir }) => {
const wsLocation = await createTmpDir('ws-location-terminal');
test.describe('Manage Workspace Actions - Open in Terminal', () => {
test('should open terminal from the workspace actions menu', async ({ page }) => {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Sanity tag is not added here. Do we not need it?

await test.step('Verify default workspace has no actions menu', async () => {
const defaultWorkspaceItem = page.locator('.workspace-item').filter({ hasText: 'My Workspace' });
await expect(defaultWorkspaceItem.locator('.more-actions-btn')).toHaveCount(0);
});

const app = await launchElectronApp({ initUserDataPath, templateVars: { wsLocation } });
const page = await app.firstWindow();
await test.step('Open terminal from workspace actions', async () => {
const workspaceItem = page.locator('.workspace-item').filter({ hasText: 'Custom Workspace' });
await expect(workspaceItem).toBeVisible();
await workspaceItem.locator('.more-actions-btn').click();
await page.locator('.dropdown-item').filter({ hasText: 'Open in Terminal' }).click();
});

await test.step('Verify terminal session opens at the workspace folder', async () => {
const terminalSession = page.getByTestId('session-list-0');
await expect(terminalSession).toBeVisible();
await expect(terminalSession).toContainText('Custom Workspace');
});
});
});

try {
await page.locator('[data-app-state="loaded"]').waitFor({ timeout: 30000 });
test.describe('Manage Workspace Actions - Rename Workspace', () => {
test('Verify renaming a workspace from manage workspace section.', { tag: '@sanity' }, async ({ page }) => {
const workspaceItem = page.locator('.workspace-item').filter({
has: page.locator('.workspace-name', { hasText: 'Custom Workspace' })
});
await expect(workspaceItem).toBeVisible();

Check failure on line 46 in tests/workspace/manage-workspace/manage-workspace.spec.ts

View workflow job for this annotation

GitHub Actions / Detect Flaky Tests

[default] › tests/workspace/manage-workspace/manage-workspace.spec.ts:42:9 › Manage Workspace › Manage Workspace Actions - Rename Workspace › Verify renaming a workspace from manage workspace section. @sanity

4) [default] › tests/workspace/manage-workspace/manage-workspace.spec.ts:42:9 › Manage Workspace › Manage Workspace Actions - Rename Workspace › Verify renaming a workspace from manage workspace section. @sanity Error: expect.toBeVisible: Error: strict mode violation: locator('.workspace-item').filter({ has: locator('.workspace-name').filter({ hasText: 'Custom Workspace' }) }) resolved to 2 elements: 1) <div class="workspace-item">…</div> aka getByText('Custom Workspace/home/runner/bruno/Custom WorkspaceOpenReveal in File Manager') 2) <div class="workspace-item">…</div> aka getByText('Custom Workspace/home/runner/bruno/Custom Workspace - 1OpenReveal in File') Call log: - expect.toBeVisible with timeout 5000ms - waiting for locator('.workspace-item').filter({ has: locator('.workspace-name').filter({ hasText: 'Custom Workspace' }) }) 44 | has: page.locator('.workspace-name', { hasText: 'Custom Workspace' }) 45 | }); > 46 | await expect(workspaceItem).toBeVisible(); | ^ 47 | 48 | await test.step('Click on the more actions button', async () => { 49 | await workspaceItem.locator('.more-actions-btn').click(); at /home/runner/work/bruno/bruno/tests/workspace/manage-workspace/manage-workspace.spec.ts:46:35

await test.step('Create a workspace', async () => {
await page.locator('.workspace-name-container').click();
await page.locator('.dropdown-item').filter({ hasText: 'Create workspace' }).click();
const renameInput = page.locator('.workspace-name-input');
await expect(renameInput).toBeVisible({ timeout: 5000 });
await renameInput.fill('Terminal Workspace');
await renameInput.press('Enter');
await expect(page.getByText('Workspace created!')).toBeVisible({ timeout: 10000 });
await test.step('Click on the more actions button', async () => {
await workspaceItem.locator('.more-actions-btn').click();
await page.locator('.dropdown-item').filter({ hasText: 'Rename' }).click();
await expect(page.locator('.bruno-modal-card')).toBeVisible();
});

const wsDirs = findCreatedWorkspaceDirs(wsLocation);
expect(wsDirs).toHaveLength(1);
await test.step('Enter a new name for the workspace in the editing field.', async () => {
const workspaceNameInput = page.locator('#workspace-name');
await expect(workspaceNameInput).toBeVisible();
await workspaceNameInput.fill('New Workspace Name');
await page.getByTestId('modal-submit-btn').filter({ hasText: 'Rename' }).click();
});

await test.step('Open Manage Workspaces', async () => {
await page.locator('.workspace-name-container').click();
await page.locator('.dropdown-item').filter({ hasText: 'Manage workspaces' }).click();
await expect(page.getByText('Manage Workspace')).toBeVisible({ timeout: 5000 });
await test.step('Verify the workspace name is updated in the workspace list.', async () => {
const renamedWorkspaceName = page.getByTestId('workspace-name');
await expect(renamedWorkspaceName).toHaveText('New Workspace Name');
const manageWorkspaceItem = page.locator('.workspace-item').filter({
has: page.locator('.workspace-name', { hasText: 'New Workspace Name' })
});
await expect(manageWorkspaceItem).toBeVisible();
});
});
});

await test.step('Verify default workspace has no actions menu', async () => {
const defaultWorkspaceItem = page.locator('.workspace-item').filter({ hasText: 'My Workspace' });
await expect(defaultWorkspaceItem.locator('.more-actions-btn')).toHaveCount(0);
test.describe('Manage Workspace Actions - Remove Workspace', () => {
test('Verify removing a Workspace from manage workspace section', { tag: '@sanity' }, async ({ page }) => {
const workspaceItem = page.locator('.workspace-item').filter({
has: page.locator('.workspace-name', { hasText: 'Custom Workspace' })
});
await expect(workspaceItem).toBeVisible();

Check failure on line 77 in tests/workspace/manage-workspace/manage-workspace.spec.ts

View workflow job for this annotation

GitHub Actions / Playwright E2E Tests (Linux)

[default] › tests/workspace/manage-workspace/manage-workspace.spec.ts:73:9 › Manage Workspace › Manage Workspace Actions - Remove Workspace › Verify removing a Workspace from manage workspace section @sanity

5) [default] › tests/workspace/manage-workspace/manage-workspace.spec.ts:73:9 › Manage Workspace › Manage Workspace Actions - Remove Workspace › Verify removing a Workspace from manage workspace section @sanity Error: expect.toBeVisible: Error: strict mode violation: locator('.workspace-item').filter({ has: locator('.workspace-name').filter({ hasText: 'Custom Workspace' }) }) resolved to 2 elements: 1) <div class="workspace-item">…</div> aka getByText('Custom Workspace/home/runner/bruno/Custom WorkspaceOpenReveal in File Manager') 2) <div class="workspace-item">…</div> aka getByText('Custom Workspace/home/runner/bruno/Custom Workspace - 2OpenReveal in File') Call log: - expect.toBeVisible with timeout 5000ms - waiting for locator('.workspace-item').filter({ has: locator('.workspace-name').filter({ hasText: 'Custom Workspace' }) }) 75 | has: page.locator('.workspace-name', { hasText: 'Custom Workspace' }) 76 | }); > 77 | await expect(workspaceItem).toBeVisible(); | ^ 78 | 79 | await test.step('Click on the 3 dots icon on the workspace you want to remove', async () => { 80 | await workspaceItem.locator('.more-actions-btn').click(); at /home/runner/work/bruno/bruno/tests/workspace/manage-workspace/manage-workspace.spec.ts:77:35

await test.step('Open terminal from workspace actions', async () => {
const workspaceItem = page.locator('.workspace-item').filter({ hasText: 'Terminal Workspace' });
await expect(workspaceItem).toBeVisible({ timeout: 5000 });
await test.step('Click on the 3 dots icon on the workspace you want to remove', async () => {
await workspaceItem.locator('.more-actions-btn').click();
await page.locator('.dropdown-item').filter({ hasText: 'Open in Terminal' }).click();
await expect(page.getByTestId('menu-dropdown-dropdown')).toBeVisible();
await page.getByTestId('menu-dropdown-remove').click();
await expect(page.locator('.bruno-modal-card')).toBeVisible();
await expect(page.locator('.bruno-modal-content span').first()).toHaveText('Custom Workspace');
});

await test.step('Verify terminal session opens at the workspace folder', async () => {
const terminalSession = page.getByTestId('session-list-0');
await expect(terminalSession).toBeVisible({ timeout: 5000 });
await expect(terminalSession).toContainText(wsDirs[0]);
await test.step('Click on the Remove button in the modal.', async () => {
await page.getByTestId('modal-submit-btn').click();
await expect(page.locator('.workspace-item').filter({ hasText: 'Custom Workspace' })).not.toBeVisible({ timeout: 10000 });
});
} finally {
await closeElectronApp(app);
}
});
});
});
56 changes: 45 additions & 11 deletions tests/workspace/open-workspace/open-workspace.spec.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,60 @@
import type { ElectronApplication } from '@playwright/test';
import { expect, test } from '../../../playwright';
import { buildCommonLocators, waitForReadyPage } from '../../utils/page';
import fs from 'fs/promises';

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

remove this file changes add a separate PR for this.

import path from 'path';

test.describe('Open Workspace', () => {
test('click on cancel button, should just close the dialog', async ({
launchElectronApp,
createTmpDir
}) => {
test('Verify the open an existing workspace from device', { tag: '@sanity' }, async ({ launchElectronApp, createTmpDir }) => {
const workspacePath = await createTmpDir('my-workspace');
await fs.writeFile(path.join(workspacePath, 'workspace.yml'),
`
opencollection: 1.0.0

info:
name: "my-workspace"
type: workspace
`
);

await fs.mkdir(path.join(workspacePath, 'collections'), { recursive: true });

const userDataPath = await createTmpDir('open-workspace');
const app: ElectronApplication = await launchElectronApp({ userDataPath });
const page = await waitForReadyPage(app);
const locators = buildCommonLocators(page);

await app.evaluate(({ dialog }, workspacePath) => {
(dialog as { showOpenDialog: typeof dialog.showOpenDialog }).showOpenDialog = () =>
Promise.resolve({
canceled: false,
filePaths: [workspacePath]
});
},
workspacePath
);

await test.step('Open Workspace from My Workspace menu', async () => {
await page.getByTestId('workspace-menu').click();
await locators.dropdown.item('Open workspace').click();
});

await test.step('Verify workspace opened successfully', async () => {
await expect(page.getByText('Workspace opened successfully', { exact: true })).toBeVisible();
await expect(page.getByTestId('workspace-name')).toHaveText('my-workspace');
});
});

test('click on cancel button, should just close the dialog', async ({ launchElectronApp, createTmpDir }) => {
const userDataPath = await createTmpDir('open-workspace-cancel');

let app: ElectronApplication = await launchElectronApp({ userDataPath });
const page = await waitForReadyPage(app);
const locators = buildCommonLocators(page);

const initialWorkspaceName = await page
.getByTestId('workspace-name')
.textContent();
const initialWorkspaceName = await page.getByTestId('workspace-name').textContent();

await app.evaluate(({ dialog }) => {
(
dialog as { showOpenDialog: typeof dialog.showOpenDialog }
).showOpenDialog = () =>
(dialog as { showOpenDialog: typeof dialog.showOpenDialog }).showOpenDialog = () =>
Promise.resolve({ canceled: true, filePaths: [] });
});

Expand Down
Loading