Backend: - Add TenantCustomTier model for per-tenant feature overrides - Update EntitlementService to check custom tier before plan features - Add custom_tier action on TenantViewSet (GET/PUT/DELETE) - Add Celery task for grace period management (30-day expiry) Frontend: - Add DynamicFeaturesEditor component for dynamic feature management - Fix BusinessEditModal to load features from plan defaults when no custom tier - Update limits (max_users, max_resources, etc.) to use featureValues - Remove outdated canonical feature check from FeaturePicker (removes warning icons) - Add useBillingPlans hook for accessing billing system data - Add custom tier API functions to platform.ts Features now follow consistent rules: - Load from plan defaults when no custom tier exists - Load from custom tier when one exists - Reset to plan defaults when plan changes - Save to custom tier on edit 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
48 lines
1.6 KiB
TypeScript
48 lines
1.6 KiB
TypeScript
import { describe, it, expect } from 'vitest';
|
|
import { render } from '@testing-library/react';
|
|
import SmoothScheduleLogo from '../SmoothScheduleLogo';
|
|
|
|
describe('SmoothScheduleLogo', () => {
|
|
it('renders an SVG element', () => {
|
|
const { container } = render(<SmoothScheduleLogo />);
|
|
const svg = container.querySelector('svg');
|
|
expect(svg).toBeInTheDocument();
|
|
});
|
|
|
|
it('has correct viewBox', () => {
|
|
const { container } = render(<SmoothScheduleLogo />);
|
|
const svg = container.querySelector('svg');
|
|
expect(svg).toHaveAttribute('viewBox', '0 0 1730 1100');
|
|
});
|
|
|
|
it('uses currentColor for fill', () => {
|
|
const { container } = render(<SmoothScheduleLogo />);
|
|
const svg = container.querySelector('svg');
|
|
expect(svg).toHaveAttribute('fill', 'currentColor');
|
|
});
|
|
|
|
it('applies custom className', () => {
|
|
const { container } = render(<SmoothScheduleLogo className="custom-logo-class" />);
|
|
const svg = container.querySelector('svg');
|
|
expect(svg).toHaveClass('custom-logo-class');
|
|
});
|
|
|
|
it('renders without className when not provided', () => {
|
|
const { container } = render(<SmoothScheduleLogo />);
|
|
const svg = container.querySelector('svg');
|
|
expect(svg).toBeInTheDocument();
|
|
});
|
|
|
|
it('contains path elements', () => {
|
|
const { container } = render(<SmoothScheduleLogo />);
|
|
const paths = container.querySelectorAll('path');
|
|
expect(paths.length).toBeGreaterThan(0);
|
|
});
|
|
|
|
it('has xmlns attribute', () => {
|
|
const { container } = render(<SmoothScheduleLogo />);
|
|
const svg = container.querySelector('svg');
|
|
expect(svg).toHaveAttribute('xmlns', 'http://www.w3.org/2000/svg');
|
|
});
|
|
});
|