diff --git a/.storybook/main.ts b/.storybook/main.ts index ea601bca..cabea784 100644 --- a/.storybook/main.ts +++ b/.storybook/main.ts @@ -1,4 +1,7 @@ -import path from "path" +import path from "path"; +import { fileURLToPath } from "url"; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); const config = { stories: [ diff --git a/components/biz/LLMSelector/LLMSelector.stories.tsx b/components/biz/LLMSelector/LLMSelector.stories.tsx index 4465b194..2f57627e 100644 --- a/components/biz/LLMSelector/LLMSelector.stories.tsx +++ b/components/biz/LLMSelector/LLMSelector.stories.tsx @@ -3,6 +3,7 @@ import { useState } from "react" import { AIProvider } from "@/lib/config/ai-providers" import { LLMSelector } from "." import { LLMOption } from "./interface" +import { within, userEvent, expect } from "@storybook/test" const meta: Meta = { title: "biz/LLMSelector", @@ -56,6 +57,41 @@ export const Basic: Story = { initialData: mockLLMOptions, placeholder: "Select an LLM model", }, + play: async ({ canvasElement, step }) => { + const canvas = within(canvasElement) + + // 步骤 1: 查找并点击下拉框 + await step("Open dropdown", async () => { + const selectButton = canvas.getByRole("combobox") + await userEvent.click(selectButton) + }) + + // 步骤 2: 等待下拉菜单渲染并选择选项 + await step("Select option", async () => { + // 使用 getByRole 查找选项列表 + await new Promise(resolve => setTimeout(resolve, 500)) // 增加等待时间 + + // 查找下拉列表中的所有选项 + const options = document.querySelectorAll('[role="option"]') + const gpt4Option = Array.from(options).find(option => + option.textContent?.includes("GPT-4o"), + ) + + if (!gpt4Option) { + throw new Error("GPT-4o option not found") + } + + await userEvent.click(gpt4Option) + }) + + // 步骤 3: 验证选择结果 + await step("Verify selection", async () => { + const selectButton = canvas.getByRole("combobox") + // 使用正则表达式进行更灵活的文本匹配 + const hasGPT4Text = selectButton.textContent?.match(/GPT-4o/i) + expect(hasGPT4Text).toBeTruthy() + }) + }, } // With initial selection @@ -65,6 +101,11 @@ export const WithSelection: Story = { selectedProvider: "openai", selectedModel: "gpt-4o", }, + play: async ({ canvasElement }) => { + const canvas = within(canvasElement) + const selectButton = canvas.getByRole("combobox") + expect(selectButton.textContent?.includes("GPT-4o")).toBeTruthy() + }, } // Disabled state @@ -73,6 +114,11 @@ export const Disabled: Story = { initialData: mockLLMOptions, disabled: true, }, + play: async ({ canvasElement }) => { + const canvas = within(canvasElement) + const selectButton = canvas.getByRole("combobox") + expect(selectButton.hasAttribute("disabled")).toBeTruthy() + }, } // Interactive example with state @@ -95,12 +141,38 @@ export const Interactive: Story = {

Selected Provider: {provider || "None"} -

+

Selected Model: {model || "None"} -

+

) }, -} + play: async ({ canvasElement }) => { + const canvas = within(canvasElement) + + // 1. 先验证下拉框是否存在 + const selectButton = canvas.getByRole("combobox") + expect(selectButton).toBeTruthy() + + // 2. 点击打开下拉框 + await userEvent.click(selectButton) + + // 3. 等待并选择选项 + await new Promise(resolve => setTimeout(resolve, 500)) + + const options = document.querySelectorAll('[role="option"]') + const gpt4Option = Array.from(options).find(option => + option.textContent?.includes("GPT-4o"), + ) + + if (gpt4Option) { + await userEvent.click(gpt4Option) + } + + // 5. 验证选择后的显示文本 + await new Promise(resolve => setTimeout(resolve, 100)) + expect(selectButton.textContent).toContain("GPT-4o") + }, +} \ No newline at end of file diff --git a/package.json b/package.json index 385298e7..db7f8df3 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,9 @@ "version": "0.1.0", "private": true, "description": "AI-Powered Component Code Generator For Every Frontend Engineer", + "engines": { + "node": ">=22.7.0" + }, "scripts": { "dev": "next dev", "build": "next build", @@ -111,4 +114,4 @@ "typescript": "^5", "playwright": "^1.51.1" } -} +} \ No newline at end of file