import {
  AddColumnsRowsCommand,
  CarouselData,
  CreateChartCommand,
  FreezeColumnsCommand,
  FreezeRowsCommand,
  RemoveColumnsRowsCommand,
  ResizeColumnsRowsCommand,
  UpdateChartCommand,
  UpdateTableCommand,
} from "../../../src";
import { transform } from "../../../src/collaborative/ot/ot";
import { toZone } from "../../../src/helpers/zones";
import { BarChartDefinition } from "../../../src/types/chart/bar_chart";
import { toChartDataSource } from "../../test_helpers/chart_helpers";
import {
  OT_TESTS_HEADER_GROUP_COMMANDS,
  OT_TESTS_SINGLE_CELL_COMMANDS,
  TEST_COMMANDS,
  TEST_COMMANDS_RANGE_DEPENDENT,
  TEST_COMMANDS_TARGET_DEPENDENT,
  TEST_COMMANDS_ZONE_DEPENDENT,
} from "../../test_helpers/constants";
import { target, toRangeData, toRangesData } from "../../test_helpers/helpers";
import { getFormulaStringCommands } from "./ot_helper";

describe("OT with ADD_COLUMNS_ROWS with dimension ROW", () => {
  const sheetId = "Sheet1";
  const addRowsAfter: AddColumnsRowsCommand = {
    type: "ADD_COLUMNS_ROWS",
    dimension: "ROW",
    position: "after",
    base: 5,
    quantity: 2,
    sheetId,
    sheetName: "",
  };
  const addRowsBefore: AddColumnsRowsCommand = {
    type: "ADD_COLUMNS_ROWS",
    dimension: "ROW",
    position: "before",
    base: 10,
    quantity: 2,
    sheetId,
    sheetName: "",
  };
  describe.each(OT_TESTS_SINGLE_CELL_COMMANDS)(
    "OT with ADD_COLUMNS_ROW with dimension ROW",
    (cmd) => {
      test(`${cmd.type} before added rows`, () => {
        const command = { ...cmd, sheetId, row: 1 };
        const result = transform(command, addRowsAfter);
        expect(result).toEqual(command);
      });
      test(`${cmd.type} after added rows`, () => {
        const command = { ...cmd, sheetId, row: 10 };
        const result = transform(command, addRowsAfter);
        expect(result).toEqual({ ...command, row: 12 });
      });
      test(`${cmd.type} in pivot row with rows added before`, () => {
        const command = { ...cmd, sheetId, row: 10 };
        const result = transform(command, addRowsBefore);
        expect(result).toEqual({ ...command, row: 12 });
      });
      test(`${cmd.type} in pivot row with rows added after`, () => {
        const command = { ...cmd, sheetId, row: 5 };
        const result = transform(command, addRowsAfter);
        expect(result).toEqual(command);
      });
      test(`${cmd.type} after added rows, in another sheet`, () => {
        const command = { ...cmd, row: 10, sheetId: "42" };
        const result = transform(command, addRowsAfter);
        expect(result).toEqual(command);
      });
    }
  );

  describe.each(TEST_COMMANDS_TARGET_DEPENDENT)("target commands", (cmd) => {
    test(`add rows after ${cmd.type}`, () => {
      const command = { ...cmd, sheetId, target: [toZone("A1:C1")] };
      const result = transform(command, addRowsAfter);
      expect(result).toEqual(command);
    });
    test(`add rows before ${cmd.type}`, () => {
      const command = { ...cmd, sheetId, target: [toZone("A10:B11")] };
      const result = transform(command, addRowsAfter);
      expect(result).toEqual({ ...command, target: [toZone("A12:B13")] });
    });
    test(`add rows in ${cmd.type}`, () => {
      const command = { ...cmd, sheetId, target: [toZone("A1:B10")] };
      const result = transform(command, addRowsAfter);
      expect(result).toEqual({ ...command, target: [toZone("A1:B12")] });
    });
    test(`${cmd.type} and rows added in different sheets`, () => {
      const command = { ...cmd, target: [toZone("A1:F3")], sheetId: "42" };
      const result = transform(command, addRowsAfter);
      expect(result).toEqual(command);
    });
    test(`${cmd.type} with two targets, one before and one after`, () => {
      const command = { ...cmd, sheetId, target: [toZone("A1:C1"), toZone("A10:B11")] };
      const result = transform(command, addRowsAfter);
      expect(result).toEqual({ ...command, target: [toZone("A1:C1"), toZone("A12:B13")] });
    });
  });

  describe.each(TEST_COMMANDS_ZONE_DEPENDENT)("zone dependant commands", (cmd) => {
    test(`add rows after ${cmd.type}`, () => {
      const command = { ...cmd, sheetId, zone: toZone("A1:C1") };
      const result = transform(command, addRowsAfter);
      expect(result).toEqual(command);
    });
    test(`add rows before ${cmd.type}`, () => {
      const command = { ...cmd, sheetId, zone: toZone("A10:B11") };
      const result = transform(command, addRowsAfter);
      expect(result).toEqual({ ...command, zone: toZone("A12:B13") });
    });
    test(`add rows in ${cmd.type}`, () => {
      const command = { ...cmd, sheetId, zone: toZone("A1:B12") };
      const result = transform(command, addRowsAfter);
      expect(result).toEqual({ ...command, zone: toZone("A1:B14") });
    });
    test(`${cmd.type} and rows added in different sheets`, () => {
      const command = { ...cmd, zone: toZone("A1:F3"), sheetId: "42" };
      const result = transform(command, addRowsAfter);
      expect(result).toEqual(command);
    });
  });

  describe.each(TEST_COMMANDS_RANGE_DEPENDENT)("Range dependant commands", (cmd) => {
    test(`add rows after ${cmd.type}`, () => {
      const command = { ...cmd, sheetId, ranges: toRangesData(sheetId, "A1:C1") };
      const result = transform(command, addRowsAfter);
      expect(result).toEqual(command);
    });
    test(`add rows before ${cmd.type}`, () => {
      const command = { ...cmd, sheetId, ranges: toRangesData(sheetId, "A10:B11") };
      const result = transform(command, addRowsAfter);
      expect(result).toEqual({ ...command, ranges: toRangesData(sheetId, "A12:B13") });
    });
    test(`add rows before in the sheet of the range ${cmd.type}`, () => {
      const command = {
        ...cmd,
        ranges: toRangesData(sheetId, "A10:B11"),
        sheetId: "42",
      };
      const result = transform(command, addRowsAfter);
      expect(result).toEqual({ ...command, ranges: toRangesData(sheetId, "A12:B13") });
    });
    test(`add rows after in ${cmd.type}`, () => {
      const command = { ...cmd, sheetId, ranges: toRangesData(sheetId, "A5:B6") };
      const result = transform(command, addRowsAfter);
      expect(result).toEqual({ ...command, ranges: toRangesData(sheetId, "A5:B6") });
    });
    test(`add rows before in ${cmd.type}`, () => {
      const command = { ...cmd, sheetId, ranges: toRangesData(sheetId, "A5:B6") };
      const result = transform(command, addRowsBefore);
      expect(result).toEqual({ ...command, ranges: toRangesData(sheetId, "A5:B6") });
    });
    test(`${cmd.type} and rows added in different sheets`, () => {
      const command = {
        ...cmd,
        ranges: toRangesData(sheetId, "A1:F3"),
        sheetId: "42",
      };
      const result = transform(command, addRowsAfter);
      expect(result).toEqual(command);
    });
    test(`${cmd.type} with two targets, one before and one after`, () => {
      const command = { ...cmd, sheetId, ranges: toRangesData(sheetId, "A1:C1,A10:B11") };
      const result = transform(command, addRowsAfter);
      expect(result).toEqual({ ...command, ranges: toRangesData(sheetId, "A1:C1,A12:B13") });
    });

    describe("With unbounded zones", () => {
      test(`add rows after ${cmd.type}`, () => {
        const command = { ...cmd, sheetId, ranges: toRangesData(sheetId, "1:1") };
        const result = transform(command, addRowsAfter);
        expect(result).toEqual(command);
      });
      test(`add rows before ${cmd.type}`, () => {
        const command = { ...cmd, sheetId, ranges: toRangesData(sheetId, "A10:11") };
        const result = transform(command, addRowsAfter);
        expect(result).toEqual({ ...command, ranges: toRangesData(sheetId, "A12:13") });
      });
      test(`add rows in ${cmd.type}`, () => {
        const command = { ...cmd, sheetId, ranges: toRangesData(sheetId, "5:8") };
        const result = transform(command, addRowsAfter);
        expect(result).toEqual({ ...command, ranges: toRangesData(sheetId, "5:10") });
      });
    });
  });

  const resizeRowsCommand: Omit<ResizeColumnsRowsCommand, "elements"> = {
    type: "RESIZE_COLUMNS_ROWS",
    dimension: "ROW",
    sheetId,
    size: 10,
  };

  const removeRowsCommands: Omit<RemoveColumnsRowsCommand, "elements"> = {
    type: "REMOVE_COLUMNS_ROWS",
    dimension: "ROW",
    sheetId,
    sheetName: "",
  };

  describe.each([resizeRowsCommand, removeRowsCommands])("delete or resize rows", (toTransform) => {
    test(`${toTransform.type} which are positioned before the added rows`, () => {
      const command = { ...toTransform, elements: [1, 2] };
      const result = transform(command, addRowsAfter);
      expect(result).toEqual(command);
    });

    test(`${toTransform.type} which are positioned before AND after the added rows`, () => {
      const command = { ...toTransform, elements: [1, 10] };
      const result = transform(command, addRowsAfter);
      expect(result).toEqual({ ...command, elements: [1, 12] });
    });

    test(`${toTransform.type} which is the row on which the added command is triggered, with before position`, () => {
      const command = { ...toTransform, elements: [10] };
      const result = transform(command, addRowsBefore);
      expect(result).toEqual({ ...command, elements: [12] });
    });

    test(`${toTransform.type} which is the row on which the added command is triggered, with after position`, () => {
      const command = { ...toTransform, elements: [5] };
      const result = transform(command, addRowsAfter);
      expect(result).toEqual(command);
    });

    test(`${toTransform.type} in another sheet`, () => {
      const command = { ...toTransform, elements: [1, 10], sheetId: "coucou" };
      const result = transform(command, addRowsAfter);
      expect(result).toEqual(command);
    });
  });

  describe.each([TEST_COMMANDS.ADD_MERGE, TEST_COMMANDS.REMOVE_MERGE])("merge", (cmd) => {
    test(`add rows before merge`, () => {
      const command = { ...cmd, sheetId, target: target("A1:C1") };
      const result = transform(command, addRowsAfter);
      expect(result).toEqual(command);
    });
    test(`add rows after merge`, () => {
      const command = { ...cmd, sheetId, target: target("A10:B11") };
      const result = transform(command, addRowsAfter);
      expect(result).toEqual({ ...command, target: target("A12:B13") });
    });
    test(`add rows in merge`, () => {
      const command = { ...cmd, sheetId, target: target("A5:B7") };
      const result = transform(command, addRowsAfter);
      expect(result).toEqual({ ...command, target: target("A5:B9") });
    });
    test(`merge and rows added in different sheets`, () => {
      const command = { ...cmd, target: target("A1:F3"), sheetId: "42" };
      const result = transform(command, addRowsAfter);
      expect(result).toEqual(command);
    });
  });

  describe("ADD_COLUMNS_ROWS with dimension ROW & ADD_COLUMNS_ROWS with dimension ROW", () => {
    test("same base row, one after, one before", () => {
      const addRowsAfter: AddColumnsRowsCommand = {
        type: "ADD_COLUMNS_ROWS",
        dimension: "ROW",
        position: "after",
        base: 5,
        quantity: 2,
        sheetId,
        sheetName: "",
      };
      const addRowsBefore: AddColumnsRowsCommand = {
        type: "ADD_COLUMNS_ROWS",
        dimension: "ROW",
        position: "before",
        base: 5,
        quantity: 2,
        sheetId,
        sheetName: "",
      };
      const result = transform(addRowsBefore, addRowsAfter);
      expect(result).toEqual(addRowsBefore);
    });
    test("same base row, one before, one after", () => {
      const addRowsAfter: AddColumnsRowsCommand = {
        type: "ADD_COLUMNS_ROWS",
        dimension: "ROW",
        position: "after",
        base: 5,
        quantity: 2,
        sheetId,
        sheetName: "",
      };
      const addRowsBefore: AddColumnsRowsCommand = {
        type: "ADD_COLUMNS_ROWS",
        dimension: "ROW",
        position: "before",
        base: 5,
        quantity: 2,
        sheetId,
        sheetName: "",
      };
      const result = transform(addRowsAfter, addRowsBefore);
      expect(result).toEqual({ ...addRowsAfter, base: 7 });
    });
    test("Base row before the one already added", () => {
      const addRowsAfter: AddColumnsRowsCommand = {
        type: "ADD_COLUMNS_ROWS",
        dimension: "ROW",
        position: "after",
        base: 5,
        quantity: 2,
        sheetId,
        sheetName: "",
      };
      const result = transform({ ...addRowsAfter, base: 0 }, addRowsAfter);
      expect(result).toEqual({ ...addRowsAfter, base: 0 });
    });
    test("Base row after the one already added", () => {
      const addRowsAfter: AddColumnsRowsCommand = {
        type: "ADD_COLUMNS_ROWS",
        dimension: "ROW",
        position: "after",
        base: 5,
        quantity: 2,
        sheetId,
        sheetName: "",
      };
      const result = transform({ ...addRowsAfter, base: 10 }, addRowsAfter);
      expect(result).toEqual({ ...addRowsAfter, base: 12 });
    });
    test("add a row on another sheet", () => {
      const command = { ...addRowsAfter, sheetId: "other" };
      const result = transform(command, addRowsAfter);
      expect(result).toEqual(command);
    });
  });

  describe("Adding column does not impact commands in dimension 'ROW'", () => {
    test("Add rows after add columns after", () => {
      const command = { ...addRowsAfter, dimension: "COL" } as AddColumnsRowsCommand;
      const result = transform(command, addRowsAfter);
      expect(result).toEqual(command);
    });
    test("Add rows after add columns before", () => {
      const command = { ...addRowsBefore, dimension: "COL" } as AddColumnsRowsCommand;
      const result = transform(command, addRowsBefore);
      expect(result).toEqual(command);
    });
  });

  describe("OT with AddRows before - FREEZE_ROWS", () => {
    const toTransform: Omit<FreezeRowsCommand, "quantity"> = {
      type: "FREEZE_ROWS",
      sheetId,
    };

    test("freeze a row before the left-most added row", () => {
      const command = { ...toTransform, quantity: 8 };
      const result = transform(command, addRowsBefore);
      expect(result).toEqual({ ...command });
    });

    test("Freeze row after the added ones", () => {
      const command = { ...toTransform, quantity: 12 };
      const result = transform(command, addRowsBefore);
      expect(result).toEqual({ ...command, quantity: 14 });
    });

    test("Freeze a row before the added ones", () => {
      const command = { ...toTransform, quantity: 1 };
      const result = transform(command, addRowsBefore);
      expect(result).toEqual(command);
    });

    test("Freeze row on another sheet", () => {
      const command = { ...toTransform, quantity: 11, sheetId: "42" };
      const result = transform(command, addRowsBefore);
      expect(result).toEqual(command);
    });
  });

  describe("OT with AddRows after - FREEZE_ROWS", () => {
    const toTransform: Omit<FreezeRowsCommand, "quantity"> = {
      type: "FREEZE_ROWS",
      sheetId,
    };

    test("freeze a row before the left-most added row", () => {
      const command = { ...toTransform, quantity: 5 };
      const result = transform(command, addRowsAfter);
      expect(result).toEqual({ ...command });
    });

    test("Freeze row after the added ones", () => {
      const command = { ...toTransform, quantity: 12 };
      const result = transform(command, addRowsAfter);
      expect(result).toEqual({ ...command, quantity: 14 });
    });

    test("Freeze a row before the added ones", () => {
      const command = { ...toTransform, quantity: 1 };
      const result = transform(command, addRowsAfter);
      expect(result).toEqual(command);
    });

    test("Freeze row on another sheet", () => {
      const command = { ...toTransform, quantity: 11, sheetId: "42" };
      const result = transform(command, addRowsAfter);
      expect(result).toEqual(command);
    });
  });

  describe("OT with addRows after/ before FREEZE_COLUMNS has no effect", () => {
    const toTransform: Omit<FreezeColumnsCommand, "quantity"> = {
      type: "FREEZE_COLUMNS",
      sheetId,
    };

    test("freeze a columns after added after row", () => {
      const command = { ...toTransform, quantity: 6 };
      const result = transform(command, addRowsAfter);
      expect(result).toEqual({ ...command });
    });

    test("freeze a column after added before row", () => {
      const command = { ...toTransform, quantity: 2 };
      const result = transform(command, addRowsBefore);
      expect(result).toEqual({ ...command });
    });
  });
});

