From a4ec9411c3ef4cf4856e86777ae9be8333a6e4ee Mon Sep 17 00:00:00 2001 From: starkiVector-090 Date: Wed, 29 Apr 2026 01:38:20 +0000 Subject: [PATCH] feat: preview workspace component --- .../app/preview/PreviewWorkspace.test.ts | 119 ------------------ .../app/preview/PreviewWorkspace.test.tsx | 44 ++++--- apps/frontend/vitest.config.ts | 2 + 3 files changed, 23 insertions(+), 142 deletions(-) delete mode 100644 apps/frontend/src/components/app/preview/PreviewWorkspace.test.ts diff --git a/apps/frontend/src/components/app/preview/PreviewWorkspace.test.ts b/apps/frontend/src/components/app/preview/PreviewWorkspace.test.ts deleted file mode 100644 index 8f3f34b..0000000 --- a/apps/frontend/src/components/app/preview/PreviewWorkspace.test.ts +++ /dev/null @@ -1,119 +0,0 @@ -import { describe, it, expect, vi, beforeEach } from 'vitest'; -import { render, screen, fireEvent, waitFor } from '@testing-library/react'; -import { PreviewWorkspace } from './PreviewWorkspace'; - -// Mock dependencies -vi.mock('@/hooks/usePreviewService', () => ({ - usePreviewService: () => ({ - generatePreview: vi.fn().mockResolvedValue({ - branding: { primaryColor: '#6366f1', secondaryColor: '#a5b4fc', fontFamily: 'Inter' }, - features: { enableCharts: true, enableTransactionHistory: true }, - mockData: { accountBalance: '10000', recentTransactions: [] }, - css: 'body { background: #6366f1; }', - viewport: { width: 1440, height: 900, class: 'desktop' }, - }), - refreshPreview: vi.fn().mockResolvedValue({ - branding: { primaryColor: '#6366f1', secondaryColor: '#a5b4fc', fontFamily: 'Inter' }, - features: { enableCharts: true, enableTransactionHistory: true }, - mockData: { accountBalance: '10000', recentTransactions: [] }, - css: 'body { background: #6366f1; }', - viewport: { width: 1440, height: 900, class: 'desktop' }, - }), - isLoading: false, - error: null, - }), -})); - -vi.mock('../LoadingSkeleton', () => ({ - LoadingSkeleton: () =>
Loading...
, -})); - -vi.mock('../ErrorState', () => ({ - ErrorState: ({ title, description, onRetry }: any) => ( -
-

{title}

-

{description}

- -
- ), -})); - -const mockCustomization = { - branding: { - appName: 'Test App', - primaryColor: '#6366f1', - secondaryColor: '#a5b4fc', - fontFamily: 'Inter', - }, - features: { - enableCharts: true, - enableTransactionHistory: true, - enableAnalytics: false, - enableNotifications: false, - }, - stellar: { - network: 'testnet', - horizonUrl: 'https://horizon-testnet.stellar.org', - }, -}; - -describe('PreviewWorkspace', () => { - beforeEach(() => { - vi.clearAllMocks(); - }); - - it('renders preview controls and iframe area', () => { - render(); - - // Check if viewport switcher is present - expect(screen.getByText('Desktop')).toBeInTheDocument(); - expect(screen.getByText('Tablet')).toBeInTheDocument(); - expect(screen.getByText('Mobile')).toBeInTheDocument(); - - // Check if refresh button is present - expect(screen.getByText('Refresh')).toBeInTheDocument(); - }); - - it('switches viewports correctly', async () => { - render(); - - const tabletButton = screen.getByText('Tablet'); - fireEvent.click(tabletButton); - - await waitFor(() => { - expect(tabletButton.closest('button')).toHaveClass('bg-white'); - }); - }); - - it('shows loading state initially', () => { - render(); - - expect(screen.getByTestId('loading-skeleton')).toBeInTheDocument(); - }); - - it('handles refresh action', async () => { - render(); - - const refreshButton = screen.getByText('Refresh'); - fireEvent.click(refreshButton); - - await waitFor(() => { - expect(refreshButton.closest('button')).toBeDisabled(); - }); - }); - - it('displays viewport dimensions', () => { - render(); - - // Desktop dimensions should be visible - expect(screen.getByText('1440×900')).toBeInTheDocument(); - }); - - it('handles missing customization gracefully', () => { - render(); - - // Should still render controls even without customization - expect(screen.getByText('Desktop')).toBeInTheDocument(); - expect(screen.getByText('Refresh')).toBeInTheDocument(); - }); -}); diff --git a/apps/frontend/src/components/app/preview/PreviewWorkspace.test.tsx b/apps/frontend/src/components/app/preview/PreviewWorkspace.test.tsx index efe3fff..8e864cf 100644 --- a/apps/frontend/src/components/app/preview/PreviewWorkspace.test.tsx +++ b/apps/frontend/src/components/app/preview/PreviewWorkspace.test.tsx @@ -1,19 +1,19 @@ import React from 'react'; +import { describe, it, expect, vi, beforeEach } from 'vitest'; import { render, screen, fireEvent, waitFor } from '@testing-library/react'; import { PreviewWorkspace } from './PreviewWorkspace'; -import { CustomizationConfig, ViewportClass } from '@craft/types'; +import type { CustomizationConfig, ViewportClass } from '@craft/types'; -// Mock the preview service -jest.mock('@/hooks/usePreviewService', () => ({ +vi.mock('@/hooks/usePreviewService', () => ({ usePreviewService: () => ({ - generatePreview: jest.fn().mockResolvedValue({ + generatePreview: vi.fn().mockResolvedValue({ branding: { primaryColor: '#6366f1', secondaryColor: '#a5b4fc', fontFamily: 'Inter' }, features: { enableCharts: true, enableTransactionHistory: true }, mockData: { accountBalance: '10000', recentTransactions: [] }, css: 'body { background: #6366f1; }', viewport: { width: 1440, height: 900, class: 'desktop' as ViewportClass }, }), - refreshPreview: jest.fn().mockResolvedValue({ + refreshPreview: vi.fn().mockResolvedValue({ branding: { primaryColor: '#6366f1', secondaryColor: '#a5b4fc', fontFamily: 'Inter' }, features: { enableCharts: true, enableTransactionHistory: true }, mockData: { accountBalance: '10000', recentTransactions: [] }, @@ -25,12 +25,11 @@ jest.mock('@/hooks/usePreviewService', () => ({ }), })); -// Mock the LoadingSkeleton and ErrorState components -jest.mock('../LoadingSkeleton', () => ({ +vi.mock('../LoadingSkeleton', () => ({ LoadingSkeleton: () =>
Loading...
, })); -jest.mock('../ErrorState', () => ({ +vi.mock('../ErrorState', () => ({ ErrorState: ({ title, description, onRetry }: any) => (

{title}

@@ -60,57 +59,56 @@ const mockCustomization: CustomizationConfig = { }; describe('PreviewWorkspace', () => { + beforeEach(() => { + vi.clearAllMocks(); + }); + it('renders preview controls and iframe area', () => { render(); - - // Check if viewport switcher is present + expect(screen.getByText('Desktop')).toBeInTheDocument(); expect(screen.getByText('Tablet')).toBeInTheDocument(); expect(screen.getByText('Mobile')).toBeInTheDocument(); - - // Check if refresh button is present expect(screen.getByText('Refresh')).toBeInTheDocument(); }); it('switches viewports correctly', async () => { render(); - + const tabletButton = screen.getByText('Tablet'); fireEvent.click(tabletButton); - + await waitFor(() => { - expect(tabletButton).toHaveClass('bg-white'); + expect(tabletButton.closest('button')).toHaveClass('bg-white'); }); }); it('shows loading state initially', () => { render(); - + expect(screen.getByTestId('loading-skeleton')).toBeInTheDocument(); }); it('handles refresh action', async () => { render(); - + const refreshButton = screen.getByText('Refresh'); fireEvent.click(refreshButton); - + await waitFor(() => { - expect(refreshButton).toBeDisabled(); + expect(refreshButton.closest('button')).toBeDisabled(); }); }); it('displays viewport dimensions', () => { render(); - - // Desktop dimensions should be visible + expect(screen.getByText('1440×900')).toBeInTheDocument(); }); it('handles missing customization gracefully', () => { render(); - - // Should still render controls even without customization + expect(screen.getByText('Desktop')).toBeInTheDocument(); expect(screen.getByText('Refresh')).toBeInTheDocument(); }); diff --git a/apps/frontend/vitest.config.ts b/apps/frontend/vitest.config.ts index 774d8ac..b6468f1 100644 --- a/apps/frontend/vitest.config.ts +++ b/apps/frontend/vitest.config.ts @@ -13,6 +13,8 @@ export default defineConfig({ resolve: { alias: { '@': path.resolve(__dirname, './src'), + '@craft/types': path.resolve(__dirname, '../../packages/types/src'), + '@craft/stellar': path.resolve(__dirname, '../../packages/stellar/src'), }, }, });