mirror of
https://github.com/zoriya/v10.git
synced 2026-08-16 02:45:09 +00:00
test(site): replace api-docs-builder design doc with E2E spec tests (#1225)
Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
+32
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Multi-part component fixture (core).
|
||||
*
|
||||
* Exercises: multi-part Props/State extraction, defaultProps merging,
|
||||
* non-boolean data-attr type inference (string union, number).
|
||||
*/
|
||||
|
||||
export type FillLevel = 'empty' | 'partial' | 'full';
|
||||
|
||||
export interface GaugeProps {
|
||||
/** Minimum value. */
|
||||
min: number;
|
||||
/** Maximum value. */
|
||||
max: number;
|
||||
/** Custom label for accessibility. */
|
||||
label: string | ((state: GaugeState) => string);
|
||||
}
|
||||
|
||||
export interface GaugeState {
|
||||
/** Current value as a percentage (0–1). */
|
||||
percentage: number;
|
||||
/** The fill level. */
|
||||
fillLevel: FillLevel;
|
||||
}
|
||||
|
||||
export class GaugeCore {
|
||||
static readonly defaultProps = {
|
||||
min: 0,
|
||||
max: 100,
|
||||
label: '',
|
||||
};
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* CSS vars fixture for multi-part component.
|
||||
*
|
||||
* Exercises: CSS custom properties on a multi-part component (assigned to primary part).
|
||||
*/
|
||||
|
||||
export const GaugeCSSVars = {
|
||||
/** The fill color of the gauge. */
|
||||
fill: '--media-gauge-fill',
|
||||
} as const;
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* Data attributes fixture for multi-part component.
|
||||
*
|
||||
* Exercises: non-boolean type inference through satisfies StateAttrMap<State>.
|
||||
* - percentage → number type (shown in output)
|
||||
* - fillLevel → string literal union (shown in output, expanded from FillLevel alias)
|
||||
*/
|
||||
|
||||
type StateAttrMap<State> = { [Key in keyof State]?: string };
|
||||
|
||||
type FillLevel = 'empty' | 'partial' | 'full';
|
||||
|
||||
interface GaugeState {
|
||||
percentage: number;
|
||||
fillLevel: FillLevel;
|
||||
}
|
||||
|
||||
export const GaugeDataAttrs = {
|
||||
/** Current percentage as a string. */
|
||||
percentage: 'data-percentage',
|
||||
/** The fill level. */
|
||||
fillLevel: 'data-fill-level',
|
||||
} as const satisfies StateAttrMap<GaugeState>;
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* NAME_OVERRIDES fixture.
|
||||
*
|
||||
* Exercises: The NAME_OVERRIDES map in pipeline.ts. The directory name is
|
||||
* "pip-button", which kebabToPascal would convert to "PipButton". But the
|
||||
* override maps it to "PiPButton" (capital P at position 2).
|
||||
*
|
||||
* This covers cases where standard kebab-to-PascalCase conversion produces
|
||||
* the wrong name. The builder uses NAME_OVERRIDES[dirName] ?? kebabToPascal(dirName).
|
||||
*/
|
||||
|
||||
export interface PiPButtonProps {
|
||||
/** Whether the button is disabled. */
|
||||
disabled: boolean;
|
||||
}
|
||||
|
||||
export interface PiPButtonState {
|
||||
/** Whether picture-in-picture is active. */
|
||||
active: boolean;
|
||||
}
|
||||
|
||||
export class PiPButtonCore {}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Base slider component (core).
|
||||
*
|
||||
* Exercises: base component whose parts get re-exported by domain variants
|
||||
* (volume-slider). This component is also discovered on its own.
|
||||
*/
|
||||
|
||||
export interface SliderProps {
|
||||
/** Minimum slider value. */
|
||||
min: number;
|
||||
/** Maximum slider value. */
|
||||
max: number;
|
||||
}
|
||||
|
||||
export interface SliderState {
|
||||
/** Current slider value (0–1). */
|
||||
value: number;
|
||||
/** Whether the user is dragging. */
|
||||
dragging: boolean;
|
||||
}
|
||||
|
||||
export class SliderCore {
|
||||
static readonly defaultProps = {
|
||||
min: 0,
|
||||
max: 100,
|
||||
};
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
/**
|
||||
* Data attributes for slider base (used by re-exported sub-parts).
|
||||
*
|
||||
* Exercises: boolean type (omitted) + non-boolean type for re-exported parts.
|
||||
*/
|
||||
|
||||
type StateAttrMap<State> = { [Key in keyof State]?: string };
|
||||
|
||||
interface SliderState {
|
||||
value: number;
|
||||
dragging: boolean;
|
||||
}
|
||||
|
||||
export const SliderDataAttrs = {
|
||||
/** The current slider value. */
|
||||
value: 'data-value',
|
||||
/** Present when the user is dragging the slider. */
|
||||
dragging: 'data-dragging',
|
||||
} as const satisfies StateAttrMap<SliderState>;
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
* Single-part component fixture.
|
||||
*
|
||||
* Exercises: Props interface, State interface, defaultProps, function-typed prop
|
||||
* (triggers type abbreviation), @ignore JSDoc (skipped prop), ref prop (auto-skipped),
|
||||
* required prop (no default, not optional).
|
||||
*/
|
||||
|
||||
export interface ToggleButtonProps {
|
||||
/** Whether the button is disabled. */
|
||||
disabled: boolean;
|
||||
/** Custom label for the button. */
|
||||
label: string | ((state: ToggleButtonState) => string);
|
||||
/** @ignore Internal ref — should be excluded from output. */
|
||||
_internalFlag: boolean;
|
||||
/** React ref — auto-skipped by the builder. */
|
||||
ref: unknown;
|
||||
/** Callback when pressed state changes. */
|
||||
onPressedChange: (pressed: boolean) => void;
|
||||
}
|
||||
|
||||
export interface ToggleButtonState {
|
||||
/** Whether the toggle is pressed. */
|
||||
pressed: boolean;
|
||||
/** Whether the button is disabled. */
|
||||
disabled: boolean;
|
||||
}
|
||||
|
||||
export class ToggleButtonCore {
|
||||
static readonly defaultProps = {
|
||||
disabled: false,
|
||||
label: '',
|
||||
};
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
/**
|
||||
* CSS vars fixture for single-part component.
|
||||
*
|
||||
* Exercises: CSS custom property extraction with JSDoc descriptions.
|
||||
*/
|
||||
|
||||
export const ToggleButtonCSSVars = {
|
||||
/** Background color when pressed. */
|
||||
pressed: '--media-toggle-pressed-bg',
|
||||
/** Transition duration for the toggle animation. */
|
||||
transition: '--media-toggle-transition',
|
||||
} as const;
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
/**
|
||||
* Data attributes fixture for single-part component.
|
||||
*
|
||||
* Exercises: boolean type inference (omitted), satisfies StateAttrMap<State> pattern.
|
||||
*/
|
||||
|
||||
type StateAttrMap<State> = { [Key in keyof State]?: string };
|
||||
|
||||
interface ToggleButtonState {
|
||||
pressed: boolean;
|
||||
disabled: boolean;
|
||||
}
|
||||
|
||||
export const ToggleButtonDataAttrs = {
|
||||
/** Present when the toggle is pressed. */
|
||||
pressed: 'data-pressed',
|
||||
/** Present when the button is disabled. */
|
||||
disabled: 'data-disabled',
|
||||
} as const satisfies StateAttrMap<ToggleButtonState>;
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* Domain variant component (core).
|
||||
*
|
||||
* Exercises: domain variant components that share base logic (slider/)
|
||||
* but have their own directory under core/ui/. The builder discovers
|
||||
* components by directory — this file must exist for volume-slider to be found.
|
||||
*/
|
||||
|
||||
export interface VolumeSliderProps {
|
||||
/** The orientation of the slider. */
|
||||
orientation: 'horizontal' | 'vertical';
|
||||
}
|
||||
|
||||
export interface VolumeSliderState {
|
||||
/** Current volume (0–1). */
|
||||
volume: number;
|
||||
}
|
||||
|
||||
export class VolumeSliderCore {
|
||||
static readonly defaultProps = {
|
||||
orientation: 'horizontal',
|
||||
};
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
/**
|
||||
* HTML element fixture for multi-part primary part.
|
||||
*
|
||||
* Exercises: primary part gets the root element's tagName.
|
||||
*/
|
||||
|
||||
export class GaugeElement {
|
||||
static readonly tagName = 'media-gauge';
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* HTML element fixture for multi-part sub-part.
|
||||
*/
|
||||
|
||||
export class GaugeFillElement {
|
||||
static readonly tagName = 'media-gauge-fill';
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
/**
|
||||
* HTML element fixture for multi-part sub-part.
|
||||
*
|
||||
* Exercises: sub-part element file naming convention ({component}-{part}-element.ts).
|
||||
*/
|
||||
|
||||
export class GaugeTrackElement {
|
||||
static readonly tagName = 'media-gauge-track';
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
export class SliderElement {
|
||||
static readonly tagName = 'media-slider';
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
export class SliderThumbElement {
|
||||
static readonly tagName = 'media-slider-thumb';
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
export class SliderTrackElement {
|
||||
static readonly tagName = 'media-slider-track';
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
/**
|
||||
* HTML element fixture for single-part component.
|
||||
*
|
||||
* Exercises: static tagName extraction for platforms.html.
|
||||
*/
|
||||
|
||||
export class ToggleButtonElement {
|
||||
static readonly tagName = 'media-toggle-button';
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
export class VolumeSliderElement {
|
||||
static readonly tagName = 'media-volume-slider';
|
||||
}
|
||||
site/scripts/api-docs-builder/src/tests/fixtures/monorepo/packages/react/src/ui/gauge/gauge-fill.tsx
Vendored
+28
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* Sub-part React component that references stateAttrMap.
|
||||
*
|
||||
* Exercises:
|
||||
* 1. Sub-part inheriting shared data-attrs from the component's data-attrs
|
||||
* file. The builder uses a string search heuristic — if the React source
|
||||
* contains "stateAttrMap", the sub-part gets shared data attributes.
|
||||
* 2. Sub-part custom React props. The builder extracts own members from the
|
||||
* `{LocalName}Props` interface (must be `interface`, not `type`).
|
||||
* `children` and React DOM attributes are excluded.
|
||||
*/
|
||||
|
||||
import type { GaugeDataAttrs } from '../../../../core/src/core/ui/gauge/gauge-data-attrs';
|
||||
|
||||
const stateAttrMap = {} as typeof GaugeDataAttrs;
|
||||
|
||||
/** The filled portion of the gauge. Renders a `<div>` element. */
|
||||
export function Fill() {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Must be `interface` (not `type`) for extractSubPartProps to detect it.
|
||||
// `children` is auto-excluded by the builder.
|
||||
export interface FillProps {
|
||||
/** The color of the fill bar. */
|
||||
color: string;
|
||||
children: unknown;
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
/**
|
||||
* Primary part React component.
|
||||
*
|
||||
* Exercises: primary part detection via `new GaugeCore` instantiation.
|
||||
* The builder checks React source files for `new {ComponentName}Core\b`.
|
||||
*/
|
||||
|
||||
class GaugeCore {}
|
||||
|
||||
/** A visual indicator for the current value. Renders a `<span>` element. */
|
||||
export function Indicator() {
|
||||
const core = new GaugeCore();
|
||||
return null;
|
||||
}
|
||||
|
||||
export type IndicatorProps = {};
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* React-only sub-part (no HTML element counterpart).
|
||||
*
|
||||
* Exercises: framework-divergent parts. Parts discovered from index.parts.ts
|
||||
* always get platforms.react. Parts WITHOUT a matching HTML element file do NOT
|
||||
* get platforms.html. This part has no gauge-label-element.ts in the HTML dir.
|
||||
*/
|
||||
|
||||
/** An accessible label for the gauge value. Renders a `<span>` element. */
|
||||
export function Label() {
|
||||
return null;
|
||||
}
|
||||
|
||||
export type LabelProps = {};
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Sub-part React component with no special behavior.
|
||||
*
|
||||
* Exercises: sub-part that has an HTML element counterpart but no data-attrs reference.
|
||||
* Gets empty props, state, dataAttributes, cssCustomProperties.
|
||||
*/
|
||||
|
||||
/** The track area of the gauge. Renders a `<div>` element. */
|
||||
export function Track() {
|
||||
return null;
|
||||
}
|
||||
|
||||
export type TrackProps = {};
|
||||
site/scripts/api-docs-builder/src/tests/fixtures/monorepo/packages/react/src/ui/gauge/index.parts.ts
Vendored
+14
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* React parts index for multi-part component.
|
||||
*
|
||||
* Exercises: multi-part detection, local exports for part discovery.
|
||||
* - Indicator: primary part (instantiates GaugeCore)
|
||||
* - Track: sub-part with HTML element
|
||||
* - Fill: sub-part with HTML element and stateAttrMap reference (gets shared data-attrs)
|
||||
* - Label: React-only part (no HTML element file)
|
||||
*/
|
||||
|
||||
export { Fill, type FillProps } from './gauge-fill';
|
||||
export { Indicator, type IndicatorProps } from './gauge-indicator';
|
||||
export { Label, type LabelProps } from './gauge-label';
|
||||
export { Track, type TrackProps } from './gauge-track';
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
/**
|
||||
* Slider base parts index.
|
||||
*
|
||||
* All local exports. volume-slider re-exports Thumb and Track from here.
|
||||
*/
|
||||
export { Root, type RootProps } from './slider-root';
|
||||
export { Thumb, type ThumbProps } from './slider-thumb';
|
||||
export { Track, type TrackProps } from './slider-track';
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Primary part of slider — instantiates SliderCore.
|
||||
*/
|
||||
|
||||
class SliderCore {}
|
||||
|
||||
/** The root slider container. Renders a `<div>` element. */
|
||||
export function Root() {
|
||||
const core = new SliderCore();
|
||||
return null;
|
||||
}
|
||||
|
||||
export type RootProps = {};
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
/**
|
||||
* Slider sub-part that references stateAttrMap.
|
||||
*
|
||||
* When volume-slider re-exports this part, data-attrs come from
|
||||
* the ORIGIN component (slider), not the consuming component (volume-slider).
|
||||
*/
|
||||
|
||||
const stateAttrMap = {};
|
||||
|
||||
/** The draggable thumb of the slider. Renders a `<div>` element. */
|
||||
export function Thumb() {
|
||||
return null;
|
||||
}
|
||||
|
||||
export type ThumbProps = {};
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
/** The track area of the slider. Renders a `<div>` element. */
|
||||
export function Track() {
|
||||
return null;
|
||||
}
|
||||
|
||||
export type TrackProps = {};
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* Volume slider parts index — re-exports from slider base.
|
||||
*
|
||||
* Exercises: re-exported parts from another component.
|
||||
* - Root: local export (primary part, instantiates VolumeSliderCore)
|
||||
* - Thumb: re-exported from slider (gets slider's HTML elements + data-attrs)
|
||||
* - Track: re-exported from slider (gets slider's HTML elements)
|
||||
*
|
||||
* Re-exported parts are NEVER primary. Their element files and data-attrs
|
||||
* are resolved from the ORIGIN component (slider), not the consumer (volume-slider).
|
||||
*
|
||||
* Because there are re-exported parts, this always produces multi-part output
|
||||
* (no single-part fallback).
|
||||
*/
|
||||
|
||||
export { Thumb, type ThumbProps, Track, type TrackProps } from '../slider/index.parts';
|
||||
export { Root, type RootProps } from './volume-slider-root';
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Primary part of volume-slider — instantiates VolumeSliderCore.
|
||||
*/
|
||||
|
||||
class VolumeSliderCore {}
|
||||
|
||||
/** The root volume slider container. Renders a `<div>` element. */
|
||||
export function Root() {
|
||||
const core = new VolumeSliderCore();
|
||||
return null;
|
||||
}
|
||||
|
||||
export type RootProps = {};
|
||||
Reference in New Issue
Block a user