/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
import { strict as assert } from "node:assert";
import { defaultMinVersionForCollab, } from "@fluidframework/runtime-utils/internal";
import { createMockLoggerExt, } from "@fluidframework/telemetry-utils/internal";
import { lt } from "semver-ts";
import { pkgVersion } from "../packageVersion.js";
import { DocumentsSchemaController, } from "../summary/index.js";
function boolToProp(b) {
    return b === true ? true : undefined;
}
function arrayToProp(arr) {
    return arr.length === 0 ? undefined : arr;
}
describe("Runtime", () => {
    let logger;
    beforeEach(() => {
        logger = createMockLoggerExt();
    });
    const validConfig = {
        version: 1,
        refSeq: 0,
        info: { minVersionForCollab: defaultMinVersionForCollab },
        runtime: {
            // explicitSchemaControl: undefined,
            compressionLz4: true,
            idCompressorMode: "delayed",
            // opGroupingEnabled: undefined,
            // createBlobPayloadPending: true,
        },
    };
    const features = {
        explicitSchemaControl: true,
        compressionLz4: true,
        opGroupingEnabled: false,
        idCompressorMode: "delayed",
        createBlobPayloadPending: undefined,
        disallowedVersions: [],
    };
    function createController(config) {
        return new DocumentsSchemaController(true, // existing,
        0, // snapshotSequenceNumber
        config, // old schema,
        features, () => { }, // onSchemaChange
        { minVersionForCollab: defaultMinVersionForCollab }, // info,
        logger, false);
    }
    function testWrongConfig(config) {
        assert.throws(() => {
            createController(config);
        }, "should throw on unknown property");
        const controller = createController(validConfig);
        assert.throws(() => controller.processDocumentSchemaMessages([config], false, // local
        100)); // sequenceNumber
    }
    // Validate first that config is indeed valid, such that all further tests are not tripping
    // on something else that they are not modifying.
    it("valid config", () => {
        createController(validConfig);
    });
    // It's hard to say if we will allow additional propeorty trees here like this sample shows.
    // More likely that will require version bump, to ensure that old code does not run with such structure.
    // If if such configs will be backward compatible (similar to runtime options we are listing that were in use for very long time),
    // then maybe ability to add them in such back-compat way is a plus
    it("extra global property ois Ok", () => {
        createController({
            ...validConfig,
            appProperty: { foo: 5 },
        });
    });
    it("empty object", () => {
        testWrongConfig({});
    });
    it("wrong version", () => {
        testWrongConfig({ ...validConfig, version: 4 });
        testWrongConfig({ ...validConfig, version: "1" });
        testWrongConfig({ ...validConfig, version: "2.0" });
    });
    it("wrong refSeq", () => {
        testWrongConfig({ ...validConfig, refSeq: "aaa" });
    });
    it("no refSeq", () => {
        testWrongConfig({ ...validConfig, refSeq: undefined });
    });
    it("no runtime", () => {
        testWrongConfig({
            ...validConfig,
            runtime: undefined,
        });
    });
    it("unknown runtime property", () => {
        testWrongConfig({ ...validConfig, runtime: { ...validConfig.runtime, foo: 5 } });
    });
    it("disallowed versions", () => {
        const controller = new DocumentsSchemaController(true, // existing,
        0, // snapshotSequenceNumber
        validConfig, // old schema,
        { ...features, disallowedVersions: [] }, () => { }, // onSchemaChange
        { minVersionForCollab: defaultMinVersionForCollab }, // info,
        logger, false);
        assert(controller.sessionSchema.runtime.disallowedVersions === undefined);
        assert(controller.maybeGenerateSchemaMessage() === undefined);
        createController({
            ...validConfig,
            runtime: { ...validConfig.runtime, disallowedVersions: ["aaa"] },
        });
        testWrongConfig({
            ...validConfig,
            runtime: { ...validConfig.runtime, disallowedVersions: [pkgVersion] },
        });
        testWrongConfig({
            ...validConfig,
            runtime: { ...validConfig.runtime, disallowedVersions: ["aaa", pkgVersion, "bbb"] },
        });
    });
    it("change disallowed versions", () => {
        const controller = new DocumentsSchemaController(true, // existing,
        0, // snapshotSequenceNumber
        // old schema
        {
            ...validConfig,
            runtime: { ...validConfig.runtime, explicitSchemaControl: true },
        }, 
        // features requested
        {
            ...features,
            disallowedVersions: ["aaa", "bbb"],
        }, 
        // onSchemaChange
        () => { }, { minVersionForCollab: defaultMinVersionForCollab }, // info,
        logger, false);
        assert.deepEqual(controller.sessionSchema.runtime.disallowedVersions, ["aaa", "bbb"]);
        let message = controller.maybeGenerateSchemaMessage();
        assert(message !== undefined);
        controller.processDocumentSchemaMessages([message], true /* local */, 100 /* sequenceNumber */);
        assert.deepEqual(controller.sessionSchema.runtime.disallowedVersions, ["aaa", "bbb"]);
        // Some runtime that drops one version, and adds another version to disallowed list
        const controller2 = new DocumentsSchemaController(true, // existing,
        300, // snapshotSequenceNumber
        // old schema
        controller.summarizeDocumentSchema(300), 
        // features requested
        {
            ...features,
            disallowedVersions: ["ccc", "aaa"],
        }, 
        // onSchemaChange
        () => { }, { minVersionForCollab: defaultMinVersionForCollab }, // info,
        logger, false);
        assert.deepEqual(controller2.sessionSchema.runtime.disallowedVersions, [
            "aaa",
            "bbb",
            "ccc",
        ]);
        message = controller2.maybeGenerateSchemaMessage();
        assert(message !== undefined);
        controller2.processDocumentSchemaMessages([message], true /* local */, 400 /* sequenceNumber */);
        assert.deepEqual(controller2.sessionSchema.runtime.disallowedVersions, [
            "aaa",
            "bbb",
            "ccc",
        ]);
        // Some runtime that only processes document schema op
        const controller3 = new DocumentsSchemaController(true, // existing,
        500, // snapshotSequenceNumber
        // old schema
        controller.summarizeDocumentSchema(500), features, 
        // onSchemaChange
        () => { }, { minVersionForCollab: defaultMinVersionForCollab }, // info,
        logger, false);
        controller3.processDocumentSchemaMessages([message], true /* local */, 600 /* sequenceNumber */);
        assert.deepEqual(controller3.sessionSchema.runtime.disallowedVersions, [
            "aaa",
            "bbb",
            "ccc",
        ]);
    });
    it("wrong values for known properties", () => {
        testWrongConfig({
            ...validConfig,
            runtime: { ...validConfig.runtime, idCompressorMode: 5 },
        });
        testWrongConfig({
            ...validConfig,
            runtime: { ...validConfig.runtime, idCompressorMode: "foo" },
        });
        testWrongConfig({
            ...validConfig,
            runtime: { ...validConfig.runtime, opGroupingEnabled: false },
        });
        testWrongConfig({
            ...validConfig,
            runtime: { ...validConfig.runtime, opGroupingEnabled: "aa" },
        });
    });
    function testSimpleCases(explicitSchemaControl, existing) {
        const featuresModified = { ...features, explicitSchemaControl };
        const controller = new DocumentsSchemaController(existing, // existing,
        0, // snapshotSequenceNumber
        undefined, // old schema,
        featuresModified, () => assert(false, "no schema changes!"), // onSchemaChange
        { minVersionForCollab: defaultMinVersionForCollab }, // info,
        logger, false);
        assert(controller.sessionSchema.refSeq === 0, "refSeq");
        assert(controller.sessionSchema.version === 1, "version");
        assert(controller.sessionSchema.runtime.explicitSchemaControl ===
            boolToProp(explicitSchemaControl), "explicitSchemaControl");
        if (existing && explicitSchemaControl) {
            assert(controller.sessionSchema.runtime.compressionLz4 === undefined, "lz4");
            assert(controller.sessionSchema.runtime.idCompressorMode === undefined, "idCompressorMode");
        }
        else {
            assert(controller.sessionSchema.runtime.compressionLz4 === true, "lz4");
            assert(controller.sessionSchema.runtime.idCompressorMode === "delayed", "idCompressorMode");
        }
        assert(controller.sessionSchema.runtime.opGroupingEnabled === undefined, "opGroupingEnabled");
        if (!existing || !explicitSchemaControl) {
            controller.pendingOpNotAcked();
            assert(controller.maybeGenerateSchemaMessage() === undefined, "no messages should be sent!");
        }
        // get rid of all properties with undefined values.
        const summarySchema = JSON.parse(JSON.stringify(controller.summarizeDocumentSchema(100 /* refSeq */)));
        if (!explicitSchemaControl) {
            assert.deepEqual(summarySchema, validConfig, "summarized schema as expected");
        }
        else if (existing) {
            const expected = {
                version: 1,
                refSeq: 0,
                info: { minVersionForCollab: defaultMinVersionForCollab },
                runtime: {
                    // Existing files without any schema are considered to be in legacy mode.
                    explicitSchemaControl: undefined,
                },
            };
            assert.deepEqual(summarySchema, JSON.parse(JSON.stringify(expected)), "summarized schema as expected");
        }
        else {
            const expected = {
                version: 1,
                refSeq: 0,
                info: { minVersionForCollab: defaultMinVersionForCollab },
                runtime: {
                    explicitSchemaControl: boolToProp(featuresModified.explicitSchemaControl),
                    compressionLz4: boolToProp(featuresModified.compressionLz4),
                    idCompressorMode: featuresModified.idCompressorMode,
                    opGroupingEnabled: boolToProp(featuresModified.opGroupingEnabled),
                    createBlobPayloadPending: featuresModified.createBlobPayloadPending,
                    disallowedVersions: arrayToProp(featuresModified.disallowedVersions),
                },
            };
            assert.deepEqual(summarySchema, JSON.parse(JSON.stringify(expected)), "summarized schema as expected");
        }
        // No local messages are expected
        assert.throws(() => controller.processDocumentSchemaMessages([validConfig], true, // local
        100)); // sequenceNumber
    }
    it("Creation of new document", () => {
        testSimpleCases(true, // explicitSchemaControl
        false);
        testSimpleCases(false, // explicitSchemaControl
        false);
    });
    it("Existing document, no schema", () => {
        testSimpleCases(true, // explicitSchemaControl
        true);
        testSimpleCases(false, // explicitSchemaControl
        true);
    });
    function testExistingDocNoChangesInSchema(schema) {
        const controller = new DocumentsSchemaController(true, // existing,
        0, // snapshotSequenceNumber
        schema, // old schema,
        features, () => { }, // onSchemaChange
        schema.info ?? { minVersionForCollab: defaultMinVersionForCollab }, // info,
        logger, false);
        controller.pendingOpNotAcked();
        assert(controller.maybeGenerateSchemaMessage() === undefined, "no messages should be sent!");
    }
    it("Existing document with existing schema, no changes", () => {
        testExistingDocNoChangesInSchema(validConfig);
        testExistingDocNoChangesInSchema({
            ...validConfig,
            runtime: { ...validConfig.runtime, explicitSchemaControl: true },
        });
        testExistingDocNoChangesInSchema({
            ...validConfig,
            // Should not change schema since it is lower than the existing minVersionForCollab
            info: { minVersionForCollab: "1.0.0" },
        });
    });
    it("New DocumentSchemaController will produce schema update message when the initial schema's info property is undefined", () => {
        testMinVersionForCollabUpdateProcess({
            initialSchema: {
                version: validConfig.version,
                refSeq: validConfig.refSeq,
                runtime: validConfig.runtime,
            },
            newMinVersionForCollab: "2.20.0",
            expectedFinalMinVersionForCollab: "2.20.0",
            expectSchemaChangeMessage: true,
        });
    });
    it("New DocumentSchemaController will produce schema update message when the provided minVersionForCollab is higher than the initial schema's default minVersionForCollab", () => {
        testMinVersionForCollabUpdateProcess({
            initialSchema: validConfig,
            newMinVersionForCollab: "2.20.0",
            expectedFinalMinVersionForCollab: "2.20.0",
            expectSchemaChangeMessage: true,
        });
    });
    it("New DocumentSchemaController will produce schema update message when the provided minVersionForCollab is higher than the initial schema's non-default minVersionForCollab", () => {
        testMinVersionForCollabUpdateProcess({
            initialSchema: {
                version: validConfig.version,
                refSeq: validConfig.refSeq,
                runtime: validConfig.runtime,
                info: { minVersionForCollab: "2.20.0" },
            },
            newMinVersionForCollab: "2.30.0",
            expectedFinalMinVersionForCollab: "2.30.0",
            expectSchemaChangeMessage: true,
        });
    });
    it("New DocumentSchemaController will NOT produce schema update message when the provided minVersionForCollab is lower than the initial schema's minVersionForCollab", () => {
        // It should stay at 2.20.0 since 2.0.0 is lower than the existing minVersionForCollab (2.20.0)
        testMinVersionForCollabUpdateProcess({
            initialSchema: {
                version: validConfig.version,
                refSeq: validConfig.refSeq,
                runtime: validConfig.runtime,
                info: { minVersionForCollab: "2.20.0" },
            },
            newMinVersionForCollab: "2.0.0",
            expectedFinalMinVersionForCollab: "2.20.0",
            expectSchemaChangeMessage: false,
        });
    });
    it("New DocumentSchemaController will NOT produce schema update message when the provided minVersionForCollab is equal to the initial schema's minVersionForCollab", () => {
        // It should stay at 2.20.0 since 2.0.0 is lower than the existing minVersionForCollab (2.20.0)
        testMinVersionForCollabUpdateProcess({
            initialSchema: {
                version: validConfig.version,
                refSeq: validConfig.refSeq,
                runtime: validConfig.runtime,
                info: { minVersionForCollab: "2.20.0" },
            },
            newMinVersionForCollab: "2.20.0",
            expectedFinalMinVersionForCollab: "2.20.0",
            expectSchemaChangeMessage: false,
        });
    });
    it("Existing document, changes required; race conditions", () => {
        const controller = new DocumentsSchemaController(true, // existing,
        0, // snapshotSequenceNumber
        validConfig, // old schema,
        { ...features, opGroupingEnabled: true }, () => { }, // onSchemaChange
        { minVersionForCollab: defaultMinVersionForCollab }, // info
        logger, false);
        const message = controller.maybeGenerateSchemaMessage();
        assert(message !== undefined);
        assert(message.runtime.opGroupingEnabled === true);
        // Validate that client will attempt to send only one such message.
        // This is important, as otherwise we will keep sending them forever. Not only this is useless,
        // but it will also trip asserts as we will have two messages with same sequence number (due to op grouping)
        assert(controller.maybeGenerateSchemaMessage() === undefined);
        assert(controller.processDocumentSchemaMessages([message], true, // local
        200) === true);
        assert(controller.sessionSchema.runtime.opGroupingEnabled === true);
        assert(controller.sessionSchema.refSeq === 200);
        const schema = controller.summarizeDocumentSchema(300);
        assert(schema !== undefined);
        assert(schema.refSeq === 200);
        const controller2 = new DocumentsSchemaController(true, // existing,
        300, // snapshotSequenceNumber
        schema, // old schema,
        { ...features, idCompressorMode: undefined, compressionLz4: false }, () => { }, // onSchemaChange
        { minVersionForCollab: defaultMinVersionForCollab }, // info
        logger, false);
        // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access -- Accessing private property
        assert.deepEqual(controller2.documentSchema, schema);
        // updates with old refSeq should fail silently.
        assert(controller.processDocumentSchemaMessages([{ ...message, refSeq: 100 }], false, // local
        201) === false);
        // new change with some future sequence number should never happen, thus code should throw.
        assert.throws(() => {
            assert(message !== undefined);
            controller.processDocumentSchemaMessages([{ ...message, refSeq: 300 }], false, // local
            202);
        });
        // new change in schema with updated ref seq should be allowed
        assert(controller.processDocumentSchemaMessages([{ ...message, refSeq: 200 }], false, // local
        305) === true);
        // Sequence numbers should move only forward.
        assert.throws(() => {
            assert(message !== undefined);
            controller.processDocumentSchemaMessages([{ ...message, refSeq: 305 }], false, // local
            300);
        });
    });
    it("AzureClient modes", () => {
        /**
         * Start with no schema in a document.
         * There should be no ops sent.
         */
        const controller = new DocumentsSchemaController(true, // existing,
        0, // snapshotSequenceNumber
        undefined, // old schema,
        { ...features, idCompressorMode: undefined, compressionLz4: false }, () => {
            assert(false, "no changes!");
        }, // onSchemaChange
        { minVersionForCollab: defaultMinVersionForCollab }, // info
        logger, false);
        assert(controller.maybeGenerateSchemaMessage() === undefined);
        /**
         * validate that we can summarize, load new client from that summary and it also will not send any ops
         */
        const newSchema = controller.summarizeDocumentSchema(100);
        const controller2 = new DocumentsSchemaController(true, // existing,
        0, // snapshotSequenceNumber
        newSchema, // old schema,
        { ...features, idCompressorMode: undefined, compressionLz4: false }, () => {
            assert(false, "no changes!");
        }, // onSchemaChange
        { minVersionForCollab: defaultMinVersionForCollab }, // info
        logger, false);
        assert(controller2.maybeGenerateSchemaMessage() === undefined);
        /**
         * Summarize from that new client and ensure we are getting exactly same summary, thus getting to same state.
         */
        const newSchema2 = controller.summarizeDocumentSchema(100);
        assert.deepEqual(newSchema, newSchema2, "got into stable state");
        /**
         * Now let's see if we can change schema.
         */
        let schemaChanged = false;
        const controller3 = new DocumentsSchemaController(true, // existing,
        0, // snapshotSequenceNumber
        newSchema, // old schema,
        { ...features, idCompressorMode: "on", compressionLz4: false }, () => {
            schemaChanged = true;
        }, // onSchemaChange
        { minVersionForCollab: defaultMinVersionForCollab }, // info
        logger, false);
        // setting is not on yet
        assert(controller3.sessionSchema.runtime.idCompressorMode === undefined);
        const message = controller3.maybeGenerateSchemaMessage();
        assert(message !== undefined, "message sent");
        assert(message.runtime.idCompressorMode === "on");
        controller3.processDocumentSchemaMessages([message], true, // local
        100); // sequenceNumber
        assert(schemaChanged, "schema changed");
        assert(controller3.sessionSchema.runtime.idCompressorMode === "on");
        const schema = controller3.summarizeDocumentSchema(200);
        assert(schema !== undefined, "schema should be defined");
        assert(schema.runtime.idCompressorMode === "on", "now on");
        assert(controller3.maybeGenerateSchemaMessage() === undefined);
        /**
         * Validate now that another client that was observing schema changes (not initiating them) will arrive to same state
         * This client will want to flip groupedBatching, but it will process someone else op first...
         */
        schemaChanged = false;
        const controller4 = new DocumentsSchemaController(true, // existing,
        0, // snapshotSequenceNumber
        newSchema, // old schema,
        {
            ...features,
            idCompressorMode: undefined,
            compressionLz4: false,
            opGroupingEnabled: true,
        }, () => (schemaChanged = true), // onSchemaChange
        { minVersionForCollab: defaultMinVersionForCollab }, // info
        logger, false);
        controller4.processDocumentSchemaMessages([message], false, // local
        200); // sequenceNumber
        assert(schemaChanged, "schema changed");
        assert(controller4.sessionSchema.runtime.idCompressorMode === "on");
        assert(controller4.maybeGenerateSchemaMessage() === undefined, "no messages should be sent - it lost a race and will not attempt to change file format.");
        // Validate same summaries by two clients.
        const schema2 = controller3.summarizeDocumentSchema(200);
        assert.deepEqual(schema, schema2, "same summaries");
    });
    it("Does not send telemetry warning if minVersionForCollab is less than or equal to pkgVersion", () => {
        // Document's minVersionForCollab is less than pkgVersion
        const documentMinVersionForCollab = "2.0.0";
        new DocumentsSchemaController(true, // existing,
        0, // snapshotSequenceNumber
        { ...validConfig, info: { minVersionForCollab: documentMinVersionForCollab } }, // old schema,
        features, // features
        () => { }, // onSchemaChange
        { minVersionForCollab: defaultMinVersionForCollab }, // info
        logger, false);
        const event = logger.events().find((e) => e.eventName === "MinVersionForCollabWarning");
        assert.strictEqual(event, undefined, "telemetry warning event should not be logged");
        // Document's minVersionForCollab is equal to pkgVersion
        new DocumentsSchemaController(true, // existing,
        0, // snapshotSequenceNumber
        { ...validConfig, info: { minVersionForCollab: pkgVersion } }, // old schema,
        features, // features
        () => { }, // onSchemaChange
        { minVersionForCollab: defaultMinVersionForCollab }, // info
        logger, false);
        const event2 = logger.events().find((e) => e.eventName === "MinVersionForCollabWarning");
        assert.strictEqual(event2, undefined, "telemetry warning event should not be logged");
    });
    it("Sends telemetry warning if minVersionForCollab is greater than pkgVersion", () => {
        const documentMinVersionForCollab = "100.0.0";
        assert(lt(pkgVersion, documentMinVersionForCollab), "pkgVersion must be less than documentMinVersionForCollab");
        new DocumentsSchemaController(true, // existing,
        0, // snapshotSequenceNumber
        { ...validConfig, info: { minVersionForCollab: documentMinVersionForCollab } }, // old schema,
        features, // features
        () => { }, // onSchemaChange
        { minVersionForCollab: documentMinVersionForCollab }, // info
        logger, false);
        const expectedEvent = {
            category: "generic",
            eventName: "MinVersionForCollabWarning",
            message: `WARNING: The version of Fluid Framework used by this client (${pkgVersion}) is not supported by this document! Please upgrade to version ${documentMinVersionForCollab} or later to ensure compatibility.`,
        };
        const event = logger.events().find((e) => e.eventName === "MinVersionForCollabWarning");
        assert.deepStrictEqual(event, expectedEvent, "telemetry warning event should be logged");
    });
    describe("disableSchemaUpgrade = true", () => {
        it("does not send schema change ops", () => {
            const controller = new DocumentsSchemaController(true, // existing
            0, // snapshotSequenceNumber
            { ...validConfig, runtime: { ...validConfig.runtime, explicitSchemaControl: true } }, { ...features, opGroupingEnabled: true }, () => { }, // onSchemaChange
            { minVersionForCollab: defaultMinVersionForCollab }, logger, true);
            assert.strictEqual(controller.maybeGenerateSchemaMessage(), undefined, "should not generate schema change message when disableSchemaUpgrade is true");
        });
        it("throws on incoming schema change ops", () => {
            const controller = new DocumentsSchemaController(true, // existing
            0, // snapshotSequenceNumber
            {
                ...validConfig,
                runtime: {
                    ...validConfig.runtime,
                    explicitSchemaControl: true,
                    opGroupingEnabled: undefined,
                },
            }, features, () => { }, // onSchemaChange
            { minVersionForCollab: defaultMinVersionForCollab }, logger, true);
            assert.throws(() => controller.processDocumentSchemaMessages([
                {
                    ...validConfig,
                    runtime: { ...validConfig.runtime, opGroupingEnabled: true },
                },
            ], false, // local
            100), "schema change op while disableSchemaUpgrade is enabled");
        });
    });
    /**
     * Helper function for testing {@link DocumentsSchemaController} instantiation with
     * an existing schema and requested `minVersionForCollab` through to update
     * generation and final result under uninterrupted action sequence.
     * After instantiation, checks that {@link DocumentsSchemaController.maybeGenerateSchemaMessage}
     * produces a message or not according to caller expectations. When a message is
     * expected and produced, a simulated "local" version of the message will be sent to
     * {@link DocumentsSchemaController.processDocumentSchemaMessages} and the call is
     * expected to succeed (return `true`).
     * Finally, `schema.info.minVersionForCollab` is checked by call to
     * {@link DocumentsSchemaController.summarizeDocumentSchema} to ensure it reflects
     * the given expected value.
     */
    function testMinVersionForCollabUpdateProcess({ initialSchema, newMinVersionForCollab, expectedFinalMinVersionForCollab, expectSchemaChangeMessage, }) {
        let schemaChangedCalled = false;
        const onSchemaChange = () => {
            schemaChangedCalled = true;
        };
        const currentSnapshotSeqNum = initialSchema.refSeq;
        const messageProcessingSeqNumIfGenerated = currentSnapshotSeqNum + 100;
        const summarySeqNum = currentSnapshotSeqNum + 200;
        const controller = new DocumentsSchemaController(true, // existing
        currentSnapshotSeqNum, // snapshotSequenceNumber
        initialSchema, features, onSchemaChange, { minVersionForCollab: newMinVersionForCollab }, logger, false);
        const message = controller.maybeGenerateSchemaMessage();
        if (expectSchemaChangeMessage) {
            assert(message !== undefined, "Schema change message should be generated");
            assert.strictEqual(message.info?.minVersionForCollab, newMinVersionForCollab, `Message should contain the target minVersionForCollab (${newMinVersionForCollab})`);
            assert(controller.processDocumentSchemaMessages([message], true, // local
            messageProcessingSeqNumIfGenerated) === true, "Processing schema message should succeed");
        }
        else {
            assert(message === undefined, "Schema change message should not be generated");
        }
        if (expectSchemaChangeMessage) {
            assert(schemaChangedCalled, "onSchemaChange should have been called");
        }
        else {
            assert(!schemaChangedCalled, "onSchemaChange should NOT have been called");
        }
        const resultingSchema = controller.summarizeDocumentSchema(summarySeqNum);
        assert(resultingSchema !== undefined, "Resulting schema should be defined");
        assert(resultingSchema.info?.minVersionForCollab !== undefined, "Resulting schema should have minVersionForCollab defined");
        assert.strictEqual(resultingSchema.info?.minVersionForCollab, expectedFinalMinVersionForCollab, `Resulting schema's minVersionForCollab should be ${expectedFinalMinVersionForCollab}, but was ${resultingSchema.info.minVersionForCollab}`);
        return resultingSchema;
    }
});
//# sourceMappingURL=documentSchema.spec.js.map