diff --git a/app/customize/components/ExportPanel.type-compiler.test.tsx b/app/customize/components/ExportPanel.type-compiler.test.tsx new file mode 100644 index 000000000..15a2b5f8e --- /dev/null +++ b/app/customize/components/ExportPanel.type-compiler.test.tsx @@ -0,0 +1,66 @@ +import { describe, it, expectTypeOf } from 'vitest'; +import type { ComponentProps } from 'react'; +import type { ExportFormat } from '../types'; +import { ExportPanel } from './ExportPanel'; + +describe('ExportPanel TypeScript compiler validation & schema constraints', () => { + it('ExportFormat accepts only "markdown" | "html" | "action" | "tsx" and rejects other literals', () => { + expectTypeOf().toEqualTypeOf<'markdown' | 'html' | 'action' | 'tsx'>(); + + // @ts-expect-error - 'pdf' is not a member of the ExportFormat union + const invalidFormat: ExportFormat = 'pdf'; + void invalidFormat; + }); + + it('onFormatChange must be typed as (format: ExportFormat) => void, rejecting an incompatible callback signature', () => { + type Props = ComponentProps; + expectTypeOf().toEqualTypeOf<(format: ExportFormat) => void>(); + + const invalidHandler: Props['onFormatChange'] = (format: string) => { + void format; + }; + void invalidHandler; + }); + + it('onCopy accepts either a sync (void) or an async (Promise) function without a compile error', () => { + type Props = ComponentProps; + expectTypeOf().toEqualTypeOf<() => void | Promise>(); + + const syncHandler: Props['onCopy'] = () => {}; + const asyncHandler: Props['onCopy'] = async () => { + await Promise.resolve(); + }; + expectTypeOf(syncHandler).toEqualTypeOf<() => void | Promise>(); + expectTypeOf(asyncHandler).toEqualTypeOf<() => void | Promise>(); + }); + + it('every ExportPanel prop is required, omitting any one is rejected at compile time', () => { + type Props = ComponentProps; + + expectTypeOf().not.toBeUndefined(); + expectTypeOf().toEqualTypeOf(); + expectTypeOf().toEqualTypeOf(); + + // @ts-expect-error - `username` is missing, which is a compile error since it's required + const incompleteProps: Props = { + format: 'markdown', + snippet: '', + copied: false, + copyStatusMessage: '', + hasUsername: true, + onFormatChange: () => {}, + onCopy: () => {}, + }; + void incompleteProps; + }); + + it('copied and hasUsername are strictly boolean, rejecting truthy/falsy stand-ins like 0, 1, or string values', () => { + type Props = ComponentProps; + expectTypeOf().toEqualTypeOf(); + expectTypeOf().toEqualTypeOf(); + + // @ts-expect-error - 1 is a number, not assignable to boolean + const invalidCopied: Props['copied'] = 1; + void invalidCopied; + }); +});