Files
electerm--electerm/test/e2e/021.cmd-history.spec.js
2026-07-13 12:46:20 +08:00

185 lines
7.4 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* Terminal command-history test
*
* Verifies:
* 1. Running a command in a local terminal adds it to cmd history.
* 2. Clicking the history item re-runs the command.
* 3. Deleting a history item removes it from the list.
* 4. History persists across app restarts.
*/
const { _electron: electron } = require('@playwright/test')
const { test: it } = require('@playwright/test')
const { describe } = it
it.setTimeout(10000000)
const delay = require('./common/wait')
const log = require('./common/log')
const appOptions = require('./common/app-options')
const extendClient = require('./common/client-extend')
const { expect } = require('./common/expect')
const { closeApp } = require('./common/common')
// ─── helpers ──────────────────────────────────────────────────────────────────
/** Open the command-history popover in the footer.
* Closes any currently-open popover first so we get a clean open. */
async function openHistoryPopover (client) {
// Click outside any popover to ensure it is closed before reopening
await client.click('.session-current .term-wrap')
await delay(400)
await client.click('.terminal-footer-history .ant-btn')
await delay(800)
}
/** Close the popover by clicking outside of it. */
async function closeHistoryPopover (client) {
await client.click('.session-current .term-wrap')
await delay(400)
}
/**
* Return the text of all visible command-history items.
* The popover must already be open.
*/
async function getHistoryItems (client) {
const items = await client.locator('.cmd-history-item .cmd-history-item-text')
const count = await items.count()
const texts = []
for (let i = 0; i < count; i++) {
texts.push(await items.nth(i).innerText())
}
return texts
}
/**
* Hover over a history item whose text includes `term` to reveal action buttons,
* then click the delete button. The popover must already be open.
*/
async function deleteHistoryItem (client, term) {
const items = client.locator('.cmd-history-item')
const count = await items.count()
for (let i = 0; i < count; i++) {
const txt = await items.nth(i).locator('.cmd-history-item-text').innerText()
if (txt.includes(term)) {
await items.nth(i).hover()
await delay(400)
await items.nth(i).locator('.cmd-history-item-delete').click()
await delay(600)
return
}
}
throw new Error(`History item matching "${term}" not found in popover`)
}
/** Return the cmd strings currently in window.store.terminalCommandHistory. */
async function getStoredHistory (client) {
return client.evaluate(() =>
window.store.terminalCommandHistory.map(i => i.cmd)
)
}
/** Type a command in the terminal and press Enter. */
async function runInTerminal (client, cmd) {
await client.click('.session-current .term-wrap')
await delay(1000)
await client.keyboard.type(cmd)
await delay(300)
await client.keyboard.press('Enter')
await delay(1500)
}
// ─── test ─────────────────────────────────────────────────────────────────────
describe('cmd-history', function () {
it('should add, re-run, delete commands and persist across restarts', async function () {
// ── first session ──────────────────────────────────────────────────────────
let electronApp = await electron.launch(appOptions)
let client = await electronApp.firstWindow()
extendClient(client, electronApp)
await delay(13000)
log('021: app launched (session 1)')
const ts = Date.now()
// Use simple commands without quotes to avoid shell-escaping issues
const cmd1 = `echo cmd-history-test-${ts}`
const cmd2 = `echo cmd-history-persist-${ts}`
// Clear existing history so our unique commands are easy to find
await client.evaluate(() => window.store.clearAllCmdHistory())
await delay(300)
// ── step 1: run cmd1 in terminal → should appear in history ───────────────
await runInTerminal(client, cmd1)
log(`021: ran "${cmd1}" in terminal`)
// Verify via store (ground truth)
const stored1 = await getStoredHistory(client)
log(`021: stored history: ${JSON.stringify(stored1)}`)
expect(stored1.includes(cmd1)).equal(true)
// Verify via UI popover
await openHistoryPopover(client)
const items1 = await getHistoryItems(client)
log(`021: history popover items: ${JSON.stringify(items1)}`)
expect(items1.some(t => t.trim() === cmd1 || t.includes(`cmd-history-test-${ts}`))).equal(true)
// ── step 2: click the item to re-run the command ──────────────────────────
const allItems = client.locator('.cmd-history-item')
const count = await allItems.count()
let clicked = false
for (let i = 0; i < count; i++) {
const txt = await allItems.nth(i).locator('.cmd-history-item-text').innerText()
if (txt.includes(`cmd-history-test-${ts}`)) {
await allItems.nth(i).locator('.cmd-history-item-text').click()
clicked = true
break
}
}
expect(clicked).equal(true)
await delay(2000)
log('021: clicked history item to re-run')
// count in store should have updated (command was re-run)
const stored2 = await getStoredHistory(client)
expect(stored2.includes(cmd1)).equal(true)
// ── step 3: delete the item ────────────────────────────────────────────────
// Reopen popover (clicking the item might or might not have closed it; use
// the helper which first clicks outside to normalise state)
await openHistoryPopover(client)
await deleteHistoryItem(client, `cmd-history-test-${ts}`)
const storedAfterDel = await getStoredHistory(client)
log(`021: history after delete: ${JSON.stringify(storedAfterDel)}`)
expect(storedAfterDel.includes(cmd1)).equal(false)
await closeHistoryPopover(client)
// ── step 4: run cmd2 that should persist after restart ────────────────────
await runInTerminal(client, cmd2)
await delay(2000) // allow store + db flush
log(`021: ran "${cmd2}" in terminal`)
await closeApp(electronApp, __filename)
log('021: session 1 closed')
// ── second session (restart) ───────────────────────────────────────────────
await delay(2000)
electronApp = await electron.launch(appOptions)
client = await electronApp.firstWindow()
extendClient(client, electronApp)
await delay(13000)
log('021: app launched (session 2 restart)')
// cmd2 must still be in history
const storedRestart = await getStoredHistory(client)
log(`021: history after restart: ${JSON.stringify(storedRestart)}`)
expect(storedRestart.includes(cmd2)).equal(true)
// cmd1 must NOT be in history (was deleted before restart)
expect(storedRestart.includes(cmd1)).equal(false)
await closeApp(electronApp, __filename)
log('021: all cmd-history tests passed')
})
})