"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const type_analyzer_1 = require("@previewjs/type-analyzer");
const vfs_1 = require("@previewjs/vfs");
const path_1 = __importDefault(require("path"));
const vitest_1 = require("vitest");
const _1 = require(".");
const analyze_component_1 = require("./analyze-component");
const vue_reader_1 = require("./vue-reader");
const ROOT_DIR_PATH = path_1.default.join(__dirname, "virtual");
const MAIN_FILE = path_1.default.join(ROOT_DIR_PATH, "App.vue");
(0, vitest_1.describe)("analyze Vue 2 component", () => {
    let memoryReader;
    let typeAnalyzer;
    let frameworkPlugin;
    (0, vitest_1.beforeEach)(async () => {
        memoryReader = (0, vfs_1.createMemoryReader)();
        frameworkPlugin = await _1.vue2FrameworkPlugin.create();
        typeAnalyzer = (0, type_analyzer_1.createTypeAnalyzer)({
            rootDirPath: ROOT_DIR_PATH,
            reader: (0, vue_reader_1.createVueTypeScriptReader)((0, vfs_1.createStackedReader)([
                memoryReader,
                (0, vfs_1.createFileSystemReader)({
                    watch: false,
                }),
                (0, vfs_1.createFileSystemReader)({
                    mapping: {
                        from: path_1.default.join(__dirname, "..", "preview", "modules"),
                        to: path_1.default.join(ROOT_DIR_PATH, "node_modules"),
                    },
                    watch: false,
                }),
            ])),
            tsCompilerOptions: frameworkPlugin.tsCompilerOptions,
        });
    });
    (0, vitest_1.afterEach)(() => {
        typeAnalyzer.dispose();
    });
    (0, vitest_1.test)("export default {} without props", async () => {
        (0, vitest_1.expect)(await analyze(`
<template>
  <div>{{ label }}</div>
</template>
<script>
export default {
  name: "App"
}
</script>
`)).toEqual({
            propsType: (0, type_analyzer_1.objectType)({}),
            types: {},
        });
    });
    (0, vitest_1.test)("export default {} with object props", async () => {
        (0, vitest_1.expect)(await analyze(`
<template>
  <div>{{ label }}</div>
</template>
<script>
export default {
  
  props: {
    a: String,
    b: { type: String },
    c: { type: String, default: "foo" },
    d: { type: String, required: true },
    e: { type: String, default: "foo", required: false },
    f: [String, Number],
    g: { type: [String, Number], default: "foo" },
    h: { type: [String, Number], required: true },
    i: { type: [String, Number], default: "foo", required: false },
  }
}
</script>
`)).toEqual({
            propsType: (0, type_analyzer_1.objectType)({
                a: (0, type_analyzer_1.optionalType)(type_analyzer_1.STRING_TYPE),
                b: (0, type_analyzer_1.optionalType)(type_analyzer_1.STRING_TYPE),
                c: (0, type_analyzer_1.optionalType)(type_analyzer_1.STRING_TYPE),
                d: type_analyzer_1.STRING_TYPE,
                e: (0, type_analyzer_1.optionalType)(type_analyzer_1.STRING_TYPE),
                f: (0, type_analyzer_1.optionalType)((0, type_analyzer_1.unionType)([type_analyzer_1.STRING_TYPE, type_analyzer_1.NUMBER_TYPE])),
                g: (0, type_analyzer_1.optionalType)((0, type_analyzer_1.unionType)([type_analyzer_1.STRING_TYPE, type_analyzer_1.NUMBER_TYPE])),
                h: (0, type_analyzer_1.unionType)([type_analyzer_1.STRING_TYPE, type_analyzer_1.NUMBER_TYPE]),
                i: (0, type_analyzer_1.optionalType)((0, type_analyzer_1.unionType)([type_analyzer_1.STRING_TYPE, type_analyzer_1.NUMBER_TYPE])),
            }),
            types: {},
        });
    });
    (0, vitest_1.test)("export default {} with array props", async () => {
        (0, vitest_1.expect)(await analyze(`
<template>
  <div>{{ label }}</div>
</template>
<script>
export default {
  
  props: ["a", "b", "c"]
}
</script>
`)).toEqual({
            propsType: (0, type_analyzer_1.objectType)({
                a: type_analyzer_1.UNKNOWN_TYPE,
                b: type_analyzer_1.UNKNOWN_TYPE,
                c: type_analyzer_1.UNKNOWN_TYPE,
            }),
            types: {},
        });
    });
    (0, vitest_1.test)("export default class with vue-property-decorator", async () => {
        (0, vitest_1.expect)(await analyze(`
<template>
  <div :class="\`size-\${size}\`">{{ label }}</div>
</template>
<script>
import Vue from 'vue';
import Component from 'vue-class-component';
import { Prop } from 'vue-property-decorator';

type Size = "default" | "small" | "big";

@Component
export default class App extends Vue {
  @Prop({ type: String, required: true }) readonly label;
  @Prop({ type: String, default: 'default' }) readonly size!: Size;
}
</script>
`)).toEqual({
            propsType: (0, type_analyzer_1.objectType)({
                label: type_analyzer_1.STRING_TYPE,
                size: (0, type_analyzer_1.optionalType)((0, type_analyzer_1.unionType)([
                    (0, type_analyzer_1.literalType)("default"),
                    (0, type_analyzer_1.literalType)("small"),
                    (0, type_analyzer_1.literalType)("big"),
                ])),
            }),
            types: {},
        });
    });
    async function analyze(source) {
        memoryReader.updateFile(MAIN_FILE, source);
        return (0, analyze_component_1.analyzeVueComponentFromTemplate)(typeAnalyzer, MAIN_FILE);
    }
});
