/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
import { strict as assert } from "assert";
import { isNeverField, isNeverTree,
// Allow importing from this specific file which is being tested:
/* eslint-disable-next-line import/no-internal-modules */
 } from "../../../feature-libraries/modular-schema/isNeverTree.js";
import { storedEmptyFieldSchema, MapNodeStoredSchema, ObjectNodeStoredSchema, TreeStoredSchemaRepository, } from "../../../core/index.js";
import { brand } from "../../../util/index.js";
import { defaultSchemaPolicy, FieldKinds } from "../../../feature-libraries/index.js";
/* eslint-disable-next-line import/no-internal-modules */
import { allowsTreeSuperset } from "../../../feature-libraries/modular-schema/index.js";
/**
 * Empty readonly map.
 */
const emptyMap = new Map();
/**
 * Helper for building {@link TreeFieldStoredSchema}.
 * @internal
 */
function fieldSchema(kind, types) {
    return {
        kind,
        types: types === undefined ? undefined : new Set(types),
    };
}
describe("Schema Comparison", () => {
    /**
     * TreeFieldStoredSchema permits anything.
     * Note that children inside the field still have to be in schema.
     */
    const anyField = fieldSchema(FieldKinds.sequence);
    /**
     * TreeNodeStoredSchema that permits anything without a value.
     * Note that children under the fields still have to be in schema.
     */
    const anyTreeWithoutValue = new MapNodeStoredSchema(anyField);
    /**
     * TreeFieldStoredSchema which is impossible for any data to be in schema with.
     */
    const neverField = fieldSchema(FieldKinds.required, []);
    /**
     * TreeNodeStoredSchema which is impossible for any data to be in schema with.
     */
    const neverTree = new MapNodeStoredSchema(neverField);
    const neverTree2 = new ObjectNodeStoredSchema(new Map([[brand("x"), neverField]]));
    const emptyTree = {
        name: brand("empty"),
        schema: new ObjectNodeStoredSchema(new Map()),
    };
    const emptyLocalFieldTree = {
        name: brand("emptyLocalFieldTree"),
        schema: new ObjectNodeStoredSchema(new Map([[brand("x"), storedEmptyFieldSchema]])),
    };
    const optionalLocalFieldTree = {
        name: brand("optionalLocalFieldTree"),
        schema: new ObjectNodeStoredSchema(new Map([[brand("x"), fieldSchema(FieldKinds.optional, [emptyTree.name])]])),
    };
    const valueLocalFieldTree = {
        name: brand("valueLocalFieldTree"),
        schema: new ObjectNodeStoredSchema(new Map([[brand("x"), fieldSchema(FieldKinds.required, [emptyTree.name])]])),
    };
    const valueAnyField = fieldSchema(FieldKinds.required);
    const valueEmptyTreeField = fieldSchema(FieldKinds.required, [emptyTree.name]);
    const optionalAnyField = fieldSchema(FieldKinds.optional);
    const optionalEmptyTreeField = fieldSchema(FieldKinds.optional, [emptyTree.name]);
    function updateTreeSchema(repo, identifier, schema) {
        repo.apply({
            rootFieldSchema: repo.rootFieldSchema,
            nodeSchema: new Map([...repo.nodeSchema, [identifier, schema]]),
        });
    }
    it("isNeverField", () => {
        const repo = new TreeStoredSchemaRepository();
        assert(isNeverField(defaultSchemaPolicy, repo, neverField));
        updateTreeSchema(repo, brand("never"), neverTree);
        const neverField2 = fieldSchema(FieldKinds.required, [
            brand("never"),
        ]);
        assert(isNeverField(defaultSchemaPolicy, repo, neverField2));
        assert.equal(isNeverField(defaultSchemaPolicy, repo, storedEmptyFieldSchema), false);
        assert.equal(isNeverField(defaultSchemaPolicy, repo, anyField), false);
        assert.equal(isNeverField(defaultSchemaPolicy, repo, valueEmptyTreeField), true);
        updateTreeSchema(repo, brand("empty"), emptyTree.schema);
        assert.equal(isNeverField(defaultSchemaPolicy, repo, fieldSchema(FieldKinds.required, [brand("empty")])), false);
        assert.equal(isNeverField(defaultSchemaPolicy, repo, valueAnyField), false);
        assert.equal(isNeverField(defaultSchemaPolicy, repo, valueEmptyTreeField), false);
        assert.equal(isNeverField(defaultSchemaPolicy, repo, optionalAnyField), false);
        assert.equal(isNeverField(defaultSchemaPolicy, repo, optionalEmptyTreeField), false);
    });
    it("isNeverTree", () => {
        const repo = new TreeStoredSchemaRepository();
        assert(isNeverTree(defaultSchemaPolicy, repo, neverTree));
        assert(isNeverTree(defaultSchemaPolicy, repo, new MapNodeStoredSchema(neverField)));
        assert(isNeverTree(defaultSchemaPolicy, repo, neverTree2));
        assert(isNeverTree(defaultSchemaPolicy, repo, undefined));
        assert.equal(isNeverTree(defaultSchemaPolicy, repo, new ObjectNodeStoredSchema(emptyMap)), false);
        assert.equal(isNeverTree(defaultSchemaPolicy, repo, anyTreeWithoutValue), false);
        assert(allowsTreeSuperset(defaultSchemaPolicy, repo, repo.nodeSchema.get(emptyTree.name), emptyTree.schema));
        updateTreeSchema(repo, emptyTree.name, emptyTree.schema);
        assert.equal(isNeverTree(defaultSchemaPolicy, repo, emptyLocalFieldTree.schema), false);
        assert.equal(isNeverTree(defaultSchemaPolicy, repo, valueLocalFieldTree.schema), false);
        assert.equal(isNeverTree(defaultSchemaPolicy, repo, optionalLocalFieldTree.schema), false);
    });
    it("isNeverTreeRecursive", () => {
        const repo = new TreeStoredSchemaRepository();
        const recursiveField = fieldSchema(FieldKinds.required, [brand("recursive")]);
        const recursiveType = new MapNodeStoredSchema(recursiveField);
        updateTreeSchema(repo, brand("recursive"), recursiveType);
        assert(isNeverTree(defaultSchemaPolicy, repo, recursiveType));
    });
    it("isNeverTreeRecursive non-never", () => {
        const repo = new TreeStoredSchemaRepository();
        const recursiveField = fieldSchema(FieldKinds.required, [
            brand("recursive"),
            emptyTree.name,
        ]);
        const recursiveType = new MapNodeStoredSchema(recursiveField);
        updateTreeSchema(repo, emptyTree.name, emptyTree.schema);
        updateTreeSchema(repo, brand("recursive"), recursiveType);
        assert(isNeverTree(defaultSchemaPolicy, repo, recursiveType));
    });
});
//# sourceMappingURL=isNeverTree.spec.js.map