Add OpenRouter to setup banner (#1242)

<!-- This is an auto-generated description by cubic. -->

## Summary by cubic
Added OpenRouter as a first-class option in the setup banner and
introduced a reusable provider card component. This streamlines provider
selection and adds E2E coverage for the setup flow.

- **New Features**
- Added SetupProviderCard and used it for Google and OpenRouter in
SetupBanner.
- Clicking Google or OpenRouter routes to the correct provider settings
and logs PostHog events.
  - Kept “Other providers” link to Settings.
- Added setup.spec.ts E2E test to verify Google, OpenRouter, and Other
navigation; introduced test config flag showSetupScreen to control the
OPENAI_API_KEY shortcut.

<!-- End of auto-generated description by cubic. -->
This commit is contained in:
Will Chen
2025-09-10 13:00:31 -07:00
committed by GitHub
parent b9672004ed
commit 7150082f5a
4 changed files with 164 additions and 26 deletions

View File

@@ -1002,6 +1002,7 @@ export class PageObject {
interface ElectronConfig {
preLaunchHook?: ({ userDataDir }: { userDataDir: string }) => Promise<void>;
showSetupScreen?: boolean;
}
// From https://github.com/microsoft/playwright/issues/8208#issuecomment-1435475930
@@ -1064,8 +1065,10 @@ export const test = base.extend<{
process.env.DYAD_ENGINE_URL = "http://localhost:3500/engine/v1";
process.env.DYAD_GATEWAY_URL = "http://localhost:3500/gateway/v1";
process.env.E2E_TEST_BUILD = "true";
// This is just a hack to avoid the AI setup screen.
process.env.OPENAI_API_KEY = "sk-test";
if (!electronConfig.showSetupScreen) {
// This is just a hack to avoid the AI setup screen.
process.env.OPENAI_API_KEY = "sk-test";
}
const baseTmpDir = os.tmpdir();
const userDataDir = path.join(baseTmpDir, `dyad-e2e-tests-${Date.now()}`);
if (electronConfig.preLaunchHook) {

31
e2e-tests/setup.spec.ts Normal file
View File

@@ -0,0 +1,31 @@
import { testWithConfig } from "./helpers/test_helper";
import { expect } from "@playwright/test";
const testSetup = testWithConfig({
showSetupScreen: true,
});
testSetup("setup ai provider", async ({ po }) => {
await po.page
.getByRole("button", { name: "Setup Google Gemini API Key" })
.click();
await expect(
po.page.getByRole("heading", { name: "Configure Google" }),
).toBeVisible();
expect(po.page.url()).toEqual("file:///providers/google");
await po.page.getByRole("button", { name: "Go Back" }).click();
await po.page
.getByRole("button", { name: "Setup OpenRouter API Key Free" })
.click();
await expect(
po.page.getByRole("heading", { name: "Configure OpenRouter" }),
).toBeVisible();
expect(po.page.url()).toEqual("file:///providers/openrouter");
await po.page.getByRole("button", { name: "Go Back" }).click();
await po.page
.getByRole("button", { name: "Setup other AI providers" })
.click();
expect(po.page.url()).toEqual("file:///settings");
});