Oracle FileExplorerWindowRun uses Java's explorer and viewer windows as a person does (the right-click menu, Java's questions answered, the import window, the viewer's open). Both windows work on the document's files through the core's operations: the tree of folders and files, the chosen folder's entries, Java's menu (also as buttons, no right click needed), copy that stays and cut that goes once pasted, the import; the viewer's picture and title. Not taken from Java: a file chosen in the tree taken for a folder, pictures laid over each other, a text file as an empty picture. writeFiles numbers the entries in the file system's order again when a rename made a new key. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
148 lines
9.0 KiB
TypeScript
148 lines
9.0 KiB
TypeScript
// The file explorer and the image viewer on a computer's desktop in
|
||
// Chromium (F4.6f3), on browser/fixtures/web-pages.fls
|
||
// (test/webPagesFixture.test.ts): installed while the simulation runs; a
|
||
// folder made, an entry copied and pasted through Java's right-click menu,
|
||
// renamed and deleted through the buttons (after Java's questions), what the
|
||
// command line makes shown at once, a local file imported; a picture
|
||
// imported and opened in the viewer, a text file refused there.
|
||
|
||
import { dirname, join } from 'node:path';
|
||
import { fileURLToPath } from 'node:url';
|
||
import { expect, test, type Page } from '@playwright/test';
|
||
import { drawing, onDevice, serveEditor } from './editorPage.js';
|
||
|
||
let server: { readonly base: string; readonly close: () => Promise<void> };
|
||
|
||
test.beforeAll(async () => {
|
||
server = await serveEditor();
|
||
});
|
||
|
||
test.afterAll(async () => {
|
||
await server.close();
|
||
});
|
||
|
||
const here = dirname(fileURLToPath(import.meta.url));
|
||
const FIXTURE = join(here, 'fixtures/web-pages.fls');
|
||
const PICTURE = join(here, '../src/assets/desktop/ordner.png');
|
||
|
||
async function openPages(page: Page): Promise<void> {
|
||
await page.goto(`${server.base}?example=new`);
|
||
await page.waitForSelector('svg.filius-canvas');
|
||
await page.locator('input[type="file"]').first().setInputFiles(FIXTURE);
|
||
await expect.poll(async () => (await drawing(page).catch(() => ({ nodes: [] }))).nodes.length).toBe(4);
|
||
await page.getByRole('button', { name: 'Wechselt in den Aktionsmodus' }).click();
|
||
await expect(page.locator('svg.filius-canvas')).toHaveAttribute('data-mode', 'simulation');
|
||
}
|
||
|
||
test('makes, copies, pastes, renames, deletes and imports as Java’s explorer does, and shows a picture in the viewer', async ({ page }) => {
|
||
test.setTimeout(120_000);
|
||
await openPages(page);
|
||
const id = (await drawing(page)).nodes.find((node) => node.name === 'Server')!.id;
|
||
const at = await onDevice(page, id);
|
||
await page.mouse.click(at.x, at.y);
|
||
const desktop = page.locator(`section[data-desktop="${id}"]`);
|
||
await desktop.locator('[data-program="installation"]').click();
|
||
const installation = desktop.locator('[data-program-window="installation"]');
|
||
const available = installation.locator('[data-list="available"] [role="option"]');
|
||
for (const program of ['Datei-Explorer', 'Bildbetrachter', 'Befehlszeile']) await available.filter({ hasText: program }).click();
|
||
await installation.getByRole('button', { name: 'Installieren' }).click();
|
||
await installation.getByRole('button', { name: 'Änderungen annehmen' }).click();
|
||
|
||
await desktop.locator('[data-program="fileExplorer"]').click();
|
||
const window = desktop.locator('[data-program-window="fileExplorer"]');
|
||
await expect(window.locator('.program-titlebar h3')).toHaveText('Datei-Explorer');
|
||
const bar = window.getByRole('toolbar', { name: 'Aktionen' });
|
||
await expect(bar.getByRole('button')).toHaveText(['Importieren', 'Neuer Ordner', 'Löschen', 'Ausschneiden', 'Kopieren', 'Einfügen', 'Umbenennen']);
|
||
await expect(bar.getByRole('button', { name: 'Löschen' })).toBeDisabled();
|
||
await expect(bar.getByRole('button', { name: 'Einfügen' })).toBeDisabled();
|
||
const tree = window.getByRole('list', { name: 'Ordner und Dateien' }).getByRole('button');
|
||
const entries = window.getByRole('list', { name: 'Inhalt des Ordners' }).getByRole('button');
|
||
await expect(entries).toHaveText(['webserver']);
|
||
await expect(tree.first()).toHaveText('/');
|
||
|
||
// A new folder, named in Java's question.
|
||
await bar.getByRole('button', { name: 'Neuer Ordner' }).click();
|
||
const naming = window.getByRole('dialog', { name: 'Neuer Ordner' });
|
||
await naming.getByRole('textbox', { name: 'Neuer Name:' }).fill('ordner');
|
||
await naming.getByRole('button', { name: 'OK' }).click();
|
||
await expect(entries).toHaveText(['webserver', 'ordner']);
|
||
|
||
// Java's right-click menu: on an entry, then on the free space with something copied.
|
||
await entries.filter({ hasText: 'webserver' }).click({ button: 'right' });
|
||
await expect(window.getByRole('menuitem')).toHaveText(['Löschen', 'Ausschneiden', 'Kopieren', 'Umbenennen']);
|
||
await window.getByRole('menuitem', { name: 'Kopieren' }).click();
|
||
await window.locator('.file-explorer-tree [data-path="/ordner"]').click();
|
||
await expect(entries).toHaveCount(0);
|
||
await window.getByRole('list', { name: 'Inhalt des Ordners' }).click({ button: 'right', position: { x: 20, y: 20 } });
|
||
await expect(window.getByRole('menuitem')).toHaveText(['Neuer Ordner', 'Einfügen']);
|
||
await window.getByRole('menuitem', { name: 'Einfügen' }).click();
|
||
await expect(entries).toHaveText(['webserver']);
|
||
// A folder of the list opens with a double click; into the copied folder itself: Java's message.
|
||
await entries.filter({ hasText: 'webserver' }).dblclick();
|
||
await expect(window.locator('.file-explorer-tree [data-path="/ordner/webserver"]')).toHaveAttribute('aria-current', 'true');
|
||
await window.locator('.file-explorer-tree [data-path="/webserver"]').click();
|
||
await bar.getByRole('button', { name: 'Einfügen' }).click();
|
||
await expect(window.getByRole('alert')).toHaveText('Unzulässiger Zielordner!');
|
||
|
||
// Renamed through the button: the old name first, a name there already is said.
|
||
await window.locator('.file-explorer-tree [data-path="/"]').click();
|
||
await entries.filter({ hasText: 'ordner' }).click();
|
||
await bar.getByRole('button', { name: 'Umbenennen' }).click();
|
||
const renaming = window.getByRole('dialog', { name: 'Umbenennen' });
|
||
await expect(renaming.getByRole('textbox', { name: 'Neuer Name:' })).toHaveValue('ordner');
|
||
await renaming.getByRole('textbox', { name: 'Neuer Name:' }).fill('webserver');
|
||
await renaming.getByRole('button', { name: 'OK' }).click();
|
||
await expect(renaming.getByRole('alert')).toHaveText('Den Namen „webserver“ gibt es in diesem Ordner schon.');
|
||
await renaming.getByRole('textbox', { name: 'Neuer Name:' }).fill('Kopie');
|
||
await renaming.getByRole('button', { name: 'OK' }).click();
|
||
await expect(entries).toHaveText(['webserver', 'Kopie']);
|
||
|
||
// Deleted after Java's "Sicher?": no, then yes.
|
||
await bar.getByRole('button', { name: 'Löschen' }).click();
|
||
await window.getByRole('alertdialog', { name: 'Sicher?' }).getByRole('button', { name: 'Nein' }).click();
|
||
await expect(entries).toHaveText(['webserver', 'Kopie']);
|
||
await bar.getByRole('button', { name: 'Löschen' }).click();
|
||
await window.getByRole('alertdialog', { name: 'Sicher?' }).getByRole('button', { name: 'Ja' }).click();
|
||
await expect(entries).toHaveText(['webserver']);
|
||
|
||
// What the command line makes is there at once.
|
||
await desktop.locator('.desktop-home').click();
|
||
await desktop.locator('[data-program="commandPrompt"]').click();
|
||
const input = desktop.locator('input[name="terminalInput"]');
|
||
await input.fill('mkdir extern');
|
||
await input.press('Enter');
|
||
await desktop.locator('.desktop-home').click();
|
||
await desktop.locator('[data-program="fileExplorer"]').click();
|
||
await expect(entries).toHaveText(['webserver', 'extern']);
|
||
|
||
// A local picture imported: the new name is the local file's at first.
|
||
await bar.getByRole('button', { name: 'Importieren' }).click();
|
||
const importing = window.getByRole('dialog', { name: 'Datei importieren' });
|
||
await importing.getByRole('button', { name: 'Datei importieren' }).click();
|
||
await expect(importing.getByRole('status')).toHaveText('Eingabe- und Ausgabedatei müssen angegeben werden!');
|
||
await importing.locator('input[type="file"]').setInputFiles(PICTURE);
|
||
await expect(importing.getByRole('textbox', { name: 'Neuer Name:' })).toHaveValue('ordner.png');
|
||
await importing.getByRole('textbox', { name: 'Neuer Name:' }).fill('bild.png');
|
||
await importing.getByRole('button', { name: 'Datei importieren' }).click();
|
||
await expect(importing.getByRole('status')).toHaveText('Datei erfolgreich importiert!');
|
||
await importing.getByRole('button', { name: 'Schließen' }).click();
|
||
await expect(entries).toHaveText(['webserver', 'extern', 'bild.png']);
|
||
|
||
// The viewer: the picture, its name as the title; a text file is said.
|
||
await desktop.locator('.desktop-home').click();
|
||
await desktop.locator('[data-program="imageViewer"]').click();
|
||
const viewer = desktop.locator('[data-program-window="imageViewer"]');
|
||
await expect(viewer.locator('.program-titlebar h3')).toHaveText('Bildbetrachter');
|
||
await viewer.getByRole('button', { name: 'Öffnen' }).click();
|
||
const dialog = viewer.getByRole('dialog', { name: 'Datei Öffnen' });
|
||
await dialog.locator('.file-dialog-entries button', { hasText: 'bild.png' }).click();
|
||
await dialog.getByRole('button', { name: 'Öffnen' }).click();
|
||
await expect(viewer.locator('.program-titlebar h3')).toHaveText('bild.png');
|
||
await expect.poll(() => viewer.getByRole('img', { name: 'Bild' }).evaluate((image: HTMLImageElement) => image.naturalWidth)).toBe(16);
|
||
await viewer.getByRole('button', { name: 'Öffnen' }).click();
|
||
await dialog.locator('.file-dialog-entries button', { hasText: 'webserver' }).click();
|
||
await dialog.locator('.file-dialog-entries button', { hasText: 'index.html' }).click();
|
||
await dialog.getByRole('button', { name: 'Öffnen' }).click();
|
||
await expect(dialog.getByRole('alert')).toHaveText('„index.html“ ist keine Bilddatei.');
|
||
});
|