describe.each(OT_TESTS_HEADER_GROUP_COMMANDS)(
  "Transform of (UN)GROUP_HEADERS when adding rows",
  (cmd) => {
    const addRowsCmd: AddColumnsRowsCommand = {
      ...TEST_COMMANDS.ADD_COLUMNS_ROWS,
      dimension: "ROW",
      quantity: 2,
    };
    const toTransform: (typeof OT_TESTS_HEADER_GROUP_COMMANDS)[number] = {
      ...cmd,
      dimension: "ROW",
      start: 5,
      end: 7,
    };

    test("Add rows before the group", () => {
      const executed: AddColumnsRowsCommand = { ...addRowsCmd, base: 0, position: "after" };
      const result = transform(toTransform, executed);
      expect(result).toEqual({ ...toTransform, start: 7, end: 9 });
    });

    test("Add rows right before the group", () => {
      const executed: AddColumnsRowsCommand = { ...addRowsCmd, base: 5, position: "before" };
      const result = transform(toTransform, executed);
      expect(result).toEqual({ ...toTransform, start: 7, end: 9 });
    });

    test("Add rows inside the group", () => {
      const executed: AddColumnsRowsCommand = { ...addRowsCmd, base: 5, position: "after" };
      const result = transform(toTransform, executed);
      expect(result).toEqual({ ...toTransform, start: 5, end: 9 });
    });

    test("Add rows after the group", () => {
      const executed: AddColumnsRowsCommand = { ...addRowsCmd, base: 7, position: "after" };
      const result = transform(toTransform, executed);
      expect(result).toEqual({ ...toTransform, start: 5, end: 7 });
    });

    test("Add rows in another sheet", () => {
      const executed: AddColumnsRowsCommand = { ...addRowsCmd, base: 0, sheetId: "42" };
      const result = transform(toTransform, executed);
      expect(result).toEqual(toTransform);
    });
  }
);

