diff --git a/web/app/components/header/github-star/index.spec.tsx b/web/app/components/header/github-star/index.spec.tsx
new file mode 100644
index 0000000000..b218604788
--- /dev/null
+++ b/web/app/components/header/github-star/index.spec.tsx
@@ -0,0 +1,57 @@
+import React from 'react'
+import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
+import { render, screen, waitFor } from '@testing-library/react'
+import nock from 'nock'
+import GithubStar from './index'
+
+const GITHUB_HOST = 'https://api.github.com'
+const GITHUB_PATH = '/repos/langgenius/dify'
+
+const renderWithQueryClient = () => {
+ const queryClient = new QueryClient({
+ defaultOptions: { queries: { retry: false } },
+ })
+ return render(
+
+
+ ,
+ )
+}
+
+const mockGithubStar = (status: number, body: Record, delayMs = 0) => {
+ return nock(GITHUB_HOST).get(GITHUB_PATH).delay(delayMs).reply(status, body)
+}
+
+describe('GithubStar', () => {
+ beforeEach(() => {
+ nock.cleanAll()
+ })
+
+ // Shows fetched star count when request succeeds
+ it('should render fetched star count', async () => {
+ mockGithubStar(200, { stargazers_count: 123456 })
+
+ renderWithQueryClient()
+
+ expect(await screen.findByText('123,456')).toBeInTheDocument()
+ })
+
+ // Falls back to default star count when request fails
+ it('should render default star count on error', async () => {
+ mockGithubStar(500, {})
+
+ renderWithQueryClient()
+
+ expect(await screen.findByText('110,918')).toBeInTheDocument()
+ })
+
+ // Renders loader while fetching data
+ it('should show loader while fetching', async () => {
+ mockGithubStar(200, { stargazers_count: 222222 }, 50)
+
+ const { container } = renderWithQueryClient()
+
+ expect(container.querySelector('.animate-spin')).toBeInTheDocument()
+ await waitFor(() => expect(screen.getByText('222,222')).toBeInTheDocument())
+ })
+})
diff --git a/web/package.json b/web/package.json
index a3af02f230..4c2bf2dfb5 100644
--- a/web/package.json
+++ b/web/package.json
@@ -200,6 +200,7 @@
"lint-staged": "^15.5.2",
"lodash": "^4.17.21",
"magicast": "^0.3.5",
+ "nock": "^14.0.10",
"postcss": "^8.5.6",
"react-scan": "^0.4.3",
"sass": "^1.93.2",
diff --git a/web/pnpm-lock.yaml b/web/pnpm-lock.yaml
index ce5816b565..82bca67203 100644
--- a/web/pnpm-lock.yaml
+++ b/web/pnpm-lock.yaml
@@ -366,7 +366,7 @@ importers:
version: 7.28.5
'@chromatic-com/storybook':
specifier: ^4.1.1
- version: 4.1.3(storybook@9.1.13(@testing-library/dom@10.4.1))
+ version: 4.1.3(storybook@9.1.13(@testing-library/dom@10.4.1)(msw@2.12.4(@types/node@18.15.0)(typescript@5.9.3)))
'@eslint-react/eslint-plugin':
specifier: ^1.53.1
version: 1.53.1(eslint@9.39.1(jiti@1.21.7))(ts-api-utils@2.1.0(typescript@5.9.3))(typescript@5.9.3)
@@ -393,22 +393,22 @@ importers:
version: 4.2.0
'@storybook/addon-docs':
specifier: 9.1.13
- version: 9.1.13(@types/react@19.2.7)(storybook@9.1.13(@testing-library/dom@10.4.1))
+ version: 9.1.13(@types/react@19.2.7)(storybook@9.1.13(@testing-library/dom@10.4.1)(msw@2.12.4(@types/node@18.15.0)(typescript@5.9.3)))
'@storybook/addon-links':
specifier: 9.1.13
- version: 9.1.13(react@19.2.1)(storybook@9.1.13(@testing-library/dom@10.4.1))
+ version: 9.1.13(react@19.2.1)(storybook@9.1.13(@testing-library/dom@10.4.1)(msw@2.12.4(@types/node@18.15.0)(typescript@5.9.3)))
'@storybook/addon-onboarding':
specifier: 9.1.13
- version: 9.1.13(storybook@9.1.13(@testing-library/dom@10.4.1))
+ version: 9.1.13(storybook@9.1.13(@testing-library/dom@10.4.1)(msw@2.12.4(@types/node@18.15.0)(typescript@5.9.3)))
'@storybook/addon-themes':
specifier: 9.1.13
- version: 9.1.13(storybook@9.1.13(@testing-library/dom@10.4.1))
+ version: 9.1.13(storybook@9.1.13(@testing-library/dom@10.4.1)(msw@2.12.4(@types/node@18.15.0)(typescript@5.9.3)))
'@storybook/nextjs':
specifier: 9.1.13
- version: 9.1.13(esbuild@0.25.0)(next@15.5.7(@babel/core@7.28.5)(react-dom@19.2.1(react@19.2.1))(react@19.2.1)(sass@1.94.2))(react-dom@19.2.1(react@19.2.1))(react@19.2.1)(sass@1.94.2)(storybook@9.1.13(@testing-library/dom@10.4.1))(type-fest@4.2.0)(typescript@5.9.3)(uglify-js@3.19.3)(webpack-hot-middleware@2.26.1)(webpack@5.103.0(esbuild@0.25.0)(uglify-js@3.19.3))
+ version: 9.1.13(esbuild@0.25.0)(next@15.5.7(@babel/core@7.28.5)(react-dom@19.2.1(react@19.2.1))(react@19.2.1)(sass@1.94.2))(react-dom@19.2.1(react@19.2.1))(react@19.2.1)(sass@1.94.2)(storybook@9.1.13(@testing-library/dom@10.4.1)(msw@2.12.4(@types/node@18.15.0)(typescript@5.9.3)))(type-fest@4.2.0)(typescript@5.9.3)(uglify-js@3.19.3)(webpack-hot-middleware@2.26.1)(webpack@5.103.0(esbuild@0.25.0)(uglify-js@3.19.3))
'@storybook/react':
specifier: 9.1.13
- version: 9.1.13(react-dom@19.2.1(react@19.2.1))(react@19.2.1)(storybook@9.1.13(@testing-library/dom@10.4.1))(typescript@5.9.3)
+ version: 9.1.13(react-dom@19.2.1(react@19.2.1))(react@19.2.1)(storybook@9.1.13(@testing-library/dom@10.4.1)(msw@2.12.4(@types/node@18.15.0)(typescript@5.9.3)))(typescript@5.9.3)
'@testing-library/dom':
specifier: ^10.4.1
version: 10.4.1
@@ -495,7 +495,7 @@ importers:
version: 3.0.5(eslint@9.39.1(jiti@1.21.7))
eslint-plugin-storybook:
specifier: ^9.1.13
- version: 9.1.16(eslint@9.39.1(jiti@1.21.7))(storybook@9.1.13(@testing-library/dom@10.4.1))(typescript@5.9.3)
+ version: 9.1.16(eslint@9.39.1(jiti@1.21.7))(storybook@9.1.13(@testing-library/dom@10.4.1)(msw@2.12.4(@types/node@18.15.0)(typescript@5.9.3)))(typescript@5.9.3)
eslint-plugin-tailwindcss:
specifier: ^3.18.2
version: 3.18.2(tailwindcss@3.4.18(tsx@4.21.0)(yaml@2.8.2))
@@ -520,6 +520,9 @@ importers:
magicast:
specifier: ^0.3.5
version: 0.3.5
+ nock:
+ specifier: ^14.0.10
+ version: 14.0.10
postcss:
specifier: ^8.5.6
version: 8.5.6
@@ -531,7 +534,7 @@ importers:
version: 1.94.2
storybook:
specifier: 9.1.13
- version: 9.1.13(@testing-library/dom@10.4.1)
+ version: 9.1.13(@testing-library/dom@10.4.1)(msw@2.12.4(@types/node@18.15.0)(typescript@5.9.3))
tailwindcss:
specifier: ^3.4.18
version: 3.4.18(tsx@4.21.0)(yaml@2.8.2)
@@ -1987,6 +1990,41 @@ packages:
cpu: [x64]
os: [win32]
+ '@inquirer/ansi@1.0.2':
+ resolution: {integrity: sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ==}
+ engines: {node: '>=18'}
+
+ '@inquirer/confirm@5.1.21':
+ resolution: {integrity: sha512-KR8edRkIsUayMXV+o3Gv+q4jlhENF9nMYUZs9PA2HzrXeHI8M5uDag70U7RJn9yyiMZSbtF5/UexBtAVtZGSbQ==}
+ engines: {node: '>=18'}
+ peerDependencies:
+ '@types/node': '>=18'
+ peerDependenciesMeta:
+ '@types/node':
+ optional: true
+
+ '@inquirer/core@10.3.2':
+ resolution: {integrity: sha512-43RTuEbfP8MbKzedNqBrlhhNKVwoK//vUFNW3Q3vZ88BLcrs4kYpGg+B2mm5p2K/HfygoCxuKwJJiv8PbGmE0A==}
+ engines: {node: '>=18'}
+ peerDependencies:
+ '@types/node': '>=18'
+ peerDependenciesMeta:
+ '@types/node':
+ optional: true
+
+ '@inquirer/figures@1.0.15':
+ resolution: {integrity: sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g==}
+ engines: {node: '>=18'}
+
+ '@inquirer/type@3.0.10':
+ resolution: {integrity: sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA==}
+ engines: {node: '>=18'}
+ peerDependencies:
+ '@types/node': '>=18'
+ peerDependenciesMeta:
+ '@types/node':
+ optional: true
+
'@isaacs/balanced-match@4.0.1':
resolution: {integrity: sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==}
engines: {node: 20 || >=22}
@@ -2240,6 +2278,14 @@ packages:
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
+ '@mswjs/interceptors@0.39.8':
+ resolution: {integrity: sha512-2+BzZbjRO7Ct61k8fMNHEtoKjeWI9pIlHFTqBwZ5icHpqszIgEZbjb1MW5Z0+bITTCTl3gk4PDBxs9tA/csXvA==}
+ engines: {node: '>=18'}
+
+ '@mswjs/interceptors@0.40.0':
+ resolution: {integrity: sha512-EFd6cVbHsgLa6wa4RljGj6Wk75qoHxUSyc5asLyyPSyuhIcdS2Q3Phw6ImS1q+CkALthJRShiYfKANcQMuMqsQ==}
+ engines: {node: '>=18'}
+
'@napi-rs/wasm-runtime@1.1.0':
resolution: {integrity: sha512-Fq6DJW+Bb5jaWE69/qOE0D1TUN9+6uWhCeZpdnSBk14pjLcCWR7Q8n49PTSPHazM37JqrsdpEthXy2xn6jWWiA==}
@@ -2418,6 +2464,15 @@ packages:
'@octokit/types@14.1.0':
resolution: {integrity: sha512-1y6DgTy8Jomcpu33N+p5w58l6xyt55Ar2I91RPiIA0xCJBXyUAhXCcmZaDWSANiha7R9a6qJJ2CRomGPZ6f46g==}
+ '@open-draft/deferred-promise@2.2.0':
+ resolution: {integrity: sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==}
+
+ '@open-draft/logger@0.3.0':
+ resolution: {integrity: sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==}
+
+ '@open-draft/until@2.1.0':
+ resolution: {integrity: sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==}
+
'@oxc-resolver/binding-android-arm-eabi@11.14.2':
resolution: {integrity: sha512-bTrdE4Z1JcGwPxBOaGbxRbpOHL8/xPVJTTq3/bAZO2euWX0X7uZ+XxsbC+5jUDMhLenqdFokgE1akHEU4xsh6A==}
cpu: [arm]
@@ -3512,6 +3567,9 @@ packages:
'@types/stack-utils@2.0.3':
resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==}
+ '@types/statuses@2.0.6':
+ resolution: {integrity: sha512-xMAgYwceFhRA2zY+XbEA7mxYbA093wdiW8Vu6gZPGWy9cmOyU9XesH1tNcEWsKFd5Vzrqx5T3D38PWx1FIIXkA==}
+
'@types/trusted-types@2.0.7':
resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==}
@@ -4241,6 +4299,10 @@ packages:
resolution: {integrity: sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==}
engines: {node: '>=18'}
+ cli-width@4.1.0:
+ resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==}
+ engines: {node: '>= 12'}
+
client-only@0.0.1:
resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==}
@@ -4355,6 +4417,10 @@ packages:
convert-source-map@2.0.0:
resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
+ cookie@1.1.1:
+ resolution: {integrity: sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==}
+ engines: {node: '>=18'}
+
copy-to-clipboard@3.3.3:
resolution: {integrity: sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==}
@@ -5512,6 +5578,10 @@ packages:
graphemer@1.4.0:
resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==}
+ graphql@16.12.0:
+ resolution: {integrity: sha512-DKKrynuQRne0PNpEbzuEdHlYOMksHSUI8Zc9Unei5gTsMNA2/vMpoMz/yKba50pejK56qj98qM0SjYxAKi13gQ==}
+ engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0}
+
gzip-size@6.0.0:
resolution: {integrity: sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==}
engines: {node: '>=10'}
@@ -5590,6 +5660,9 @@ packages:
resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==}
hasBin: true
+ headers-polyfill@4.0.3:
+ resolution: {integrity: sha512-IScLbePpkvO846sIwOtOTDjutRMWdXdJmXdMvk6gCBHxFO8d+QKOQedyZSxFTTFYRSmlgSTDtXqqq4pcenBXLQ==}
+
highlight.js@10.7.3:
resolution: {integrity: sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==}
@@ -5831,6 +5904,9 @@ packages:
is-module@1.0.0:
resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==}
+ is-node-process@1.2.0:
+ resolution: {integrity: sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw==}
+
is-number@7.0.0:
resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
engines: {node: '>=0.12.0'}
@@ -6116,6 +6192,9 @@ packages:
json-stable-stringify-without-jsonify@1.0.1:
resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==}
+ json-stringify-safe@5.0.1:
+ resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==}
+
json5@2.2.3:
resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==}
engines: {node: '>=6'}
@@ -6621,6 +6700,20 @@ packages:
ms@2.1.3:
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
+ msw@2.12.4:
+ resolution: {integrity: sha512-rHNiVfTyKhzc0EjoXUBVGteNKBevdjOlVC6GlIRXpy+/3LHEIGRovnB5WPjcvmNODVQ1TNFnoa7wsGbd0V3epg==}
+ engines: {node: '>=18'}
+ hasBin: true
+ peerDependencies:
+ typescript: '>= 4.8.x'
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
+ mute-stream@2.0.0:
+ resolution: {integrity: sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==}
+ engines: {node: ^18.17.0 || >=20.5.0}
+
mz@2.7.0:
resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==}
@@ -6681,6 +6774,10 @@ packages:
no-case@3.0.4:
resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==}
+ nock@14.0.10:
+ resolution: {integrity: sha512-Q7HjkpyPeLa0ZVZC5qpxBt5EyLczFJ91MEewQiIi9taWuA0KB/MDJlUWtON+7dGouVdADTQsf9RA7TZk6D8VMw==}
+ engines: {node: '>=18.20.0 <20 || >=20.12.1'}
+
node-abi@3.85.0:
resolution: {integrity: sha512-zsFhmbkAzwhTft6nd3VxcG0cvJsT70rL+BIGHWVq5fi6MwGrHwzqKaxXE+Hl2GmnGItnDKPPkO5/LQqjVkIdFg==}
engines: {node: '>=10'}
@@ -6773,6 +6870,9 @@ packages:
os-browserify@0.3.0:
resolution: {integrity: sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A==}
+ outvariant@1.4.3:
+ resolution: {integrity: sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA==}
+
oxc-resolver@11.14.2:
resolution: {integrity: sha512-M5fERQKcrCngMZNnk1gRaBbYcqpqXLgMcoqAo7Wpty+KH0I18i03oiy2peUsGJwFaKAEbmo+CtAyhXh08RZ1RA==}
@@ -6890,6 +6990,9 @@ packages:
path-parse@1.0.7:
resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
+ path-to-regexp@6.3.0:
+ resolution: {integrity: sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==}
+
path-type@4.0.0:
resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
engines: {node: '>=8'}
@@ -7134,6 +7237,10 @@ packages:
prop-types@15.8.1:
resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==}
+ propagate@2.0.1:
+ resolution: {integrity: sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==}
+ engines: {node: '>= 8'}
+
property-information@5.6.0:
resolution: {integrity: sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA==}
@@ -7571,6 +7678,9 @@ packages:
resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==}
engines: {node: '>=18'}
+ rettime@0.7.0:
+ resolution: {integrity: sha512-LPRKoHnLKd/r3dVxcwO7vhCW+orkOGj9ViueosEBK6ie89CijnfRlhaDhHq/3Hxu4CkWQtxwlBG0mzTQY6uQjw==}
+
reusify@1.1.0:
resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==}
engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
@@ -7823,6 +7933,10 @@ packages:
state-local@1.0.7:
resolution: {integrity: sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==}
+ statuses@2.0.2:
+ resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==}
+ engines: {node: '>= 0.8'}
+
storybook@9.1.13:
resolution: {integrity: sha512-G3KZ36EVzXyHds72B/qtWiJnhUpM0xOUeYlDcO9DSHL1bDTv15cW4+upBl+mcBZrDvU838cn7Bv4GpF+O5MCfw==}
hasBin: true
@@ -7838,6 +7952,9 @@ packages:
stream-http@3.2.0:
resolution: {integrity: sha512-Oq1bLqisTyK3TSCXpPbT4sdeYNdmyZJv1LxpEm2vu1ZhK89kSE5YXwZc3cWk0MagGaKriBh9mCFbVGtO+vY29A==}
+ strict-event-emitter@0.5.1:
+ resolution: {integrity: sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ==}
+
string-argv@0.3.2:
resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==}
engines: {node: '>=0.6.19'}
@@ -7984,6 +8101,10 @@ packages:
tabbable@6.3.0:
resolution: {integrity: sha512-EIHvdY5bPLuWForiR/AN2Bxngzpuwn1is4asboytXtpTgsArc+WmSJKVLlhdh71u7jFcryDqB2A8lQvj78MkyQ==}
+ tagged-tag@1.0.0:
+ resolution: {integrity: sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==}
+ engines: {node: '>=20'}
+
tailwind-merge@2.6.0:
resolution: {integrity: sha512-P+Vu1qXfzediirmHOC3xKGAYeZtPcV9g76X+xg2FD4tYgR71ewMA35Y3sCz3zhiN/dwefRpJX0yBcgwi1fXNQA==}
@@ -8098,6 +8219,10 @@ packages:
resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==}
engines: {node: '>=6'}
+ tough-cookie@6.0.0:
+ resolution: {integrity: sha512-kXuRi1mtaKMrsLUxz3sQYvVl37B0Ns6MzfrtV5DvJceE9bPyspOqk9xxv7XbZWcfLWbFmm997vl83qUWVJA64w==}
+ engines: {node: '>=16'}
+
tr46@1.0.1:
resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==}
@@ -8197,6 +8322,10 @@ packages:
resolution: {integrity: sha512-5zknd7Dss75pMSED270A1RQS3KloqRJA9XbXLe0eCxyw7xXFb3rd+9B0UQ/0E+LQT6lnrLviEolYORlRWamn4w==}
engines: {node: '>=16'}
+ type-fest@5.3.0:
+ resolution: {integrity: sha512-d9CwU93nN0IA1QL+GSNDdwLAu1Ew5ZjTwupvedwg3WdfoH6pIDvYQ2hV0Uc2nKBLPq7NB5apCx57MLS5qlmO5g==}
+ engines: {node: '>=20'}
+
typescript@5.9.3:
resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==}
engines: {node: '>=14.17'}
@@ -8279,6 +8408,9 @@ packages:
resolution: {integrity: sha512-us4j03/499KhbGP8BU7Hrzrgseo+KdfJYWcbcajCOqsAyb8Gk0Yn2kiUIcZISYCb1JFaZfIuG3b42HmguVOKCQ==}
engines: {node: '>=18.12.0'}
+ until-async@3.0.2:
+ resolution: {integrity: sha512-IiSk4HlzAMqTUseHHe3VhIGyuFmN90zMTpD3Z3y8jeQbzLIq500MVM7Jq2vUAnTKAFPJrqwkzr6PoTcPhGcOiw==}
+
upath@1.2.0:
resolution: {integrity: sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==}
engines: {node: '>=4'}
@@ -8553,6 +8685,10 @@ packages:
workbox-window@6.6.0:
resolution: {integrity: sha512-L4N9+vka17d16geaJXXRjENLFldvkWy7JyGxElRD0JvBxvFEd8LOhr+uXCcar/NzAmIBRv9EZ+M+Qr4mOoBITw==}
+ wrap-ansi@6.2.0:
+ resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==}
+ engines: {node: '>=8'}
+
wrap-ansi@7.0.0:
resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
engines: {node: '>=10'}
@@ -8644,6 +8780,10 @@ packages:
resolution: {integrity: sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==}
engines: {node: '>=12.20'}
+ yoctocolors-cjs@2.1.3:
+ resolution: {integrity: sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw==}
+ engines: {node: '>=18'}
+
zen-observable-ts@1.1.0:
resolution: {integrity: sha512-1h4zlLSqI2cRLPJUHJFL8bCWHhkpuXkF+dbGkRaWjgDIG26DmzyshUMrdV/rL3UnR+mhaX4fRq8LPouq0MYYIA==}
@@ -9742,13 +9882,13 @@ snapshots:
'@chevrotain/utils@11.0.3': {}
- '@chromatic-com/storybook@4.1.3(storybook@9.1.13(@testing-library/dom@10.4.1))':
+ '@chromatic-com/storybook@4.1.3(storybook@9.1.13(@testing-library/dom@10.4.1)(msw@2.12.4(@types/node@18.15.0)(typescript@5.9.3)))':
dependencies:
'@neoconfetti/react': 1.0.0
chromatic: 13.3.4
filesize: 10.1.6
jsonfile: 6.2.0
- storybook: 9.1.13(@testing-library/dom@10.4.1)
+ storybook: 9.1.13(@testing-library/dom@10.4.1)(msw@2.12.4(@types/node@18.15.0)(typescript@5.9.3))
strip-ansi: 7.1.2
transitivePeerDependencies:
- '@chromatic-com/cypress'
@@ -10364,6 +10504,39 @@ snapshots:
'@img/sharp-win32-x64@0.34.5':
optional: true
+ '@inquirer/ansi@1.0.2':
+ optional: true
+
+ '@inquirer/confirm@5.1.21(@types/node@18.15.0)':
+ dependencies:
+ '@inquirer/core': 10.3.2(@types/node@18.15.0)
+ '@inquirer/type': 3.0.10(@types/node@18.15.0)
+ optionalDependencies:
+ '@types/node': 18.15.0
+ optional: true
+
+ '@inquirer/core@10.3.2(@types/node@18.15.0)':
+ dependencies:
+ '@inquirer/ansi': 1.0.2
+ '@inquirer/figures': 1.0.15
+ '@inquirer/type': 3.0.10(@types/node@18.15.0)
+ cli-width: 4.1.0
+ mute-stream: 2.0.0
+ signal-exit: 4.1.0
+ wrap-ansi: 6.2.0
+ yoctocolors-cjs: 2.1.3
+ optionalDependencies:
+ '@types/node': 18.15.0
+ optional: true
+
+ '@inquirer/figures@1.0.15':
+ optional: true
+
+ '@inquirer/type@3.0.10(@types/node@18.15.0)':
+ optionalDependencies:
+ '@types/node': 18.15.0
+ optional: true
+
'@isaacs/balanced-match@4.0.1': {}
'@isaacs/brace-expansion@5.0.0':
@@ -10886,6 +11059,25 @@ snapshots:
react: 19.2.1
react-dom: 19.2.1(react@19.2.1)
+ '@mswjs/interceptors@0.39.8':
+ dependencies:
+ '@open-draft/deferred-promise': 2.2.0
+ '@open-draft/logger': 0.3.0
+ '@open-draft/until': 2.1.0
+ is-node-process: 1.2.0
+ outvariant: 1.4.3
+ strict-event-emitter: 0.5.1
+
+ '@mswjs/interceptors@0.40.0':
+ dependencies:
+ '@open-draft/deferred-promise': 2.2.0
+ '@open-draft/logger': 0.3.0
+ '@open-draft/until': 2.1.0
+ is-node-process: 1.2.0
+ outvariant: 1.4.3
+ strict-event-emitter: 0.5.1
+ optional: true
+
'@napi-rs/wasm-runtime@1.1.0':
dependencies:
'@emnapi/core': 1.7.1
@@ -11042,6 +11234,15 @@ snapshots:
dependencies:
'@octokit/openapi-types': 25.1.0
+ '@open-draft/deferred-promise@2.2.0': {}
+
+ '@open-draft/logger@0.3.0':
+ dependencies:
+ is-node-process: 1.2.0
+ outvariant: 1.4.3
+
+ '@open-draft/until@2.1.0': {}
+
'@oxc-resolver/binding-android-arm-eabi@11.14.2':
optional: true
@@ -11584,38 +11785,38 @@ snapshots:
dependencies:
'@sinonjs/commons': 3.0.1
- '@storybook/addon-docs@9.1.13(@types/react@19.2.7)(storybook@9.1.13(@testing-library/dom@10.4.1))':
+ '@storybook/addon-docs@9.1.13(@types/react@19.2.7)(storybook@9.1.13(@testing-library/dom@10.4.1)(msw@2.12.4(@types/node@18.15.0)(typescript@5.9.3)))':
dependencies:
'@mdx-js/react': 3.1.1(@types/react@19.2.7)(react@19.2.1)
- '@storybook/csf-plugin': 9.1.13(storybook@9.1.13(@testing-library/dom@10.4.1))
+ '@storybook/csf-plugin': 9.1.13(storybook@9.1.13(@testing-library/dom@10.4.1)(msw@2.12.4(@types/node@18.15.0)(typescript@5.9.3)))
'@storybook/icons': 1.6.0(react-dom@19.2.1(react@19.2.1))(react@19.2.1)
- '@storybook/react-dom-shim': 9.1.13(react-dom@19.2.1(react@19.2.1))(react@19.2.1)(storybook@9.1.13(@testing-library/dom@10.4.1))
+ '@storybook/react-dom-shim': 9.1.13(react-dom@19.2.1(react@19.2.1))(react@19.2.1)(storybook@9.1.13(@testing-library/dom@10.4.1)(msw@2.12.4(@types/node@18.15.0)(typescript@5.9.3)))
react: 19.2.1
react-dom: 19.2.1(react@19.2.1)
- storybook: 9.1.13(@testing-library/dom@10.4.1)
+ storybook: 9.1.13(@testing-library/dom@10.4.1)(msw@2.12.4(@types/node@18.15.0)(typescript@5.9.3))
ts-dedent: 2.2.0
transitivePeerDependencies:
- '@types/react'
- '@storybook/addon-links@9.1.13(react@19.2.1)(storybook@9.1.13(@testing-library/dom@10.4.1))':
+ '@storybook/addon-links@9.1.13(react@19.2.1)(storybook@9.1.13(@testing-library/dom@10.4.1)(msw@2.12.4(@types/node@18.15.0)(typescript@5.9.3)))':
dependencies:
'@storybook/global': 5.0.0
- storybook: 9.1.13(@testing-library/dom@10.4.1)
+ storybook: 9.1.13(@testing-library/dom@10.4.1)(msw@2.12.4(@types/node@18.15.0)(typescript@5.9.3))
optionalDependencies:
react: 19.2.1
- '@storybook/addon-onboarding@9.1.13(storybook@9.1.13(@testing-library/dom@10.4.1))':
+ '@storybook/addon-onboarding@9.1.13(storybook@9.1.13(@testing-library/dom@10.4.1)(msw@2.12.4(@types/node@18.15.0)(typescript@5.9.3)))':
dependencies:
- storybook: 9.1.13(@testing-library/dom@10.4.1)
+ storybook: 9.1.13(@testing-library/dom@10.4.1)(msw@2.12.4(@types/node@18.15.0)(typescript@5.9.3))
- '@storybook/addon-themes@9.1.13(storybook@9.1.13(@testing-library/dom@10.4.1))':
+ '@storybook/addon-themes@9.1.13(storybook@9.1.13(@testing-library/dom@10.4.1)(msw@2.12.4(@types/node@18.15.0)(typescript@5.9.3)))':
dependencies:
- storybook: 9.1.13(@testing-library/dom@10.4.1)
+ storybook: 9.1.13(@testing-library/dom@10.4.1)(msw@2.12.4(@types/node@18.15.0)(typescript@5.9.3))
ts-dedent: 2.2.0
- '@storybook/builder-webpack5@9.1.13(esbuild@0.25.0)(storybook@9.1.13(@testing-library/dom@10.4.1))(typescript@5.9.3)(uglify-js@3.19.3)':
+ '@storybook/builder-webpack5@9.1.13(esbuild@0.25.0)(storybook@9.1.13(@testing-library/dom@10.4.1)(msw@2.12.4(@types/node@18.15.0)(typescript@5.9.3)))(typescript@5.9.3)(uglify-js@3.19.3)':
dependencies:
- '@storybook/core-webpack': 9.1.13(storybook@9.1.13(@testing-library/dom@10.4.1))
+ '@storybook/core-webpack': 9.1.13(storybook@9.1.13(@testing-library/dom@10.4.1)(msw@2.12.4(@types/node@18.15.0)(typescript@5.9.3)))
case-sensitive-paths-webpack-plugin: 2.4.0
cjs-module-lexer: 1.4.3
css-loader: 6.11.0(webpack@5.103.0(esbuild@0.25.0)(uglify-js@3.19.3))
@@ -11623,7 +11824,7 @@ snapshots:
fork-ts-checker-webpack-plugin: 8.0.0(typescript@5.9.3)(webpack@5.103.0(esbuild@0.25.0)(uglify-js@3.19.3))
html-webpack-plugin: 5.6.5(webpack@5.103.0(esbuild@0.25.0)(uglify-js@3.19.3))
magic-string: 0.30.21
- storybook: 9.1.13(@testing-library/dom@10.4.1)
+ storybook: 9.1.13(@testing-library/dom@10.4.1)(msw@2.12.4(@types/node@18.15.0)(typescript@5.9.3))
style-loader: 3.3.4(webpack@5.103.0(esbuild@0.25.0)(uglify-js@3.19.3))
terser-webpack-plugin: 5.3.14(esbuild@0.25.0)(uglify-js@3.19.3)(webpack@5.103.0(esbuild@0.25.0)(uglify-js@3.19.3))
ts-dedent: 2.2.0
@@ -11640,14 +11841,14 @@ snapshots:
- uglify-js
- webpack-cli
- '@storybook/core-webpack@9.1.13(storybook@9.1.13(@testing-library/dom@10.4.1))':
+ '@storybook/core-webpack@9.1.13(storybook@9.1.13(@testing-library/dom@10.4.1)(msw@2.12.4(@types/node@18.15.0)(typescript@5.9.3)))':
dependencies:
- storybook: 9.1.13(@testing-library/dom@10.4.1)
+ storybook: 9.1.13(@testing-library/dom@10.4.1)(msw@2.12.4(@types/node@18.15.0)(typescript@5.9.3))
ts-dedent: 2.2.0
- '@storybook/csf-plugin@9.1.13(storybook@9.1.13(@testing-library/dom@10.4.1))':
+ '@storybook/csf-plugin@9.1.13(storybook@9.1.13(@testing-library/dom@10.4.1)(msw@2.12.4(@types/node@18.15.0)(typescript@5.9.3)))':
dependencies:
- storybook: 9.1.13(@testing-library/dom@10.4.1)
+ storybook: 9.1.13(@testing-library/dom@10.4.1)(msw@2.12.4(@types/node@18.15.0)(typescript@5.9.3))
unplugin: 1.16.1
'@storybook/global@5.0.0': {}
@@ -11657,7 +11858,7 @@ snapshots:
react: 19.2.1
react-dom: 19.2.1(react@19.2.1)
- '@storybook/nextjs@9.1.13(esbuild@0.25.0)(next@15.5.7(@babel/core@7.28.5)(react-dom@19.2.1(react@19.2.1))(react@19.2.1)(sass@1.94.2))(react-dom@19.2.1(react@19.2.1))(react@19.2.1)(sass@1.94.2)(storybook@9.1.13(@testing-library/dom@10.4.1))(type-fest@4.2.0)(typescript@5.9.3)(uglify-js@3.19.3)(webpack-hot-middleware@2.26.1)(webpack@5.103.0(esbuild@0.25.0)(uglify-js@3.19.3))':
+ '@storybook/nextjs@9.1.13(esbuild@0.25.0)(next@15.5.7(@babel/core@7.28.5)(react-dom@19.2.1(react@19.2.1))(react@19.2.1)(sass@1.94.2))(react-dom@19.2.1(react@19.2.1))(react@19.2.1)(sass@1.94.2)(storybook@9.1.13(@testing-library/dom@10.4.1)(msw@2.12.4(@types/node@18.15.0)(typescript@5.9.3)))(type-fest@4.2.0)(typescript@5.9.3)(uglify-js@3.19.3)(webpack-hot-middleware@2.26.1)(webpack@5.103.0(esbuild@0.25.0)(uglify-js@3.19.3))':
dependencies:
'@babel/core': 7.28.5
'@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.28.5)
@@ -11673,9 +11874,9 @@ snapshots:
'@babel/preset-typescript': 7.28.5(@babel/core@7.28.5)
'@babel/runtime': 7.28.4
'@pmmmwh/react-refresh-webpack-plugin': 0.5.17(react-refresh@0.14.2)(type-fest@4.2.0)(webpack-hot-middleware@2.26.1)(webpack@5.103.0(esbuild@0.25.0)(uglify-js@3.19.3))
- '@storybook/builder-webpack5': 9.1.13(esbuild@0.25.0)(storybook@9.1.13(@testing-library/dom@10.4.1))(typescript@5.9.3)(uglify-js@3.19.3)
- '@storybook/preset-react-webpack': 9.1.13(esbuild@0.25.0)(react-dom@19.2.1(react@19.2.1))(react@19.2.1)(storybook@9.1.13(@testing-library/dom@10.4.1))(typescript@5.9.3)(uglify-js@3.19.3)
- '@storybook/react': 9.1.13(react-dom@19.2.1(react@19.2.1))(react@19.2.1)(storybook@9.1.13(@testing-library/dom@10.4.1))(typescript@5.9.3)
+ '@storybook/builder-webpack5': 9.1.13(esbuild@0.25.0)(storybook@9.1.13(@testing-library/dom@10.4.1)(msw@2.12.4(@types/node@18.15.0)(typescript@5.9.3)))(typescript@5.9.3)(uglify-js@3.19.3)
+ '@storybook/preset-react-webpack': 9.1.13(esbuild@0.25.0)(react-dom@19.2.1(react@19.2.1))(react@19.2.1)(storybook@9.1.13(@testing-library/dom@10.4.1)(msw@2.12.4(@types/node@18.15.0)(typescript@5.9.3)))(typescript@5.9.3)(uglify-js@3.19.3)
+ '@storybook/react': 9.1.13(react-dom@19.2.1(react@19.2.1))(react@19.2.1)(storybook@9.1.13(@testing-library/dom@10.4.1)(msw@2.12.4(@types/node@18.15.0)(typescript@5.9.3)))(typescript@5.9.3)
'@types/semver': 7.7.1
babel-loader: 9.2.1(@babel/core@7.28.5)(webpack@5.103.0(esbuild@0.25.0)(uglify-js@3.19.3))
css-loader: 6.11.0(webpack@5.103.0(esbuild@0.25.0)(uglify-js@3.19.3))
@@ -11691,7 +11892,7 @@ snapshots:
resolve-url-loader: 5.0.0
sass-loader: 16.0.6(sass@1.94.2)(webpack@5.103.0(esbuild@0.25.0)(uglify-js@3.19.3))
semver: 7.7.3
- storybook: 9.1.13(@testing-library/dom@10.4.1)
+ storybook: 9.1.13(@testing-library/dom@10.4.1)(msw@2.12.4(@types/node@18.15.0)(typescript@5.9.3))
style-loader: 3.3.4(webpack@5.103.0(esbuild@0.25.0)(uglify-js@3.19.3))
styled-jsx: 5.1.7(@babel/core@7.28.5)(react@19.2.1)
tsconfig-paths: 4.2.0
@@ -11717,9 +11918,9 @@ snapshots:
- webpack-hot-middleware
- webpack-plugin-serve
- '@storybook/preset-react-webpack@9.1.13(esbuild@0.25.0)(react-dom@19.2.1(react@19.2.1))(react@19.2.1)(storybook@9.1.13(@testing-library/dom@10.4.1))(typescript@5.9.3)(uglify-js@3.19.3)':
+ '@storybook/preset-react-webpack@9.1.13(esbuild@0.25.0)(react-dom@19.2.1(react@19.2.1))(react@19.2.1)(storybook@9.1.13(@testing-library/dom@10.4.1)(msw@2.12.4(@types/node@18.15.0)(typescript@5.9.3)))(typescript@5.9.3)(uglify-js@3.19.3)':
dependencies:
- '@storybook/core-webpack': 9.1.13(storybook@9.1.13(@testing-library/dom@10.4.1))
+ '@storybook/core-webpack': 9.1.13(storybook@9.1.13(@testing-library/dom@10.4.1)(msw@2.12.4(@types/node@18.15.0)(typescript@5.9.3)))
'@storybook/react-docgen-typescript-plugin': 1.0.6--canary.9.0c3f3b7.0(typescript@5.9.3)(webpack@5.103.0(esbuild@0.25.0)(uglify-js@3.19.3))
'@types/semver': 7.7.1
find-up: 7.0.0
@@ -11729,7 +11930,7 @@ snapshots:
react-dom: 19.2.1(react@19.2.1)
resolve: 1.22.11
semver: 7.7.3
- storybook: 9.1.13(@testing-library/dom@10.4.1)
+ storybook: 9.1.13(@testing-library/dom@10.4.1)(msw@2.12.4(@types/node@18.15.0)(typescript@5.9.3))
tsconfig-paths: 4.2.0
webpack: 5.103.0(esbuild@0.25.0)(uglify-js@3.19.3)
optionalDependencies:
@@ -11755,19 +11956,19 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@storybook/react-dom-shim@9.1.13(react-dom@19.2.1(react@19.2.1))(react@19.2.1)(storybook@9.1.13(@testing-library/dom@10.4.1))':
+ '@storybook/react-dom-shim@9.1.13(react-dom@19.2.1(react@19.2.1))(react@19.2.1)(storybook@9.1.13(@testing-library/dom@10.4.1)(msw@2.12.4(@types/node@18.15.0)(typescript@5.9.3)))':
dependencies:
react: 19.2.1
react-dom: 19.2.1(react@19.2.1)
- storybook: 9.1.13(@testing-library/dom@10.4.1)
+ storybook: 9.1.13(@testing-library/dom@10.4.1)(msw@2.12.4(@types/node@18.15.0)(typescript@5.9.3))
- '@storybook/react@9.1.13(react-dom@19.2.1(react@19.2.1))(react@19.2.1)(storybook@9.1.13(@testing-library/dom@10.4.1))(typescript@5.9.3)':
+ '@storybook/react@9.1.13(react-dom@19.2.1(react@19.2.1))(react@19.2.1)(storybook@9.1.13(@testing-library/dom@10.4.1)(msw@2.12.4(@types/node@18.15.0)(typescript@5.9.3)))(typescript@5.9.3)':
dependencies:
'@storybook/global': 5.0.0
- '@storybook/react-dom-shim': 9.1.13(react-dom@19.2.1(react@19.2.1))(react@19.2.1)(storybook@9.1.13(@testing-library/dom@10.4.1))
+ '@storybook/react-dom-shim': 9.1.13(react-dom@19.2.1(react@19.2.1))(react@19.2.1)(storybook@9.1.13(@testing-library/dom@10.4.1)(msw@2.12.4(@types/node@18.15.0)(typescript@5.9.3)))
react: 19.2.1
react-dom: 19.2.1(react@19.2.1)
- storybook: 9.1.13(@testing-library/dom@10.4.1)
+ storybook: 9.1.13(@testing-library/dom@10.4.1)(msw@2.12.4(@types/node@18.15.0)(typescript@5.9.3))
optionalDependencies:
typescript: 5.9.3
@@ -12213,6 +12414,9 @@ snapshots:
'@types/stack-utils@2.0.3': {}
+ '@types/statuses@2.0.6':
+ optional: true
+
'@types/trusted-types@2.0.7': {}
'@types/unist@2.0.11': {}
@@ -12343,11 +12547,13 @@ snapshots:
chai: 5.3.3
tinyrainbow: 2.0.0
- '@vitest/mocker@3.2.4':
+ '@vitest/mocker@3.2.4(msw@2.12.4(@types/node@18.15.0)(typescript@5.9.3))':
dependencies:
'@vitest/spy': 3.2.4
estree-walker: 3.0.3
magic-string: 0.30.21
+ optionalDependencies:
+ msw: 2.12.4(@types/node@18.15.0)(typescript@5.9.3)
'@vitest/pretty-format@3.2.4':
dependencies:
@@ -13033,6 +13239,9 @@ snapshots:
slice-ansi: 5.0.0
string-width: 4.2.3
+ cli-width@4.1.0:
+ optional: true
+
client-only@0.0.1: {}
cliui@8.0.1:
@@ -13133,6 +13342,9 @@ snapshots:
convert-source-map@2.0.0: {}
+ cookie@1.1.1:
+ optional: true
+
copy-to-clipboard@3.3.3:
dependencies:
toggle-selection: 1.0.6
@@ -14014,11 +14226,11 @@ snapshots:
semver: 7.7.2
typescript: 5.9.3
- eslint-plugin-storybook@9.1.16(eslint@9.39.1(jiti@1.21.7))(storybook@9.1.13(@testing-library/dom@10.4.1))(typescript@5.9.3):
+ eslint-plugin-storybook@9.1.16(eslint@9.39.1(jiti@1.21.7))(storybook@9.1.13(@testing-library/dom@10.4.1)(msw@2.12.4(@types/node@18.15.0)(typescript@5.9.3)))(typescript@5.9.3):
dependencies:
'@typescript-eslint/utils': 8.48.1(eslint@9.39.1(jiti@1.21.7))(typescript@5.9.3)
eslint: 9.39.1(jiti@1.21.7)
- storybook: 9.1.13(@testing-library/dom@10.4.1)
+ storybook: 9.1.13(@testing-library/dom@10.4.1)(msw@2.12.4(@types/node@18.15.0)(typescript@5.9.3))
transitivePeerDependencies:
- supports-color
- typescript
@@ -14531,6 +14743,9 @@ snapshots:
graphemer@1.4.0: {}
+ graphql@16.12.0:
+ optional: true
+
gzip-size@6.0.0:
dependencies:
duplexer: 0.1.2
@@ -14705,6 +14920,9 @@ snapshots:
he@1.2.0: {}
+ headers-polyfill@4.0.3:
+ optional: true
+
highlight.js@10.7.3: {}
highlightjs-vue@1.0.0: {}
@@ -14907,6 +15125,8 @@ snapshots:
is-module@1.0.0: {}
+ is-node-process@1.2.0: {}
+
is-number@7.0.0: {}
is-obj@1.0.1: {}
@@ -15350,6 +15570,8 @@ snapshots:
json-stable-stringify-without-jsonify@1.0.1: {}
+ json-stringify-safe@5.0.1: {}
+
json5@2.2.3: {}
jsonc-eslint-parser@2.4.1:
@@ -16165,6 +16387,35 @@ snapshots:
ms@2.1.3: {}
+ msw@2.12.4(@types/node@18.15.0)(typescript@5.9.3):
+ dependencies:
+ '@inquirer/confirm': 5.1.21(@types/node@18.15.0)
+ '@mswjs/interceptors': 0.40.0
+ '@open-draft/deferred-promise': 2.2.0
+ '@types/statuses': 2.0.6
+ cookie: 1.1.1
+ graphql: 16.12.0
+ headers-polyfill: 4.0.3
+ is-node-process: 1.2.0
+ outvariant: 1.4.3
+ path-to-regexp: 6.3.0
+ picocolors: 1.1.1
+ rettime: 0.7.0
+ statuses: 2.0.2
+ strict-event-emitter: 0.5.1
+ tough-cookie: 6.0.0
+ type-fest: 5.3.0
+ until-async: 3.0.2
+ yargs: 17.7.2
+ optionalDependencies:
+ typescript: 5.9.3
+ transitivePeerDependencies:
+ - '@types/node'
+ optional: true
+
+ mute-stream@2.0.0:
+ optional: true
+
mz@2.7.0:
dependencies:
any-promise: 1.3.0
@@ -16236,6 +16487,12 @@ snapshots:
lower-case: 2.0.2
tslib: 2.8.1
+ nock@14.0.10:
+ dependencies:
+ '@mswjs/interceptors': 0.39.8
+ json-stringify-safe: 5.0.1
+ propagate: 2.0.1
+
node-abi@3.85.0:
dependencies:
semver: 7.7.3
@@ -16344,6 +16601,8 @@ snapshots:
os-browserify@0.3.0: {}
+ outvariant@1.4.3: {}
+
oxc-resolver@11.14.2:
optionalDependencies:
'@oxc-resolver/binding-android-arm-eabi': 11.14.2
@@ -16481,6 +16740,9 @@ snapshots:
path-parse@1.0.7: {}
+ path-to-regexp@6.3.0:
+ optional: true
+
path-type@4.0.0: {}
path2d@0.2.2:
@@ -16717,6 +16979,8 @@ snapshots:
object-assign: 4.1.1
react-is: 16.13.1
+ propagate@2.0.1: {}
+
property-information@5.6.0:
dependencies:
xtend: 4.0.2
@@ -17271,6 +17535,9 @@ snapshots:
onetime: 7.0.0
signal-exit: 4.1.0
+ rettime@0.7.0:
+ optional: true
+
reusify@1.1.0: {}
rfdc@1.4.1: {}
@@ -17549,13 +17816,16 @@ snapshots:
state-local@1.0.7: {}
- storybook@9.1.13(@testing-library/dom@10.4.1):
+ statuses@2.0.2:
+ optional: true
+
+ storybook@9.1.13(@testing-library/dom@10.4.1)(msw@2.12.4(@types/node@18.15.0)(typescript@5.9.3)):
dependencies:
'@storybook/global': 5.0.0
'@testing-library/jest-dom': 6.9.1
'@testing-library/user-event': 14.6.1(@testing-library/dom@10.4.1)
'@vitest/expect': 3.2.4
- '@vitest/mocker': 3.2.4
+ '@vitest/mocker': 3.2.4(msw@2.12.4(@types/node@18.15.0)(typescript@5.9.3))
'@vitest/spy': 3.2.4
better-opn: 3.0.2
esbuild: 0.25.0
@@ -17583,6 +17853,8 @@ snapshots:
readable-stream: 3.6.2
xtend: 4.0.2
+ strict-event-emitter@0.5.1: {}
+
string-argv@0.3.2: {}
string-length@4.0.2:
@@ -17708,6 +17980,9 @@ snapshots:
tabbable@6.3.0: {}
+ tagged-tag@1.0.0:
+ optional: true
+
tailwind-merge@2.6.0: {}
tailwindcss@3.4.18(tsx@4.21.0)(yaml@2.8.2):
@@ -17844,6 +18119,11 @@ snapshots:
totalist@3.0.1: {}
+ tough-cookie@6.0.0:
+ dependencies:
+ tldts: 7.0.19
+ optional: true
+
tr46@1.0.1:
dependencies:
punycode: 2.3.1
@@ -17934,6 +18214,11 @@ snapshots:
type-fest@4.2.0: {}
+ type-fest@5.3.0:
+ dependencies:
+ tagged-tag: 1.0.0
+ optional: true
+
typescript@5.9.3: {}
ufo@1.6.1: {}
@@ -18021,6 +18306,9 @@ snapshots:
webpack-virtual-modules: 0.6.2
optional: true
+ until-async@3.0.2:
+ optional: true
+
upath@1.2.0: {}
update-browserslist-db@1.1.4(browserslist@4.28.0):
@@ -18387,6 +18675,13 @@ snapshots:
'@types/trusted-types': 2.0.7
workbox-core: 6.6.0
+ wrap-ansi@6.2.0:
+ dependencies:
+ ansi-styles: 4.3.0
+ string-width: 4.2.3
+ strip-ansi: 6.0.1
+ optional: true
+
wrap-ansi@7.0.0:
dependencies:
ansi-styles: 4.3.0
@@ -18449,6 +18744,9 @@ snapshots:
yocto-queue@1.2.2: {}
+ yoctocolors-cjs@2.1.3:
+ optional: true
+
zen-observable-ts@1.1.0:
dependencies:
'@types/zen-observable': 0.8.3
diff --git a/web/testing/testing.md b/web/testing/testing.md
index 6ad04eb376..e2df86c653 100644
--- a/web/testing/testing.md
+++ b/web/testing/testing.md
@@ -202,6 +202,16 @@ Reserve snapshots for static, deterministic fragments (icons, badges, layout chr
**Note**: Dify is a desktop application. **No need for** responsive/mobile testing.
+### 12. Mock API
+
+Use Nock to mock API calls. Example:
+
+```ts
+const mockGithubStar = (status: number, body: Record, delayMs = 0) => {
+ return nock(GITHUB_HOST).get(GITHUB_PATH).delay(delayMs).reply(status, body)
+}
+```
+
## Code Style
### Example Structure