mirror of
https://github.com/usebruno/bruno.git
synced 2026-06-28 07:04:10 +00:00
* test cases for workspace import and validation TC-969, jira: https://usebruno.atlassian.net/browse/BRU-3575 * incorporated comments, moved findWorkspaceDirByName function to helpers.ts, fixed all the comments * modified as per comment provided , removed css locators , used playwright inbuilt methods , handled timeout * Created file structure as per comment provided, added tc-id , resolved code-rabbit review * incorporated comments removed commented line, removed timeouts, modified package.json added package in dev dependencies * changed const l to locators for better readbility * - Reorganized test helpers: split title-bar locators into title-bar.ts and import-workspace flow into workspace/import-workspace.ts for reuse - Replaced brittle .bruno-modal-card/CSS locators with stable role/testid/label based locators - Added a data-testid for the Import Workspace modal and removed the redundant one - Cleaned up unnecessary comments - Updated package-lock.json * minor changes * minor changes * addressed comments * addressed comments for variable naming * minor changes
111 lines
3.8 KiB
TypeScript
111 lines
3.8 KiB
TypeScript
import AdmZip from 'adm-zip';
|
|
import * as path from 'path';
|
|
import { clickImportWorkspace } from '../title-bar';
|
|
import { test, expect, Page, Locator, ElectronApplication, waitForReadyPage } from '../../../../playwright';
|
|
|
|
/**
|
|
* Import Workspace modal locators.
|
|
*/
|
|
export const buildImportWorkspaceModalLocators = (page: Page) => {
|
|
// Scope every modal query to the dialog so we avoid the brittle
|
|
const modal = () => page.getByRole('dialog').filter({ hasText: 'Import Workspace' });
|
|
|
|
return {
|
|
// Import Workspace modal
|
|
modal,
|
|
fileInput: () => modal().getByTestId('import-workspace-file-input'),
|
|
selectedFileName: (name: string) => modal().getByText(name),
|
|
removeFileButton: () => modal().getByText('Remove'),
|
|
locationInput: () => modal().getByLabel('Extract Location'),
|
|
browseLink: () => modal().getByText('Browse', { exact: true }),
|
|
importButton: () => modal().getByTestId('modal-submit-btn')
|
|
};
|
|
};
|
|
|
|
/**
|
|
* Build a valid Bruno workspace zip on disk that the importer will accept.
|
|
* The zip contains a single `workspace.yml` (info.name + info.type: workspace).
|
|
*
|
|
* @param zipDir - directory in which to write the zip
|
|
* @param workspaceName - the workspace name embedded in workspace.yml
|
|
* @returns absolute path to the created zip file
|
|
*/
|
|
export const createWorkspaceZip = (zipDir: string, workspaceName: string): string => {
|
|
const workspaceYml = [
|
|
'opencollection: 1.0.0',
|
|
'info:',
|
|
` name: "${workspaceName}"`,
|
|
' type: workspace',
|
|
'',
|
|
'collections: []',
|
|
'specs: []',
|
|
'docs: \'\'',
|
|
''
|
|
].join('\n');
|
|
|
|
const zip = new AdmZip();
|
|
zip.addFile('workspace.yml', Buffer.from(workspaceYml, 'utf8'));
|
|
|
|
const zipPath = path.join(zipDir, `${workspaceName}.zip`);
|
|
zip.writeZip(zipPath);
|
|
return zipPath;
|
|
};
|
|
|
|
/**
|
|
* Open the workspace dropdown and launch the Import Workspace modal.
|
|
*/
|
|
export const openImportWorkspaceModal = async (page: Page) => {
|
|
const locators = buildImportWorkspaceModalLocators(page);
|
|
await clickImportWorkspace(page);
|
|
await locators.modal().waitFor({ state: 'visible' });
|
|
};
|
|
|
|
type ImportWorkspaceOptions = {
|
|
zipPath: string;
|
|
/**
|
|
* Where to extract the workspace. When omitted, the modal's pre-filled
|
|
* default location (from preferences.general.defaultLocation) is used as-is.
|
|
*/
|
|
extractLocation?: string;
|
|
app?: ElectronApplication;
|
|
};
|
|
|
|
/**
|
|
* select the zip, ensure an extract location is set, and click Import.
|
|
*/
|
|
export const submitWorkspaceImport = async (page: Page, opts: ImportWorkspaceOptions) => {
|
|
const locators = buildImportWorkspaceModalLocators(page);
|
|
|
|
await test.step('Select the workspace zip file', async () => {
|
|
await locators.fileInput().setInputFiles(opts.zipPath);
|
|
await expect(locators.selectedFileName(path.basename(opts.zipPath))).toBeVisible();
|
|
});
|
|
|
|
await test.step('Ensure an extract location is set', async () => {
|
|
if (opts.extractLocation && opts.app) {
|
|
// Stub the directory picker so Browse resolves to the desired location.
|
|
await opts.app.evaluate(({ dialog }, target: string) => {
|
|
(dialog as { showOpenDialog: typeof dialog.showOpenDialog }).showOpenDialog = () =>
|
|
Promise.resolve({ canceled: false, filePaths: [target] });
|
|
}, opts.extractLocation);
|
|
await locators.locationInput().click();
|
|
await expect(locators.locationInput()).toHaveValue(opts.extractLocation);
|
|
} else {
|
|
// Rely on the pre-filled default location.
|
|
await expect(locators.locationInput()).not.toHaveValue('');
|
|
}
|
|
});
|
|
|
|
await test.step('Submit the import', async () => {
|
|
await locators.importButton().click();
|
|
});
|
|
};
|
|
|
|
/**
|
|
* open the modal and import a zip in one call.
|
|
*/
|
|
export const importWorkspaceFromZip = async (page: Page, opts: ImportWorkspaceOptions) => {
|
|
await openImportWorkspaceModal(page);
|
|
await submitWorkspaceImport(page, opts);
|
|
};
|