describe("Transform of UPDATE_TABLE when adding rows", () => {
  const sheetId = TEST_COMMANDS.UPDATE_TABLE.sheetId;
  const addRowsCmd: AddColumnsRowsCommand = {
    ...TEST_COMMANDS.ADD_COLUMNS_ROWS,
    dimension: "ROW",
    quantity: 1,
  };
  const updateFilterCmd: UpdateTableCommand = {
    ...TEST_COMMANDS.UPDATE_TABLE,
    zone: toZone("A1:B2"),
    newTableRange: toRangeData(sheetId, "A1:C3"),
  };

  test("Add rows before the zones", () => {
    const executed: AddColumnsRowsCommand = { ...addRowsCmd, base: 0, position: "before" };
    const result = transform(updateFilterCmd, executed);
    expect(result).toEqual({
      ...updateFilterCmd,
      zone: toZone("A2:B3"),
      newTableRange: toRangeData(sheetId, "A2:C4"),
    });
  });

  test("Add rows inside the zones", () => {
    const executed: AddColumnsRowsCommand = { ...addRowsCmd, base: 0, position: "after" };
    const result = transform(updateFilterCmd, executed);
    expect(result).toEqual({
      ...updateFilterCmd,
      zone: toZone("A1:B3"),
      newTableRange: toRangeData(sheetId, "A1:C4"),
    });
  });

  test("Add rows after the zones", () => {
    const executed: AddColumnsRowsCommand = { ...addRowsCmd, base: 7, position: "after" };
    const result = transform(updateFilterCmd, executed);
    expect(result).toEqual(updateFilterCmd);
  });

  test("Add rows in another sheet", () => {
    const executed: AddColumnsRowsCommand = { ...addRowsCmd, base: 0, sheetId: "42" };
    const result = transform(updateFilterCmd, executed);
    expect(result).toEqual(updateFilterCmd);
  });
});

