@letanure/resend-cli
Version:
A command-line interface for Resend email API
144 lines • 7.22 kB
JavaScript
import { jsx as _jsx } from "react/jsx-runtime";
import { render } from 'ink-testing-library';
import { describe, expect, it, vi } from 'vitest';
import { z } from 'zod';
import { SimpleForm } from './SimpleForm.js';
describe('SimpleForm', () => {
const textFields = [
{
name: 'email',
label: 'Email',
placeholder: 'user@example.com',
helpText: 'Enter your email address',
type: 'text',
},
];
const selectFields = [
{
name: 'subscribed',
label: 'Subscription',
type: 'select',
options: [
{ value: true, label: 'Yes', color: 'green' },
{ value: false, label: 'No', color: 'red' },
],
},
];
const mixedFields = [...textFields, ...selectFields];
const mockOnSubmit = vi.fn();
const mockOnCancel = vi.fn();
it('should render text fields', () => {
const { lastFrame } = render(_jsx(SimpleForm, { fields: textFields, onSubmit: mockOnSubmit, onCancel: mockOnCancel }));
expect(lastFrame()).toContain('Email');
expect(lastFrame()).toContain('Enter your email address');
});
it('should render select fields', () => {
const { lastFrame } = render(_jsx(SimpleForm, { fields: selectFields, onSubmit: mockOnSubmit, onCancel: mockOnCancel }));
expect(lastFrame()).toContain('Subscription');
expect(lastFrame()).toContain('[✓] Yes');
expect(lastFrame()).toContain('[ ] No');
expect(lastFrame()).toContain('Use ←/→ or Space');
});
it('should render mixed field types', () => {
const { lastFrame } = render(_jsx(SimpleForm, { fields: mixedFields, onSubmit: mockOnSubmit, onCancel: mockOnCancel }));
expect(lastFrame()).toContain('Email');
expect(lastFrame()).toContain('Subscription');
expect(lastFrame()).toContain('[✓] Yes');
});
it('should show validation schema in action', () => {
const schema = z.object({
email: z.string().email(),
subscribed: z.boolean(),
});
const { lastFrame } = render(_jsx(SimpleForm, { fields: mixedFields, validateWith: schema, onSubmit: mockOnSubmit, onCancel: mockOnCancel }));
expect(lastFrame()).toContain('Email');
expect(lastFrame()).toContain('Subscription');
});
it('should handle select field default values', () => {
const { lastFrame } = render(_jsx(SimpleForm, { fields: selectFields, onSubmit: mockOnSubmit, onCancel: mockOnCancel }));
// First option should be selected by default
expect(lastFrame()).toContain('[✓] Yes');
expect(lastFrame()).toContain('[ ] No');
});
it('should handle circular navigation with Tab key', async () => {
const multipleFields = [
{ name: 'field1', label: 'Field 1', type: 'text' },
{ name: 'field2', label: 'Field 2', type: 'text' },
{ name: 'field3', label: 'Field 3', type: 'text' },
];
const { stdin } = render(_jsx(SimpleForm, { fields: multipleFields, onSubmit: mockOnSubmit, onCancel: mockOnCancel }));
// Navigate to last field then press Tab to wrap to first
stdin.write('\t'); // Go to field 2
await new Promise((resolve) => setTimeout(resolve, 10));
stdin.write('\t'); // Go to field 3 (last)
await new Promise((resolve) => setTimeout(resolve, 10));
stdin.write('\t'); // Should wrap to field 1 (first)
await new Promise((resolve) => setTimeout(resolve, 10));
// Test passes if no errors thrown and navigation works
expect(true).toBe(true);
});
it('should handle circular navigation with Shift+Tab key', async () => {
const multipleFields = [
{ name: 'field1', label: 'Field 1', type: 'text' },
{ name: 'field2', label: 'Field 2', type: 'text' },
{ name: 'field3', label: 'Field 3', type: 'text' },
];
const { stdin } = render(_jsx(SimpleForm, { fields: multipleFields, onSubmit: mockOnSubmit, onCancel: mockOnCancel }));
// Start at first field, press Shift+Tab to wrap to last
stdin.write('\u001B[Z'); // Shift+Tab (should wrap to last field)
await new Promise((resolve) => setTimeout(resolve, 10));
// Test passes if no errors thrown and navigation works
expect(true).toBe(true);
});
it('should handle circular navigation with arrow keys', async () => {
const multipleFields = [
{ name: 'field1', label: 'Field 1', type: 'text' },
{ name: 'field2', label: 'Field 2', type: 'text' },
{ name: 'field3', label: 'Field 3', type: 'text' },
];
const { stdin } = render(_jsx(SimpleForm, { fields: multipleFields, onSubmit: mockOnSubmit, onCancel: mockOnCancel }));
// Test down arrow from last field wraps to first
stdin.write('\u001B[B'); // Down arrow to field 2
await new Promise((resolve) => setTimeout(resolve, 10));
stdin.write('\u001B[B'); // Down arrow to field 3 (last)
await new Promise((resolve) => setTimeout(resolve, 10));
stdin.write('\u001B[B'); // Down arrow should wrap to field 1 (first)
await new Promise((resolve) => setTimeout(resolve, 10));
// Test up arrow from first field wraps to last
stdin.write('\u001B[A'); // Up arrow should wrap to field 3 (last)
await new Promise((resolve) => setTimeout(resolve, 10));
// Test passes if no errors thrown and navigation works
expect(true).toBe(true);
});
it('should handle non-circular navigation with stacked select fields', async () => {
const stackedSelectFields = [
{ name: 'field1', label: 'Field 1', type: 'text' },
{
name: 'priority',
label: 'Priority',
type: 'select',
display: 'stacked',
options: [
{ value: 'low', label: 'Low' },
{ value: 'medium', label: 'Medium' },
{ value: 'high', label: 'High' },
],
},
{ name: 'field3', label: 'Field 3', type: 'text' },
];
const { stdin } = render(_jsx(SimpleForm, { fields: stackedSelectFields, onSubmit: mockOnSubmit, onCancel: mockOnCancel }));
// Navigate to stacked select field
stdin.write('\u001B[B'); // Go to select field
await new Promise((resolve) => setTimeout(resolve, 10));
// Navigate to last option then down should move to next field (non-circular)
stdin.write('\u001B[B'); // Go to medium option
await new Promise((resolve) => setTimeout(resolve, 10));
stdin.write('\u001B[B'); // Go to high option (last)
await new Promise((resolve) => setTimeout(resolve, 10));
stdin.write('\u001B[B'); // Should move to next field (non-circular)
await new Promise((resolve) => setTimeout(resolve, 10));
// Test passes if no errors thrown and navigation works
expect(true).toBe(true);
});
});
//# sourceMappingURL=SimpleForm.test.js.map