addons/isl/src/__tests__/Shelve.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 {act, fireEvent, render, screen, waitFor, within} from '@testing-library/react';
b69ab319import userEvent from '@testing-library/user-event';
b69ab3110import {ComparisonType} from 'shared/Comparison';
b69ab3111import {nullthrows} from 'shared/utils';
b69ab3112import App from '../App';
b69ab3113import {ignoreRTL} from '../testQueries';
b69ab3114import {
b69ab3115 closeCommitInfoSidebar,
b69ab3116 COMMIT,
b69ab3117 expectMessageSentToServer,
b69ab3118 resetTestMessages,
b69ab3119 simulateCommits,
b69ab3120 simulateMessageFromServer,
b69ab3121 simulateRepoConnected,
b69ab3122 simulateUncommittedChangedFiles,
b69ab3123} from '../testUtils';
b69ab3124
b69ab3125describe('Shelve', () => {
b69ab3126 beforeEach(() => {
b69ab3127 resetTestMessages();
b69ab3128 render(<App />);
b69ab3129 act(() => {
b69ab3130 simulateRepoConnected();
b69ab3131 closeCommitInfoSidebar();
b69ab3132 expectMessageSentToServer({
b69ab3133 type: 'subscribe',
b69ab3134 kind: 'smartlogCommits',
b69ab3135 subscriptionID: expect.anything(),
b69ab3136 });
b69ab3137 simulateCommits({
b69ab3138 value: [
b69ab3139 COMMIT('1', 'some public base', '0', {phase: 'public'}),
b69ab3140 COMMIT('a', 'My Commit', '1'),
b69ab3141 COMMIT('b', 'Another Commit', 'a', {isDot: true}),
b69ab3142 ],
b69ab3143 });
b69ab3144
b69ab3145 simulateUncommittedChangedFiles({
b69ab3146 value: [
b69ab3147 {path: 'src/file1.js', status: 'M'},
b69ab3148 {path: 'src/file2.js', status: 'M'},
b69ab3149 {path: 'src/file3.js', status: 'M'},
b69ab3150 ],
b69ab3151 });
b69ab3152 });
b69ab3153 });
b69ab3154
b69ab3155 describe('Shelve button', () => {
b69ab3156 it('Runs shelve when clicking button', async () => {
b69ab3157 const shelveButton = screen.getByText('Shelve');
b69ab3158 expect(shelveButton).toBeInTheDocument();
b69ab3159
b69ab3160 fireEvent.click(shelveButton);
b69ab3161 await waitFor(() =>
b69ab3162 expectMessageSentToServer({
b69ab3163 type: 'runOperation',
b69ab3164 operation: expect.objectContaining({
b69ab3165 args: ['shelve', '--unknown'],
b69ab3166 }),
b69ab3167 }),
b69ab3168 );
b69ab3169 });
b69ab3170
b69ab3171 it('Optimistic state hides all files when shelve running', async () => {
b69ab3172 expect(screen.queryAllByTestId(/changed-file-src\/file.\.js/)).toHaveLength(3);
b69ab3173 const shelveButton = screen.getByText('Shelve');
b69ab3174 fireEvent.click(shelveButton);
b69ab3175 await waitFor(() =>
b69ab3176 expect(screen.queryAllByTestId(/changed-file-src\/file.\.js/)).toHaveLength(0),
b69ab3177 );
b69ab3178 });
b69ab3179
b69ab3180 it('includes name for shelved change if typed', async () => {
b69ab3181 const shelveButton = screen.getByText('Shelve');
b69ab3182 expect(shelveButton).toBeInTheDocument();
b69ab3183
b69ab3184 const quickInput = screen.getByTestId('quick-commit-title');
b69ab3185
b69ab3186 act(() => {
b69ab3187 userEvent.type(quickInput, 'My Shelf');
b69ab3188 });
b69ab3189
b69ab3190 fireEvent.click(shelveButton);
b69ab3191 await waitFor(() =>
b69ab3192 expectMessageSentToServer({
b69ab3193 type: 'runOperation',
b69ab3194 operation: expect.objectContaining({
b69ab3195 args: ['shelve', '--unknown', '--name', 'My Shelf'],
b69ab3196 }),
b69ab3197 }),
b69ab3198 );
b69ab3199 });
b69ab31100
b69ab31101 it('only shelves selected files', async () => {
b69ab31102 const shelveButton = screen.getByText('Shelve');
b69ab31103 expect(shelveButton).toBeInTheDocument();
b69ab31104
b69ab31105 // uncheck one file
b69ab31106 fireEvent.click(
b69ab31107 nullthrows(
b69ab31108 screen.getByTestId('changed-file-src/file2.js').querySelector('input[type=checkbox]'),
b69ab31109 ),
b69ab31110 );
b69ab31111
b69ab31112 fireEvent.click(shelveButton);
b69ab31113
b69ab31114 await waitFor(() =>
b69ab31115 expectMessageSentToServer({
b69ab31116 type: 'runOperation',
b69ab31117 operation: expect.objectContaining({
b69ab31118 args: [
b69ab31119 'shelve',
b69ab31120 '--unknown',
b69ab31121 {type: 'repo-relative-file', path: 'src/file1.js'},
b69ab31122 {type: 'repo-relative-file', path: 'src/file3.js'},
b69ab31123 ],
b69ab31124 }),
b69ab31125 }),
b69ab31126 );
b69ab31127 });
b69ab31128
b69ab31129 it('Optimistic state hides selected files when shelve running', async () => {
b69ab31130 expect(screen.queryAllByTestId(/src\/file.\.js/)).toHaveLength(3);
b69ab31131 const shelveButton = screen.getByText('Shelve');
b69ab31132 fireEvent.click(shelveButton);
b69ab31133 await waitFor(() => expect(screen.queryAllByTestId(/src\/file.\.js/)).toHaveLength(0));
b69ab31134 });
b69ab31135
b69ab31136 it('shelve button disabled if no files selected', async () => {
b69ab31137 fireEvent.click(screen.getByText('Deselect All'));
b69ab31138
b69ab31139 const shelveButton = screen.getByText('Shelve');
b69ab31140 await waitFor(() => {
b69ab31141 expect(shelveButton).toBeInTheDocument();
b69ab31142 expect(shelveButton).toBeDisabled();
b69ab31143 });
b69ab31144 });
b69ab31145 });
b69ab31146
b69ab31147 describe('Shelved changes list', () => {
b69ab31148 const SHELVES = [
b69ab31149 {
b69ab31150 hash: 'aaa',
b69ab31151 name: 'my shelve',
b69ab31152 date: new Date(),
b69ab31153 description: 'shelved on commit b',
b69ab31154 filesSample: [{path: 'src/shelvedfile.js', status: 'M' as const}],
b69ab31155 totalFileCount: 1,
b69ab31156 },
b69ab31157 ];
b69ab31158
b69ab31159 it('shows shelved changes list tooltip', () => {
b69ab31160 fireEvent.click(screen.getByTestId('shelved-changes-button'));
b69ab31161 expect(screen.getByText('Shelved Changes')).toBeInTheDocument();
b69ab31162
b69ab31163 expectMessageSentToServer({
b69ab31164 type: 'fetchShelvedChanges',
b69ab31165 });
b69ab31166 });
b69ab31167
b69ab31168 it('renders errors from fetching shelved changes', async () => {
b69ab31169 fireEvent.click(screen.getByTestId('shelved-changes-button'));
b69ab31170 act(() => {
b69ab31171 simulateMessageFromServer({
b69ab31172 type: 'fetchedShelvedChanges',
b69ab31173 shelvedChanges: {
b69ab31174 error: new Error('failed to fetch shelved changes'),
b69ab31175 },
b69ab31176 });
b69ab31177 });
b69ab31178
b69ab31179 await waitFor(() => {
b69ab31180 expect(
b69ab31181 within(screen.getByTestId('shelved-changes-dropdown')).getByText(
b69ab31182 'Could not fetch shelved changes',
b69ab31183 ),
b69ab31184 ).toBeInTheDocument();
b69ab31185 });
b69ab31186 });
b69ab31187
b69ab31188 it('renders empty state', async () => {
b69ab31189 fireEvent.click(screen.getByTestId('shelved-changes-button'));
b69ab31190 act(() => {
b69ab31191 simulateMessageFromServer({
b69ab31192 type: 'fetchedShelvedChanges',
b69ab31193 shelvedChanges: {
b69ab31194 value: [],
b69ab31195 },
b69ab31196 });
b69ab31197 });
b69ab31198
b69ab31199 await waitFor(() => {
b69ab31200 expect(
b69ab31201 within(screen.getByTestId('shelved-changes-dropdown')).getByText('No shelved changes'),
b69ab31202 ).toBeInTheDocument();
b69ab31203 });
b69ab31204 });
b69ab31205
b69ab31206 describe('with shelved change rendered', () => {
b69ab31207 beforeEach(async () => {
b69ab31208 fireEvent.click(screen.getByTestId('shelved-changes-button'));
b69ab31209 act(() => {
b69ab31210 simulateMessageFromServer({
b69ab31211 type: 'fetchedShelvedChanges',
b69ab31212 shelvedChanges: {
b69ab31213 value: SHELVES,
b69ab31214 },
b69ab31215 });
b69ab31216 });
b69ab31217
b69ab31218 await waitFor(() => {
b69ab31219 expect(
b69ab31220 within(screen.getByTestId('shelved-changes-dropdown')).getByText('my shelve'),
b69ab31221 ).toBeInTheDocument();
b69ab31222 });
b69ab31223 });
b69ab31224
b69ab31225 it('renders shelved changes', () => {
b69ab31226 expect(
b69ab31227 within(screen.getByTestId('shelved-changes-dropdown')).getByText(
b69ab31228 ignoreRTL('shelvedfile.js'),
b69ab31229 ),
b69ab31230 ).toBeInTheDocument();
b69ab31231 });
b69ab31232
b69ab31233 it('runs unshelve', () => {
b69ab31234 fireEvent.click(screen.getByText('Unshelve'));
b69ab31235
b69ab31236 expectMessageSentToServer({
b69ab31237 type: 'runOperation',
b69ab31238 operation: expect.objectContaining({
b69ab31239 args: ['unshelve', '--name', 'my shelve'],
b69ab31240 }),
b69ab31241 });
b69ab31242 });
b69ab31243
b69ab31244 it('runs apply', () => {
b69ab31245 fireEvent.click(screen.getByText('Apply'));
b69ab31246
b69ab31247 expectMessageSentToServer({
b69ab31248 type: 'runOperation',
b69ab31249 operation: expect.objectContaining({
b69ab31250 args: ['unshelve', '--keep', '--name', 'my shelve'],
b69ab31251 }),
b69ab31252 });
b69ab31253 });
b69ab31254
b69ab31255 it('runs delete', () => {
b69ab31256 fireEvent.click(screen.getByTestId('delete-shelve-aaa'));
b69ab31257
b69ab31258 expectMessageSentToServer({
b69ab31259 type: 'runOperation',
b69ab31260 operation: expect.objectContaining({
b69ab31261 args: ['shelve', '--delete', 'my shelve'],
b69ab31262 }),
b69ab31263 });
b69ab31264 });
b69ab31265
b69ab31266 it('dismisses tooltip while running unshelve', () => {
b69ab31267 fireEvent.click(screen.getByText('Unshelve'));
b69ab31268
b69ab31269 expect(screen.queryByTestId('shelved-changes-dropdown')).not.toBeInTheDocument();
b69ab31270 });
b69ab31271
b69ab31272 it('can open comparison view for the shelve', async () => {
b69ab31273 fireEvent.click(
b69ab31274 within(screen.getByTestId('shelved-changes-dropdown')).getByText('View Changes'),
b69ab31275 );
b69ab31276
b69ab31277 await waitFor(() => {
b69ab31278 expectMessageSentToServer({
b69ab31279 type: 'requestComparison',
b69ab31280 comparison: {
b69ab31281 type: ComparisonType.Committed,
b69ab31282 hash: 'aaa',
b69ab31283 },
b69ab31284 });
b69ab31285 });
b69ab31286 });
b69ab31287
b69ab31288 it('refetches shelves when reopening dropdown', async () => {
b69ab31289 expect(
b69ab31290 within(screen.getByTestId('shelved-changes-dropdown')).getByText('my shelve'),
b69ab31291 ).toBeInTheDocument();
b69ab31292
b69ab31293 resetTestMessages();
b69ab31294
b69ab31295 act(() => {
b69ab31296 userEvent.type(document.body, '{Escape}');
b69ab31297 });
b69ab31298
b69ab31299 // reopen the dropdown
b69ab31300 fireEvent.click(screen.getByTestId('shelved-changes-button'));
b69ab31301 expectMessageSentToServer({
b69ab31302 type: 'fetchShelvedChanges',
b69ab31303 });
b69ab31304
b69ab31305 // send a new set of changes
b69ab31306 const NEW_SHELVES = [
b69ab31307 {
b69ab31308 hash: 'a',
b69ab31309 name: 'my new shelve',
b69ab31310 date: new Date(),
b69ab31311 description: 'shelved on commit b',
b69ab31312 filesSample: [{path: 'src/shelvedfile.js', status: 'M' as const}],
b69ab31313 totalFileCount: 1,
b69ab31314 },
b69ab31315 ];
b69ab31316 act(() => {
b69ab31317 simulateMessageFromServer({
b69ab31318 type: 'fetchedShelvedChanges',
b69ab31319 shelvedChanges: {
b69ab31320 value: NEW_SHELVES,
b69ab31321 },
b69ab31322 });
b69ab31323 });
b69ab31324
b69ab31325 // make sure we get the new name and not the old one
b69ab31326 expect(
b69ab31327 within(screen.getByTestId('shelved-changes-dropdown')).queryByText('my shelve'),
b69ab31328 ).not.toBeInTheDocument();
b69ab31329 await waitFor(() => {
b69ab31330 expect(
b69ab31331 within(screen.getByTestId('shelved-changes-dropdown')).getByText('my new shelve'),
b69ab31332 ).toBeInTheDocument();
b69ab31333 });
b69ab31334 });
b69ab31335
b69ab31336 it('shows optimistic state for unshelve', () => {
b69ab31337 expect(
b69ab31338 within(screen.getByTestId('commit-tree-root')).queryByText(ignoreRTL('shelvedfile.js')),
b69ab31339 ).not.toBeInTheDocument();
b69ab31340
b69ab31341 fireEvent.click(screen.getByText('Unshelve'));
b69ab31342
b69ab31343 expect(
b69ab31344 within(screen.getByTestId('commit-tree-root')).getByText(ignoreRTL('shelvedfile.js')),
b69ab31345 ).toBeInTheDocument();
b69ab31346 });
b69ab31347 });
b69ab31348 });
b69ab31349});