diff --git a/.opencode/package-lock.json b/.opencode/package-lock.json index 41ff2315..06ffa37a 100644 --- a/.opencode/package-lock.json +++ b/.opencode/package-lock.json @@ -5,7 +5,7 @@ "packages": { "": { "dependencies": { - "@opencode-ai/plugin": "1.14.31" + "@opencode-ai/plugin": "1.15.10" } }, "node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64": { @@ -87,32 +87,36 @@ ] }, "node_modules/@opencode-ai/plugin": { - "version": "1.14.31", - "resolved": "https://registry.npmjs.org/@opencode-ai/plugin/-/plugin-1.14.31.tgz", - "integrity": "sha512-ZF7UoNKtZDtgW/2KrcFw5I7R2HRj/NigBuRwKPonvSZS36LnghZ7PYcXYZFGCjEgBmLUMMrLVgxccKLyxsgB0g==", + "version": "1.15.10", + "resolved": "https://registry.npmjs.org/@opencode-ai/plugin/-/plugin-1.15.10.tgz", + "integrity": "sha512-V2p7CvpBtKWB+FID7Dl1y0Ci02zUT40A9b2RD9R9BOiuD8ZcKhHWov+irN0xVJA0Eg6OhEBfA0lPKRn1FNKPlw==", "license": "MIT", "dependencies": { - "@opencode-ai/sdk": "1.14.31", - "effect": "4.0.0-beta.57", + "@opencode-ai/sdk": "1.15.10", + "effect": "4.0.0-beta.66", "zod": "4.1.8" }, "peerDependencies": { - "@opentui/core": ">=0.2.0", - "@opentui/solid": ">=0.2.0" + "@opentui/core": ">=0.2.15", + "@opentui/keymap": ">=0.2.15", + "@opentui/solid": ">=0.2.15" }, "peerDependenciesMeta": { "@opentui/core": { "optional": true }, + "@opentui/keymap": { + "optional": true + }, "@opentui/solid": { "optional": true } } }, "node_modules/@opencode-ai/sdk": { - "version": "1.14.31", - "resolved": "https://registry.npmjs.org/@opencode-ai/sdk/-/sdk-1.14.31.tgz", - "integrity": "sha512-QaV+ti3NYUITmgIDqtNMqGIYBXJOx2zheN1g+7w4HC8QQsbaW1c7glxXExQHRbdUzcQPP2vUQhnXOcEsTw5CcQ==", + "version": "1.15.10", + "resolved": "https://registry.npmjs.org/@opencode-ai/sdk/-/sdk-1.15.10.tgz", + "integrity": "sha512-CUhpmMGGOqzvPnNNjjWmEIodAfP6Qnuki2ChIUKWYF7UImZ4zUcMZnzO5BtUxu/Ni1P8qzWxDioXs+7aIZQEhA==", "license": "MIT", "dependencies": { "cross-spawn": "7.0.6" @@ -149,9 +153,9 @@ } }, "node_modules/effect": { - "version": "4.0.0-beta.57", - "resolved": "https://registry.npmjs.org/effect/-/effect-4.0.0-beta.57.tgz", - "integrity": "sha512-rg32VgXnLKaPRs9tbRDaZ5jxmzNY7ojXt85gSHGUTwdlbWH5Ik+OCUY2q14TXliygPGoHwCAvNWS4bQJOqf00g==", + "version": "4.0.0-beta.66", + "resolved": "https://registry.npmjs.org/effect/-/effect-4.0.0-beta.66.tgz", + "integrity": "sha512-4arEr62cziFa8BBVDUwJCJJmaVepXf/kRg7KtC0h8+bufngscrHbwWFhr9c+HonwOF+31U3iD3xUJmw9KzX7Dw==", "license": "MIT", "dependencies": { "@standard-schema/spec": "^1.1.0", @@ -167,9 +171,9 @@ } }, "node_modules/fast-check": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/fast-check/-/fast-check-4.7.0.tgz", - "integrity": "sha512-NsZRtqvSSoCP0HbNjUD+r1JH8zqZalyp6gLY9e7OYs7NK9b6AHOs2baBFeBG7bVNsuoukh89x2Yg3rPsul8ziQ==", + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/fast-check/-/fast-check-4.8.0.tgz", + "integrity": "sha512-GOJ158CUMnN6cSahsv4+ExARvIDuzzinFjkp0E9WtiBa5zcVeLozVkWaE4IzFcc+Y48Wp1EDlUZsXRyAztQcSg==", "funding": [ { "type": "individual", @@ -216,9 +220,9 @@ "license": "Apache-2.0" }, "node_modules/msgpackr": { - "version": "1.11.10", - "resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-1.11.10.tgz", - "integrity": "sha512-iCZNq+HszvF+fC3anCm4nBmWEnbeIAfpDs6IStAEKhQ2YSgkjzVG2FF9XJqwwQh5bH3N9OUTUt4QwVN6MLMLtA==", + "version": "1.11.12", + "resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-1.11.12.tgz", + "integrity": "sha512-RBdJ1Un7yGlXWajrkxcSa93nvQ0w4zBf60c0yYv7YtBelP8H2FA7XsfBbMHtXKXUMUxH7zV3Zuozh+kUQWhHvg==", "license": "MIT", "optionalDependencies": { "msgpackr-extract": "^3.0.2" @@ -323,9 +327,9 @@ } }, "node_modules/uuid": { - "version": "13.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-13.0.1.tgz", - "integrity": "sha512-9ezox2roIft6ExBVTVqibSd5dc5/47Sw/uY6b4SjQUT2TzQ0tltNquWA46y4xPQmdZYqvnio22SgWd41M86+jw==", + "version": "13.0.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-13.0.2.tgz", + "integrity": "sha512-vzi9uRZ926x4XV73S/4qQaTwPXM2JBj6/6lI/byHH1jOpCzb0zDbfytgA9LcN/hzb2l7WQSQnxITOVx5un/wGw==", "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" @@ -351,9 +355,9 @@ } }, "node_modules/yaml": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.3.tgz", - "integrity": "sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==", + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz", + "integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==", "license": "ISC", "bin": { "yaml": "bin.mjs" diff --git a/e2e/transaction-edit.spec.ts b/e2e/transaction-edit.spec.ts index 4e982642..af6bf918 100644 --- a/e2e/transaction-edit.spec.ts +++ b/e2e/transaction-edit.spec.ts @@ -1,14 +1,14 @@ import { test, expect } from '@playwright/test'; -async function openEditModal(page: any) { +async function openEditModal(page: any, transactionIndex: number = 0) { // Navigate to transactions page await page.goto('/transaction2'); // Wait for the table to load await page.waitForSelector('table tbody tr'); - // Find and click the edit button for the test transaction - const editButton = page.locator('button[hx-get*="/transaction2/"][hx-get*="/edit"]').first(); + // Find and click the edit button for the specified transaction + const editButton = page.locator('button[hx-get*="/transaction2/"][hx-get*="/edit"]').nth(transactionIndex); await editButton.click(); // Wait for the modal to open @@ -137,6 +137,49 @@ async function addNewAccount(page: any) { await page.waitForTimeout(500); } +async function setAccountLocation(page: any, rowIndex: number, location: string) { + const row = await findAccountRow(page, rowIndex); + const locationSelect = row.locator('select[name*="location"]').first(); + + // If the option doesn't exist, add it (for testing invalid locations) + const optionExists = await locationSelect.locator(`option[value="${location}"]`).count() > 0; + if (!optionExists) { + await locationSelect.evaluate((el: HTMLSelectElement, value: string) => { + const option = document.createElement('option'); + option.value = value; + option.textContent = value; + el.appendChild(option); + }, location); + } + + await locationSelect.selectOption(location); + await locationSelect.dispatchEvent('change'); + await page.waitForTimeout(300); +} + +async function getAccountLocation(page: any, rowIndex: number): Promise { + const row = await findAccountRow(page, rowIndex); + const locationSelect = row.locator('select[name*="location"]').first(); + return await locationSelect.inputValue(); +} + +async function removeAllAccounts(page: any) { + const allRows = page.locator('#account-grid-body tbody tr'); + const rowCount = await allRows.count(); + + for (let i = rowCount - 1; i >= 0; i--) { + const row = allRows.nth(i); + const hasAccountInput = await row.locator('input[name*="transaction-account/account"]').count() > 0; + if (hasAccountInput) { + // Click the X button to remove (it's an tag, not a