import { describe, it, expect } from "vitest";
// Test the Vue prop extraction patterns directly
describe("Vue Parser - extractProps", () => {
    // Helper to extract props using the same logic as vue-parser.ts
    function extractProps(content) {
        const props = [];
        // Vue 3 Composition API: defineProps<{...}>() with TypeScript generics
        const definePropsMatch = content.match(/defineProps<\{([\s\S]*?)\}>\s*\(\)/);
        if (definePropsMatch) {
            const propsContent = definePropsMatch[1];
            // Extract defaults from withDefaults if present
            const defaultsMatch = content.match(/withDefaults\s*\(\s*defineProps<[\s\S]*?>\s*\(\)\s*,\s*\{([\s\S]*?)\}\s*\)/);
            const defaultsContent = defaultsMatch ? defaultsMatch[1] : "";
            // Parse each prop with its JSDoc comment
            const propRegex = /(?:\/\*\*[\s\S]*?\*\/\s*)?(\w+)(\?)?:\s*([^;]+);/g;
            let match;
            while ((match = propRegex.exec(propsContent)) !== null) {
                const propName = match[1];
                const isOptional = !!match[2];
                const propType = match[3].trim();
                // Extract description from JSDoc comment before this prop
                const beforeProp = propsContent.substring(0, match.index);
                // Match JSDoc: /** ... */ allowing for multi-line content with * prefixes
                const jsdocMatch = beforeProp.match(/\/\*\*([\s\S]*?)\*\/\s*$/);
                let description;
                if (jsdocMatch) {
                    // Remove leading whitespace, asterisks, and collapse to single line
                    description = jsdocMatch[1]
                        .split("\n")
                        .map((line) => line.replace(/^\s*\*?\s*/, "").trim())
                        .filter((line) => line.length > 0)
                        .join(" ")
                        .trim();
                }
                // Extract default value
                const defaultMatch = defaultsContent.match(new RegExp(`${propName}\\s*:\\s*['"\`]?([^'"\`,}]+)['"\`]?`));
                const defaultValue = defaultMatch ? defaultMatch[1].trim() : undefined;
                // Extract options from union types
                let options;
                if (propType.includes("'") && propType.includes("|")) {
                    options = propType
                        .split("|")
                        .map((s) => s.trim().replace(/['"]/g, ""))
                        .filter((s) => s.length > 0);
                }
                props.push({
                    name: propName,
                    type: propType,
                    required: !isOptional,
                    defaultValue,
                    options,
                    description,
                });
            }
        }
        return props;
    }
    it("should extract props from defineProps with TypeScript generics", () => {
        const content = `
const props = defineProps<{
  size?: 's' | 'm' | 'l';
  disabled?: boolean;
}>()
`;
        const props = extractProps(content);
        expect(props).toHaveLength(2);
        expect(props[0].name).toBe("size");
        expect(props[0].required).toBe(false);
        expect(props[0].options).toEqual(["s", "m", "l"]);
        expect(props[1].name).toBe("disabled");
        expect(props[1].type).toBe("boolean");
    });
    it("should extract props with withDefaults", () => {
        const content = `
const props = withDefaults(
  defineProps<{
    appearance?: 'standard' | 'accent' | 'danger';
    size?: 's' | 'm' | 'l';
  }>(),
  {
    appearance: 'standard',
    size: 'm',
  }
)
`;
        const props = extractProps(content);
        expect(props).toHaveLength(2);
        expect(props[0].name).toBe("appearance");
        expect(props[0].defaultValue).toBe("standard");
        expect(props[0].options).toEqual(["standard", "accent", "danger"]);
        expect(props[1].name).toBe("size");
        expect(props[1].defaultValue).toBe("m");
    });
    it("should handle boolean and string types", () => {
        const content = `
const props = defineProps<{
  isLoading?: boolean;
  label: string;
  count?: number;
}>()
`;
        const props = extractProps(content);
        expect(props).toHaveLength(3);
        expect(props[0].name).toBe("isLoading");
        expect(props[0].type).toBe("boolean");
        expect(props[0].required).toBe(false);
        expect(props[1].name).toBe("label");
        expect(props[1].type).toBe("string");
        expect(props[1].required).toBe(true);
        expect(props[2].name).toBe("count");
        expect(props[2].type).toBe("number");
    });
});
describe("Vue Parser - extractSlots", () => {
    function extractSlots(content) {
        const slots = [];
        const seenSlots = new Set();
        const slotRegex = /<slot\s*(?:name=["']([^"']+)["'])?[^>]*>/g;
        let match;
        while ((match = slotRegex.exec(content)) !== null) {
            const slotName = match[1] || "default";
            if (!seenSlots.has(slotName)) {
                seenSlots.add(slotName);
                slots.push({ name: slotName });
            }
        }
        return slots;
    }
    it("should extract default slot", () => {
        const content = `<template><slot /></template>`;
        const slots = extractSlots(content);
        expect(slots).toHaveLength(1);
        expect(slots[0].name).toBe("default");
    });
    it("should extract named slots", () => {
        const content = `
<template>
  <slot name="header" />
  <slot />
  <slot name="footer" />
</template>
`;
        const slots = extractSlots(content);
        expect(slots).toHaveLength(3);
        expect(slots.map((s) => s.name)).toContain("header");
        expect(slots.map((s) => s.name)).toContain("default");
        expect(slots.map((s) => s.name)).toContain("footer");
    });
    it("should not duplicate slots", () => {
        const content = `
<template>
  <slot name="icon" />
  <slot name="icon" />
</template>
`;
        const slots = extractSlots(content);
        expect(slots).toHaveLength(1);
        expect(slots[0].name).toBe("icon");
    });
});
describe("Vue Parser - extractEvents", () => {
    function extractEvents(content) {
        const events = [];
        const seenEvents = new Set();
        // Match emit calls: emit('eventName') or $emit('eventName')
        const emitPatterns = [/emit\s*\(\s*['"]([^'"]+)['"]/g, /\$emit\s*\(\s*['"]([^'"]+)['"]/g];
        for (const pattern of emitPatterns) {
            let match;
            while ((match = pattern.exec(content)) !== null) {
                const eventName = match[1];
                if (!seenEvents.has(eventName)) {
                    seenEvents.add(eventName);
                    events.push({ name: eventName });
                }
            }
        }
        return events;
    }
    it("should extract emit events", () => {
        const content = `
const emit = defineEmits(['update', 'change'])
emit('update', value)
emit('change', newValue)
`;
        const events = extractEvents(content);
        expect(events).toHaveLength(2);
        expect(events.map((e) => e.name)).toContain("update");
        expect(events.map((e) => e.name)).toContain("change");
    });
    it("should extract $emit events from Options API", () => {
        const content = `
methods: {
  handleClick() {
    this.$emit('click', this.value)
  },
  handleChange() {
    this.$emit('input', newValue)
  }
}
`;
        const events = extractEvents(content);
        expect(events).toHaveLength(2);
        expect(events.map((e) => e.name)).toContain("click");
        expect(events.map((e) => e.name)).toContain("input");
    });
});
//# sourceMappingURL=vue-parser.test.js.map