addons/isl/src/__tests__/interactiveSplit.test.tsxblame
View source
b69ab311/**
b69ab312 * Copyright (c) Meta Platforms, Inc. and affiliates.
b69ab313 *
b69ab314 * This source code is licensed under the MIT license found in the
b69ab315 * LICENSE file in the root directory of this source tree.
b69ab316 */
b69ab317
b69ab318import type {DateTuple} from 'shared/types/common';
b69ab319import type {CodeReviewSystem} from '../types';
b69ab3110
b69ab3111import {act, fireEvent, render, screen, waitFor, within} from '@testing-library/react';
b69ab3112import * as utils from 'shared/utils';
b69ab3113import App from '../App';
b69ab3114import {
b69ab3115 closeCommitInfoSidebar,
b69ab3116 expectMessageNOTSentToServer,
b69ab3117 expectMessageSentToServer,
b69ab3118 getLastMessageOfTypeSentToServer,
b69ab3119 resetTestMessages,
b69ab3120 simulateCommits,
b69ab3121 simulateMessageFromServer,
b69ab3122 TEST_COMMIT_HISTORY,
b69ab3123} from '../testUtils';
b69ab3124import {CommandRunner} from '../types';
b69ab3125
b69ab3126const EXPORT_STACK_DATA = [
b69ab3127 {
b69ab3128 requested: false,
b69ab3129 node: 'd',
b69ab3130 author: 'username',
b69ab3131 date: [1715719789, 25200] as DateTuple,
b69ab3132 text: 'Commit D',
b69ab3133 immutable: false,
b69ab3134 relevantFiles: {
b69ab3135 'myFile.js': {
b69ab3136 data: 'hello\nworld!\n',
b69ab3137 },
b69ab3138 },
b69ab3139 },
b69ab3140 {
b69ab3141 requested: true,
b69ab3142 node: 'e',
b69ab3143 author: 'username',
b69ab3144 date: [1715719789, 25200] as DateTuple,
b69ab3145 text: 'Commit E',
b69ab3146 immutable: false,
b69ab3147 parents: ['d'],
b69ab3148 files: {
b69ab3149 'myFile.js': {
b69ab3150 data: 'hello (changed)\nworld!\n',
b69ab3151 },
b69ab3152 },
b69ab3153 },
b69ab3154];
b69ab3155
b69ab3156describe('Interactive Split', () => {
b69ab3157 beforeEach(() => {
b69ab3158 resetTestMessages();
b69ab3159 render(<App />);
b69ab3160 act(() => {
b69ab3161 closeCommitInfoSidebar();
b69ab3162 simulateMessageFromServer({
b69ab3163 type: 'repoInfo',
b69ab3164 info: {
b69ab3165 type: 'success',
b69ab3166 repoRoot: '/path/to/repo',
b69ab3167 dotdir: '/path/to/repo/.sl',
b69ab3168 command: 'sl',
b69ab3169 pullRequestDomain: undefined,
b69ab3170 codeReviewSystem: {type: 'github'} as CodeReviewSystem,
b69ab3171 isEdenFs: false,
b69ab3172 },
b69ab3173 });
b69ab3174 expectMessageSentToServer({
b69ab3175 type: 'subscribe',
b69ab3176 kind: 'smartlogCommits',
b69ab3177 subscriptionID: expect.anything(),
b69ab3178 });
b69ab3179 simulateCommits({
b69ab3180 value: TEST_COMMIT_HISTORY,
b69ab3181 });
b69ab3182 });
b69ab3183
b69ab3184 const mockObserveFn = () => {
b69ab3185 return {
b69ab3186 observe: jest.fn(),
b69ab3187 unobserve: jest.fn(),
b69ab3188 disconnect: jest.fn(),
b69ab3189 };
b69ab3190 };
b69ab3191
b69ab3192 window.IntersectionObserver = jest.fn().mockImplementation(mockObserveFn);
b69ab3193 });
b69ab3194
b69ab3195 it('shows split button on dot commit', () => {
b69ab3196 expect(screen.getByText('Split')).toBeInTheDocument();
b69ab3197 });
b69ab3198
b69ab3199 it('show split modal with spinner on click', async () => {
b69ab31100 fireEvent.click(screen.getByText('Split'));
b69ab31101 await waitFor(() => expect(screen.getByTestId('edit-stack-loading')).toBeInTheDocument());
b69ab31102 });
b69ab31103
b69ab31104 it('requests debugexportstack data', async () => {
b69ab31105 fireEvent.click(screen.getByText('Split'));
b69ab31106
b69ab31107 await waitFor(() => expectMessageSentToServer({type: 'exportStack', revs: 'e'}));
b69ab31108 });
b69ab31109
b69ab31110 it('shows errors', async () => {
b69ab31111 fireEvent.click(screen.getByText('Split'));
b69ab31112 await waitFor(() => expectMessageSentToServer({type: 'exportStack', revs: 'e'}));
b69ab31113 act(() => {
b69ab31114 simulateMessageFromServer({
b69ab31115 type: 'exportedStack',
b69ab31116 revs: 'e',
b69ab31117 assumeTracked: [],
b69ab31118 error: 'test error',
b69ab31119 stack: [],
b69ab31120 });
b69ab31121 });
b69ab31122 await waitFor(() => expect(screen.getByText('test error')).toBeInTheDocument());
b69ab31123 });
b69ab31124
b69ab31125 it('waits for existing commands to finish running before loading stack', async () => {
b69ab31126 fireEvent.click(screen.getByText('Pull', {selector: 'button'}));
b69ab31127 const message = await waitFor(() =>
b69ab31128 utils.nullthrows(getLastMessageOfTypeSentToServer('runOperation')),
b69ab31129 );
b69ab31130 const id = message.operation.id;
b69ab31131
b69ab31132 fireEvent.click(screen.getByText('Split'));
b69ab31133
b69ab31134 expectMessageNOTSentToServer({type: 'exportStack', revs: 'e'});
b69ab31135
b69ab31136 act(() =>
b69ab31137 simulateMessageFromServer({
b69ab31138 type: 'operationProgress',
b69ab31139 id,
b69ab31140 kind: 'exit',
b69ab31141 exitCode: 0,
b69ab31142 timestamp: 0,
b69ab31143 }),
b69ab31144 );
b69ab31145
b69ab31146 await waitFor(() => expectMessageSentToServer({type: 'exportStack', revs: 'e'}));
b69ab31147 });
b69ab31148
b69ab31149 describe('with loaded stack data', () => {
b69ab31150 beforeEach(async () => {
b69ab31151 fireEvent.click(screen.getByText('Split'));
b69ab31152 await waitFor(() => expectMessageSentToServer({type: 'exportStack', revs: 'e'}));
b69ab31153 act(() => {
b69ab31154 simulateMessageFromServer({
b69ab31155 type: 'exportedStack',
b69ab31156 revs: 'e',
b69ab31157 assumeTracked: [],
b69ab31158 error: undefined,
b69ab31159 stack: EXPORT_STACK_DATA,
b69ab31160 });
b69ab31161 });
b69ab31162 await waitFor(() =>
b69ab31163 expect(screen.getByTestId('interactive-split-modal')).toBeInTheDocument(),
b69ab31164 );
b69ab31165 });
b69ab31166
b69ab31167 it('loads exported stack into UI', () => {
b69ab31168 expect(
b69ab31169 within(screen.getByTestId('interactive-split-modal')).getByText('myFile.js'),
b69ab31170 ).toBeInTheDocument();
b69ab31171
b69ab31172 expect(
b69ab31173 within(screen.getByTestId('interactive-split-modal')).getByText('hello'),
b69ab31174 ).toBeInTheDocument();
b69ab31175
b69ab31176 expect(
b69ab31177 within(screen.getByTestId('interactive-split-modal')).getByText('hello (changed)'),
b69ab31178 ).toBeInTheDocument();
b69ab31179 });
b69ab31180
b69ab31181 it('moves lines and requests importing', async () => {
b69ab31182 jest.useFakeTimers().setSystemTime(new Date('2020-01-01'));
b69ab31183
b69ab31184 const arrows = screen.getAllByTitle('Move this line change right');
b69ab31185 fireEvent.click(arrows[1]);
b69ab31186 fireEvent.click(screen.getByTestId('confirm-edit-stack-button'));
b69ab31187
b69ab31188 const message = await waitFor(() =>
b69ab31189 utils.nullthrows(getLastMessageOfTypeSentToServer('runOperation')),
b69ab31190 );
b69ab31191 const id = message.operation.id;
b69ab31192
b69ab31193 expectMessageSentToServer({
b69ab31194 type: 'runOperation',
b69ab31195 operation: {
b69ab31196 id,
b69ab31197 trackEventName: 'ImportStackOperation',
b69ab31198 args: ['debugimportstack'],
b69ab31199 stdin: JSON.stringify([
b69ab31200 [
b69ab31201 'commit',
b69ab31202 {
b69ab31203 mark: ':r1',
b69ab31204 author: 'username',
b69ab31205 date: [1577836800, 25200],
b69ab31206 text: 'Commit E',
b69ab31207 parents: ['d'],
b69ab31208 predecessors: ['e'],
b69ab31209 files: {'myFile.js': {data: 'world!\n', flags: ''}},
b69ab31210 },
b69ab31211 ],
b69ab31212 [
b69ab31213 'commit',
b69ab31214 {
b69ab31215 mark: ':r2',
b69ab31216 author: 'username',
b69ab31217 date: [1577836800, 25200],
b69ab31218 text: 'Split of "Commit E"',
b69ab31219 parents: [':r1'],
b69ab31220 predecessors: ['e'],
b69ab31221 files: {'myFile.js': {data: 'hello (changed)\nworld!\n', flags: ''}},
b69ab31222 },
b69ab31223 ],
b69ab31224 ['goto', {mark: ':r2'}],
b69ab31225 ]),
b69ab31226 runner: CommandRunner.Sapling,
b69ab31227 },
b69ab31228 });
b69ab31229 });
b69ab31230 });
b69ab31231});