diff --git a/e2e/components/apps/Terminal.spec.ts b/e2e/components/apps/Terminal.spec.ts index 56b584f1..5b685b3d 100644 --- a/e2e/components/apps/Terminal.spec.ts +++ b/e2e/components/apps/Terminal.spec.ts @@ -1,11 +1,12 @@ import { test } from "@playwright/test"; -import { TERMINAL_BASE_CD } from "e2e/constants"; +import { TERMINAL_BASE_CD, TERMINAL_TEST_FILE } from "e2e/constants"; import { captureConsoleLogs, disableWallpaper, sendToTerminal, terminalDirectoryMatchesPublicFolder, terminalDoesNotHaveText, + terminalFileMatchesPublicFile, terminalHasRows, terminalHasText, windowIsHidden, @@ -18,34 +19,56 @@ test.beforeEach(async ({ page }) => page.goto("/?app=Terminal")); test.beforeEach(windowsAreVisible); test.beforeEach(terminalHasRows); -test.describe("has directories", () => { - test("has base current directory", async ({ page }) => - terminalHasText({ page }, `${TERMINAL_BASE_CD}>`)); +test.describe("has file system access", () => { + test.describe("has current directory", () => { + test("has default base", async ({ page }) => + terminalHasText({ page }, `${TERMINAL_BASE_CD}>`)); - test("can change directories", async ({ page }) => { - await sendToTerminal({ page }, "cd /"); - await terminalHasText({ page }, "/>"); + test("can change directories", async ({ page }) => { + await sendToTerminal({ page }, "cd /"); + await terminalHasText({ page }, "/>"); + }); }); -}); -test.describe("has directory listings", () => { - test("has base directory", async ({ page }) => - terminalDirectoryMatchesPublicFolder({ page }, TERMINAL_BASE_CD)); + test("can read file", async ({ page }) => { + await sendToTerminal({ page }, `type ${TERMINAL_TEST_FILE}`); + await terminalFileMatchesPublicFile({ page }, TERMINAL_TEST_FILE); + }); - test("has 'Program Files'", async ({ page }) => - terminalDirectoryMatchesPublicFolder({ page }, "/Program Files")); + test.describe("can read folder", () => { + test("has base directory", async ({ page }) => + terminalDirectoryMatchesPublicFolder({ page }, TERMINAL_BASE_CD)); - test("has 'System'", async ({ page }) => - terminalDirectoryMatchesPublicFolder({ page }, "/System")); + test("has 'Program Files'", async ({ page }) => + terminalDirectoryMatchesPublicFolder({ page }, "/Program Files")); - test("has 'Users'", async ({ page }) => - terminalDirectoryMatchesPublicFolder({ page }, "/Users")); + test("has 'System'", async ({ page }) => + terminalDirectoryMatchesPublicFolder({ page }, "/System")); + + test("has 'Users'", async ({ page }) => + terminalDirectoryMatchesPublicFolder({ page }, "/Users")); + }); + + test.describe("can write", () => { + test("can create file", async ({ page }) => { + const testFileName = "test.txt"; + + await sendToTerminal({ page }, `touch ${testFileName}`); + + await sendToTerminal({ page }, "ls"); + await terminalHasText({ page }, `0 ${testFileName}`); + + await sendToTerminal({ page }, `ls ${testFileName}`); + await terminalDoesNotHaveText({ page }, "File Not Found"); + }); + }); }); test.describe("has commands", () => { test("can 'clear'", async ({ page }) => { await sendToTerminal({ page }, "echo hi"); await terminalHasText({ page }, "hi", 2); + await sendToTerminal({ page }, "clear"); await terminalDoesNotHaveText({ page }, "hi"); }); diff --git a/e2e/constants.ts b/e2e/constants.ts index 3477e806..aa43dad4 100644 --- a/e2e/constants.ts +++ b/e2e/constants.ts @@ -99,7 +99,7 @@ export const FILE_EXPLORER_ENTRIES_SELECTOR = `${FILE_EXPLORER_SELECTOR}>li`; export const FILE_EXPLORER_ENTRIES_FOCUSED_SELECTOR = `${FILE_EXPLORER_SELECTOR}>li${FOCUSED_ENTRY_SELECTOR}`; export const FILE_EXPLORER_ENTRIES_RENAMING_SELECTOR = `${FILE_EXPLORER_ENTRIES_SELECTOR}>button>figure>textarea`; export const TERMINAL_SELECTOR = `${WINDOW_SELECTOR}>${VIEWPORT_SELECTOR}>${APP_CONTAINER_SELECTOR}>.terminal`; -export const TERMINAL_ROWS_SELECTOR = `${TERMINAL_SELECTOR}>.xterm-screen>.xterm-rows>div`; +export const TERMINAL_ROWS_SELECTOR = `${TERMINAL_SELECTOR}>.xterm-screen>.xterm-rows>div:not(:empty)`; export const SHEEP_SELECTOR = `${DESKTOP_SELECTOR}>div>img[src^=data]`; export const CALENDAR_LABEL = /^Calendar$/; @@ -249,4 +249,6 @@ export const OG_TAGS = [...OG_REQUIRED_TAGS, "description"]; export const TERMINAL_BASE_CD = "/Users/Public"; +export const TERMINAL_TEST_FILE = `${TERMINAL_BASE_CD}/desktop.ini`; + export const ROOT_PUBLIC_FOLDER = "public"; diff --git a/e2e/functions.ts b/e2e/functions.ts index 42ad65c9..2f2b4a01 100644 --- a/e2e/functions.ts +++ b/e2e/functions.ts @@ -1,4 +1,4 @@ -import { readdirSync, statSync } from "fs"; +import { readFileSync, readdirSync, statSync } from "fs"; import { join } from "path"; import { type Locator, @@ -788,16 +788,6 @@ export const fileExplorerEntriesAreVisible = async ({ }: TestProps): Promise => entriesAreVisible(FILE_EXPLORER_ENTRIES_SELECTOR, page); -export const sendToTerminal = async ( - { page }: TestProps, - text: string -): Promise => { - const terminal = page.locator(TERMINAL_SELECTOR); - - await terminal.pressSequentially(text); - await terminal.press("Enter"); -}; - export const taskbarEntriesAreVisible = async ({ page, }: TestProps): Promise => entriesAreVisible(TASKBAR_ENTRY_SELECTOR, page); @@ -805,11 +795,13 @@ export const taskbarEntriesAreVisible = async ({ export const terminalHasText = async ( { page }: TestProps, text: string, - count = 1 + count = 1, + cursorLine = false ): Promise => { - const terminalWithTextRows = page - .locator(TERMINAL_ROWS_SELECTOR) - .getByText(text); + const terminalRows = page.locator(TERMINAL_ROWS_SELECTOR); + const terminalWithTextRows = cursorLine + ? terminalRows.last().getByText(text) + : terminalRows.getByText(text); await expect(terminalWithTextRows).toHaveCount(count); @@ -822,9 +814,22 @@ export const terminalHasText = async ( }; export const terminalDoesNotHaveText = async ( + { page }: TestProps, + text: string, + cursorLine = false +): Promise => terminalHasText({ page }, text, 0, cursorLine); + +export const sendToTerminal = async ( { page }: TestProps, text: string -): Promise => terminalHasText({ page }, text, 0); +): Promise => { + const terminal = page.locator(TERMINAL_SELECTOR); + + await terminal.pressSequentially(text); + await terminalHasText({ page }, `>${text}`, 1, true); + await terminal.press("Enter"); + await terminalDoesNotHaveText({ page }, `>${text}`, true); +}; export const terminalDirectoryMatchesPublicFolder = async ( { page }: TestProps, @@ -845,6 +850,18 @@ export const terminalDirectoryMatchesPublicFolder = async ( }).toPass(); }; +export const terminalFileMatchesPublicFile = async ( + { page }: TestProps, + file: string +): Promise => { + const fileLines = readFileSync(join(ROOT_PUBLIC_FOLDER, file)) + .toString() + .split("\r\n") + .filter(Boolean); + + await Promise.all(fileLines.map((line) => terminalHasText({ page }, line))); +}; + export const terminalHasRows = async ({ page }: TestProps): Promise => expect(async () => expect(await page.locator(TERMINAL_ROWS_SELECTOR).count()).toBeGreaterThan(