feat(10-02): create RemoteNamePreview component with TDD
- Stateless component accepting value prop (string) - Empty/whitespace state: shows grayed [my-remote] placeholder + guidance text - Value state: shows [typed-value] in on-surface-variant color - Renders only div/span elements — no form controls - 9 tests covering empty state, value state, and element type constraints
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
// @vitest-environment jsdom
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { RemoteNamePreview } from './RemoteNamePreview';
|
||||
|
||||
describe('RemoteNamePreview', () => {
|
||||
describe('empty state', () => {
|
||||
it('shows placeholder [my-remote] when value is empty string', () => {
|
||||
render(<RemoteNamePreview value="" />);
|
||||
expect(screen.getByText('[my-remote]')).toBeDefined();
|
||||
});
|
||||
|
||||
it('shows placeholder [my-remote] when value is whitespace-only', () => {
|
||||
render(<RemoteNamePreview value=" " />);
|
||||
expect(screen.getByText('[my-remote]')).toBeDefined();
|
||||
});
|
||||
|
||||
it('shows guidance text when value is empty', () => {
|
||||
render(<RemoteNamePreview value="" />);
|
||||
expect(screen.getByText('Type a name to see how it appears in your config')).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('value state', () => {
|
||||
it('shows [my-backup] when value is "my-backup"', () => {
|
||||
render(<RemoteNamePreview value="my-backup" />);
|
||||
expect(screen.getByText('[my-backup]')).toBeDefined();
|
||||
});
|
||||
|
||||
it('shows [azure-prod] when value is "azure-prod"', () => {
|
||||
render(<RemoteNamePreview value="azure-prod" />);
|
||||
expect(screen.getByText('[azure-prod]')).toBeDefined();
|
||||
});
|
||||
|
||||
it('does NOT show guidance text when value is provided', () => {
|
||||
render(<RemoteNamePreview value="my-backup" />);
|
||||
expect(screen.queryByText('Type a name to see how it appears in your config')).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('element types', () => {
|
||||
it('renders no form controls (no textbox role)', () => {
|
||||
render(<RemoteNamePreview value="" />);
|
||||
expect(screen.queryByRole('textbox')).toBeNull();
|
||||
});
|
||||
|
||||
it('renders no input elements', () => {
|
||||
const { container } = render(<RemoteNamePreview value="test" />);
|
||||
expect(container.querySelector('input')).toBeNull();
|
||||
});
|
||||
|
||||
it('renders no textarea elements', () => {
|
||||
const { container } = render(<RemoteNamePreview value="test" />);
|
||||
expect(container.querySelector('textarea')).toBeNull();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,23 @@
|
||||
interface RemoteNamePreviewProps {
|
||||
value: string;
|
||||
}
|
||||
|
||||
export function RemoteNamePreview({ value }: RemoteNamePreviewProps) {
|
||||
const trimmed = value.trim();
|
||||
const isEmpty = trimmed.length === 0;
|
||||
|
||||
return (
|
||||
<div className="mt-2 rounded-md bg-surface-variant px-3 py-2 text-xs font-mono">
|
||||
{isEmpty ? (
|
||||
<>
|
||||
<span className="text-on-surface-variant/50">[my-remote]</span>
|
||||
<p className="mt-1 text-on-surface-variant/40 font-sans">
|
||||
Type a name to see how it appears in your config
|
||||
</p>
|
||||
</>
|
||||
) : (
|
||||
<span className="text-on-surface-variant">[{trimmed}]</span>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user