/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
import { ISequencedDocumentMessage } from "@fluidframework/driver-definitions/internal";
import type { IMergeTreeOptions, InteriorSequencePlace } from "../index.js";
import type { TestClient } from "./testClient.js";
import { TestClientLogger } from "./testClientLogger.js";
declare const ClientIds: readonly ["A", "B", "C", "D"];
type ClientName = (typeof ClientIds)[number];
/**
 * Helper for authoring tests which perform operations on a number of clients.
 * This class essentially serves the role of the server in that it maintains a sequencing order of ops as well as information
 * about the latest op that each client has applied.
 *
 * When using this class, *do not* perform operations which may submit ops on clients directly: it does not currently wire up client events
 * to the server. Instead, use methods on the helper and pass the client name they should apply to as the first argument.
 *
 * It is analogous to MockContainerRuntimeFactory in the test-runtime-utils package, though the APIs are not completely equivalent
 * (see for example differences noted on disconnect and reconnect).
 *
 * This helper is also designed to support advancing only some clients to a given sequence number
 * (not all clients must be synchronized at the same time).
 *
 * This allows testing sequences of operations where clients have varying refSeqs, rather than having all clients advance refSeq
 * in lockstep.
 *
 * @remarks
 * If we wired the server up to "delta" events on the client, it would be reasonable to rename this to `MockServer` and the API for tests
 * would be a bit cleaner.
 */
export declare class ClientTestHelper {
    clients: Record<ClientName, TestClient> & {
        all: TestClient[];
    };
    idxFromName(name: ClientName): number;
    logger: TestClientLogger;
    ops: ISequencedDocumentMessage[];
    clientToLastAppliedSeq: Map<"A" | "B" | "C" | "D", number>;
    perClientOps: ISequencedDocumentMessage[][];
    private readonly disconnectedClientOps;
    private seq;
    constructor(options?: IMergeTreeOptions);
    private addMessage;
    insertText(clientName: ClientName, pos: number, text: string): void;
    removeRange(clientName: ClientName, start: number, end: number): void;
    obliterateRange(clientName: ClientName, start: number | InteriorSequencePlace, end: number | InteriorSequencePlace): void;
    advanceClientToSeq(clientName: ClientName, seq: number): void;
    /**
     * Sends all known ops to the procieded client ids.
     */
    advanceClients(...clientNames: ClientName[]): void;
    processAllOps(): void;
    /**
     * Causes the provided clients to "disconnect" by isolating their outbound queue from the op stream.
     * These clients will still receive ops from this helper just like all other clients.
     * When a client reconnects (see {@link reconnect}), the helper will rebase all of the client's pending ops (that they submitted since
     * `disconnect` was called) and re-add them to the op stream.
     *
     * BEWARE: This is slightly different from what the mocks in test-runtime-utils do in two ways:
     *
     * 1. Those mocks actually wipe outstanding ops submitted by the disconnected clients from the op stream and rebases those as well.
     * 2. Those mocks freeze the inbound queue of the disconnected clients as well as the outbound queue.
     *
     * E.g. (pseudocode; syntax is different for those mocks and these):
     *
     * ```typescript
     * B.submitLocalOp1()
     * B.submitLocalOp2()
     * disconnect(B)
     * A.submitLocalOp1()
     * B.submitLocalOp3()
     * processAllOps()
     * ```
     *
     * the test-runtime-mocks will...
     *
     * - have none of B's local ops be receieved by A in the processAllOps() line
     * - have B not receive A's local op 1
     *
     * whereas this helper will...
     *
     * - have B's local ops 1 and 2 be received by A, but not its third local op
     * - have B receive acks for its first two local ops as well as A's op in the processAllOps() line
     *
     * This operation is a no-op if called multiple times on the same client with no intervening reconnects.
     */
    disconnect(...clientNames: ClientName[]): void;
    /**
     * Reconnects clients which have been disconnected. No-ops on any client which is already connected.
     * For disconnected clients, any pending ops they have will be resubmitted using the resubmit flow, see {@link disconnect} for details and an example.
     *
     * @remarks
     * If reconnecting multiple clients, the order that their ops will be resubmitted in will match the order in the array
     */
    reconnect(...clientNames: ClientName[]): void;
    private isDisconnected;
}
export {};
//# sourceMappingURL=clientTestHelper.d.ts.map