describe("Transform adapt string formulas on row addition", () => {
  const sheetId = "mainSheetId";
  const sheetName = "MainSheetName";
  const otherSheetId = "otherSheetId";
  const otherSheetName = "OtherSheetName";

  test.each(getFormulaStringCommands(sheetId, "=SUM(A1:A5)", "=SUM(A1:A6)"))(
    "on the same sheet %s",
    (cmd, expected) => {
      const addRowCmd: AddColumnsRowsCommand = {
        ...TEST_COMMANDS.ADD_COLUMNS_ROWS,
        dimension: "ROW",
        sheetId,
        sheetName,
      };
      const result = transform(cmd, addRowCmd);
      expect(result).toEqual(expected);
    }
  );

  test.each(
    getFormulaStringCommands(
      sheetId,
      "=SUM(" + otherSheetName + "!A1:A5)",
      "=SUM(" + otherSheetName + "!A1:A6)"
    )
  )("on another sheet %s", (cmd, expected) => {
    const addRowCmd: AddColumnsRowsCommand = {
      ...TEST_COMMANDS.ADD_COLUMNS_ROWS,
      dimension: "ROW",
      sheetId: otherSheetId,
      sheetName: otherSheetName,
    };
    const result = transform(cmd, addRowCmd);
    expect(result).toEqual(expected);
  });

  test.each(getFormulaStringCommands(sheetId, "hello in A5", "hello in A5"))(
    "do not adapt string %s",
    (cmd, expected) => {
      const addRowCmd: AddColumnsRowsCommand = {
        ...TEST_COMMANDS.ADD_COLUMNS_ROWS,
        dimension: "ROW",
        sheetId,
        sheetName,
      };
      const result = transform(cmd, addRowCmd);
      expect(result).toEqual(expected);
    }
  );
});

