/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
import { strict as assert } from "assert";
import { makeAnonChange, tagChange, } from "../core/index.js";
import { brand } from "../util/index.js";
import { TestChange } from "./testChange.js";
import { runExhaustiveComposeRebaseSuite } from "./rebaserAxiomaticTests.js";
import { deepFreeze, mintRevisionTag } from "./utils.js";
describe("TestChange", () => {
    it("can be composed", () => {
        const change1 = TestChange.mint([0, 1], 2);
        const change2 = TestChange.mint([0, 1, 2], 3);
        const composed = TestChange.compose(change1, change2);
        const expected = TestChange.mint([0, 1], [2, 3]);
        assert.deepEqual(composed, expected);
    });
    it("can be composed without verification", () => {
        const change1 = TestChange.mint([0], 1);
        const change2 = TestChange.mint([2], 3);
        const composed = TestChange.compose(change1, change2, false);
        const expected = TestChange.mint([0], [1, 3]);
        assert.deepEqual(composed, expected);
    });
    it("composition of inverses leads to normalized form", () => {
        const change1 = TestChange.mint([0], [1, 2]);
        const change2 = TestChange.mint([0, 1, 2], [-2, -1, 3]);
        const composed = TestChange.compose(change1, change2);
        const expected = TestChange.mint([0], [3]);
        assert.deepEqual(composed, expected);
    });
    it("can be inverted", () => {
        const change1 = TestChange.mint([0, 1], 2);
        const inverted = TestChange.invert(change1);
        const expected = TestChange.mint([0, 1, 2], -2);
        assert.deepEqual(inverted, expected);
    });
    it("can be rebased", () => {
        const change1 = TestChange.mint([0], 1);
        const change2 = TestChange.mint([0], 2);
        const rebased = TestChange.rebase(change2, change1);
        const expected = TestChange.mint([0, 1], 2);
        assert.deepEqual(rebased, expected);
    });
    it("can be represented as a delta", () => {
        const change1 = TestChange.mint([0, 1], [2, 3]);
        const tag = mintRevisionTag();
        const delta = TestChange.toDelta(tagChange(change1, tag));
        const field = brand("testIntentions");
        const expected = new Map([
            [
                field,
                {
                    local: [{ count: 2 }, { count: 3 }],
                },
            ],
        ]);
        assert.deepEqual(delta, expected);
        assert.deepEqual(TestChange.toDelta(makeAnonChange(TestChange.mint([0, 1], []))), new Map());
    });
    it("can be encoded in JSON", () => {
        const codec = TestChange.codec;
        const empty = TestChange.emptyChange;
        const context = { originatorId: "session1" };
        const normal = TestChange.mint([0, 1], [2, 3]);
        assert.deepEqual(empty, codec.decode(codec.encode(empty, context), context));
        assert.deepEqual(normal, codec.decode(codec.encode(normal, context), context));
    });
    function rebaseComposed(metadata, change, ...baseChanges) {
        baseChanges.forEach((base) => deepFreeze(base));
        deepFreeze(change);
        const composed = TestChange.composeList(baseChanges.map((c) => c.change));
        const rebaseResult = TestChange.rebase(change, composed);
        assert(rebaseResult !== undefined, "Shouldn't get undefined.");
        return rebaseResult;
    }
    /**
     * See {@link ChildStateGenerator}
     */
    const generateChildStates = function* (state, tagFromIntention, mintIntention) {
        const context = state.content;
        const intention = mintIntention();
        const change = TestChange.mint(context, intention);
        yield {
            content: change.outputContext,
            mostRecentEdit: {
                changeset: tagChange(change, tagFromIntention(intention)),
                description: JSON.stringify(intention),
                intention,
            },
            parent: state,
        };
    };
    describe("Rebaser Axioms", () => {
        describe("Exhaustive suite", () => {
            runExhaustiveComposeRebaseSuite([{ content: [] }], generateChildStates, {
                rebase: (change, base) => {
                    return TestChange.rebase(change, base.change) ?? TestChange.emptyChange;
                },
                compose: (change1, change2) => {
                    return TestChange.compose(change1.change, change2.change);
                },
                invert: (change) => {
                    return TestChange.invert(change.change);
                },
                rebaseComposed,
                createEmpty: () => TestChange.emptyChange,
            }, { numberOfEditsToRebase: 4, numberOfEditsToRebaseOver: 4 });
        });
    });
});
//# sourceMappingURL=testChange.spec.js.map