/*! * Copyright (c) Microsoft Corporation and contributors. All rights reserved. * Licensed under the MIT License. */ import type { 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 & { 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