Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions apps/desktop/e2e-budget.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@
"tests": 5,
"electron": "Git changes re-read on native window focus; native PTY ownership survives Session navigation and renderer replacement, while Stop/exit cross preload/main into the terminal view; Side Chat owns a Host fork lifecycle; first send reaches the Host; the composer usage entry opens a workbar whose per-Session visibility survives renderer reload."
},
"settings-pricing.spec.ts": {
"tests": 1,
"electron": "the installed contextBridge, main IPC handlers and selected-Host adapter carry Pricing writes and return authoritative values through a fresh preload after renderer reload; injected services and handler fakes cannot detect missing registrations, incorrect Host scope or serialization loss. Picker, tabs and focus are covered by the existing Pricing and Settings Storybook plays"
},
"settings.spec.ts": {
"tests": 2,
"electron": "Code Mode reads back Host settings through IPC; opening Settings commits a pending title rename to the Host, with workbar hide/restore asserted in that same Session."
Expand Down
68 changes: 68 additions & 0 deletions apps/desktop/e2e/settings-pricing.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import { ensureSidebarExpanded, expect, test } from './fixtures';

// Verifies the installed Pricing contextBridge, IPC handlers and selected-Host
// adapter together. A missing handler, wrong Host scope or lost mutation/result
// serialization is invisible to injected Storybook services and handler fakes.
// The saved override must be readable through a new preload after renderer reload.
// Picker, tab scope and focus contracts live in the existing Pricing stories.
test('pricing writes cross preload and main and remain readable after renderer reload', async ({
window: page,
}) => {
await ensureSidebarExpanded(page);
await page.getByRole('button', { name: '设置' }).click();
await page.getByRole('button', { name: '使用统计', exact: true }).click();
await page
.getByRole('navigation', { name: '使用统计视图' })
.getByRole('button', { name: '定价配置', exact: true })
.click();

const modelKey = `e2e:pricing-ipc-${Date.now()}`;
const pricing = { modelKey, inputUsdPer1M: 1, outputUsdPer1M: 2 };
const host = await page.evaluate(() => window.maka.runtimeHostProfiles.getDefaultHost());
await page.getByRole('button', { name: '添加定价' }).click();
const editor = page.getByRole('dialog', { name: '添加定价' });
await editor.getByRole('button', { name: '模型不在列表中?手动输入' }).click();
await editor.getByRole('textbox', { name: /模型键/ }).fill(modelKey);
await editor.getByRole('textbox', { name: /输入价格/ }).fill('1');
await editor.getByRole('textbox', { name: /输出价格/ }).fill('2');
await editor.getByRole('button', { name: '保存' }).click();
await expect.poll(() => page.evaluate(async ({ host, modelKey }) => {
const snapshot = await window.maka.settings.pricing.load(host);
return snapshot.entries.find((row) => row.pricing.modelKey === modelKey)?.pricing;
}, { host, modelKey })).toEqual(pricing);

await page.reload();
await expect.poll(() => page.evaluate(async ({ host, modelKey }) => {
const snapshot = await window.maka.settings.pricing.load(host);
return snapshot.entries.find((row) => row.pricing.modelKey === modelKey)?.pricing;
}, { host, modelKey })).toEqual(pricing);

const removed = await page.evaluate(async ({ host, modelKey }) => {
const base = await window.maka.settings.pricing.load(host);
return window.maka.settings.pricing.mutate(base, { kind: 'delete', modelKey }, host);
}, { host, modelKey });
expect(removed.kind).toBe('saved');
await expect.poll(() => page.evaluate(async ({ host, modelKey }) => {
const snapshot = await window.maka.settings.pricing.load(host);
return snapshot.entries.some((row) => row.pricing.modelKey === modelKey);
}, { host, modelKey })).toBe(false);
});
10 changes: 10 additions & 0 deletions apps/desktop/renderer-architecture.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
"src/renderer/locales/settings-memory-copy.ts",
"src/renderer/locales/settings-navigation-copy.ts",
"src/renderer/locales/settings-preferences-copy.ts",
"src/renderer/locales/settings-pricing-copy.ts",
"src/renderer/locales/settings-projects-copy.ts",
"src/renderer/locales/settings-shared-copy.ts",
"src/renderer/locales/settings-subagents-copy.ts",
Expand Down Expand Up @@ -1407,6 +1408,15 @@
"actionFactories": [],
"dependencyPaths": {}
},
"src/renderer/locales/settings-pricing-copy.ts": {
"bridgePaths": {},
"environmentCapabilities": {},
"hookCalls": {},
"lifecycleMethods": {},
"unresolvedDependencies": 0,
"actionFactories": [],
"dependencyPaths": {}
},
"src/renderer/locales/settings-projects-copy.ts": {
"bridgePaths": {},
"environmentCapabilities": {},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,6 @@ test('projects only present Usage Session ids into the Desktop host namespace',
byProvider: [],
byModel: [],
byTool: [],
pricing: [],
provenance: EMPTY_USAGE_PROVENANCE,
};

Expand Down
Loading