describe("OT with addRows and UPDATE_CHART/CREATE_CHART", () => {
  const sheetId = "sheet1";
  const sheetName = "Sheet1";
  const definition: BarChartDefinition<string> = {
    type: "bar",
    ...toChartDataSource({
      dataSets: [{ dataRange: "Sheet1!A5:A15" }, { dataRange: "Sheet2!A5:A15" }],
      dataSetsHaveTitle: false,
      labelRange: "Sheet1!A5:A15",
    }),
    legendPosition: "top",
    stacked: false,
    title: { text: "test" },
  };

  const addRowsBefore: AddColumnsRowsCommand = {
    ...TEST_COMMANDS.ADD_COLUMNS_ROWS,
    base: 7,
    quantity: 2,
    sheetId,
    sheetName,
  };

  const addRowsOnSheet2: AddColumnsRowsCommand = {
    ...addRowsBefore,
    sheetId: "sh2",
    sheetName: "Sheet2",
  };

  test("CREATE_CHART ranges are updated on the same sheet as addRows", () => {
    const toTransform: CreateChartCommand = {
      type: "CREATE_CHART",
      sheetId,
      figureId: "chart1",
      chartId: "chart1",
      definition,
      col: 0,
      row: 0,
      offset: { x: 0, y: 0 },
      size: { width: 0, height: 0 },
    };
    let result = transform(toTransform, addRowsBefore) as CreateChartCommand;
    expect(result.definition).toEqual({
      ...definition,
      ...toChartDataSource({
        dataSets: [{ dataRange: "Sheet1!A5:A17" }, { dataRange: "Sheet2!A5:A15" }],
        labelRange: "Sheet1!A5:A17",
        dataSetsHaveTitle: false,
      }),
    });

    result = transform(toTransform, addRowsOnSheet2) as CreateChartCommand;
    expect(result.definition).toEqual({
      ...definition,
      ...toChartDataSource({
        dataSets: [{ dataRange: "Sheet1!A5:A15" }, { dataRange: "Sheet2!A5:A17" }],
        labelRange: "Sheet1!A5:A15",
        dataSetsHaveTitle: false,
      }),
    });
  });

  test("UPDATE_CHART ranges are updated on the same sheet as addRow", () => {
    const toTransform: UpdateChartCommand = {
      type: "UPDATE_CHART",
      sheetId,
      figureId: "chart1",
      chartId: "chart1",
      definition,
    };

    let result = transform(toTransform, addRowsBefore) as UpdateChartCommand;
    expect(result.definition).toEqual({
      ...definition,
      ...toChartDataSource({
        dataSets: [{ dataRange: "Sheet1!A5:A17" }, { dataRange: "Sheet2!A5:A15" }],
        labelRange: "Sheet1!A5:A17",
        dataSetsHaveTitle: false,
      }),
    });

    result = transform(toTransform, addRowsOnSheet2) as UpdateChartCommand;
    expect(result.definition).toEqual({
      ...definition,
      ...toChartDataSource({
        dataSets: [{ dataRange: "Sheet1!A5:A15" }, { dataRange: "Sheet2!A5:A17" }],
        labelRange: "Sheet1!A5:A15",
        dataSetsHaveTitle: false,
      }),
    });
  });
});

describe("OT with addRows and carousel commands", () => {
  const carousel: CarouselData = {
    items: [
      { type: "carouselDataView", rangeData: toRangeData("sh1", "C3:E5"), title: "title1" },
      { type: "carouselDataView", rangeData: toRangeData("sh2", "C3:E5"), title: "title2" },
    ],
  };

  const addRowsBefore: AddColumnsRowsCommand = {
    ...TEST_COMMANDS.ADD_COLUMNS_ROWS,
    dimension: "ROW",
    base: 1,
    quantity: 2,
    sheetId: "sh1",
    sheetName: "Sheet1",
  };

  test.each([TEST_COMMANDS.CREATE_CAROUSEL, TEST_COMMANDS.UPDATE_CAROUSEL])(
    "ranges are updated on the same sheet as addRows",
    (cmd) => {
      const toTransform = { ...cmd, sheetId: "sh1", definition: carousel };
      const result = transform(toTransform, addRowsBefore) as any;
      expect(result?.definition).toMatchObject({
        items: [
          { type: "carouselDataView", rangeData: toRangeData("sh1", "C5:E7"), title: "title1" },
          { type: "carouselDataView", rangeData: toRangeData("sh2", "C3:E5"), title: "title2" },
        ],
      });
    }
  );
});
