| b69ab31 | | | 1 | /** |
| b69ab31 | | | 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. |
| b69ab31 | | | 3 | * |
| b69ab31 | | | 4 | * This source code is licensed under the MIT license found in the |
| b69ab31 | | | 5 | * LICENSE file in the root directory of this source tree. |
| b69ab31 | | | 6 | */ |
| b69ab31 | | | 7 | |
| b69ab31 | | | 8 | import type {ChangedFileStatus, RepoRelativePath, UncommittedChanges} from '../types'; |
| b69ab31 | | | 9 | |
| b69ab31 | | | 10 | import {act, fireEvent, render, screen} from '@testing-library/react'; |
| b69ab31 | | | 11 | import userEvent from '@testing-library/user-event'; |
| b69ab31 | | | 12 | import App from '../App'; |
| b69ab31 | | | 13 | import {defaultChangedFilesDisplayType} from '../ChangedFileDisplayTypePicker'; |
| b69ab31 | | | 14 | import {CommitInfoTestUtils, ignoreRTL} from '../testQueries'; |
| b69ab31 | | | 15 | import { |
| b69ab31 | | | 16 | closeCommitInfoSidebar, |
| b69ab31 | | | 17 | COMMIT, |
| b69ab31 | | | 18 | expectMessageSentToServer, |
| b69ab31 | | | 19 | resetTestMessages, |
| b69ab31 | | | 20 | simulateCommits, |
| b69ab31 | | | 21 | simulateMessageFromServer, |
| b69ab31 | | | 22 | simulateRepoConnected, |
| b69ab31 | | | 23 | simulateUncommittedChangedFiles, |
| b69ab31 | | | 24 | } from '../testUtils'; |
| b69ab31 | | | 25 | import {leftPad} from '../utils'; |
| b69ab31 | | | 26 | |
| b69ab31 | | | 27 | jest.mock('isl-components/OperatingSystem', () => ({ |
| b69ab31 | | | 28 | isMac: true, |
| b69ab31 | | | 29 | })); |
| b69ab31 | | | 30 | |
| b69ab31 | | | 31 | describe('Changed Files', () => { |
| b69ab31 | | | 32 | beforeEach(() => { |
| b69ab31 | | | 33 | resetTestMessages(); |
| b69ab31 | | | 34 | render(<App />); |
| b69ab31 | | | 35 | act(() => { |
| b69ab31 | | | 36 | simulateRepoConnected(); |
| b69ab31 | | | 37 | closeCommitInfoSidebar(); |
| b69ab31 | | | 38 | expectMessageSentToServer({ |
| b69ab31 | | | 39 | type: 'subscribe', |
| b69ab31 | | | 40 | kind: 'smartlogCommits', |
| b69ab31 | | | 41 | subscriptionID: expect.anything(), |
| b69ab31 | | | 42 | }); |
| b69ab31 | | | 43 | simulateCommits({ |
| b69ab31 | | | 44 | value: [ |
| b69ab31 | | | 45 | COMMIT('1', 'some public base', '0', {phase: 'public'}), |
| b69ab31 | | | 46 | COMMIT('a', 'My Commit', '1'), |
| b69ab31 | | | 47 | COMMIT('b', 'Another Commit', 'a', {isDot: true}), |
| b69ab31 | | | 48 | ], |
| b69ab31 | | | 49 | }); |
| b69ab31 | | | 50 | // Reset to the default display type. |
| b69ab31 | | | 51 | act(() => { |
| b69ab31 | | | 52 | simulateMessageFromServer({ |
| b69ab31 | | | 53 | type: 'gotConfig', |
| b69ab31 | | | 54 | name: 'isl.changedFilesDisplayType', |
| b69ab31 | | | 55 | value: JSON.stringify(defaultChangedFilesDisplayType), |
| b69ab31 | | | 56 | }); |
| b69ab31 | | | 57 | }); |
| b69ab31 | | | 58 | expectMessageSentToServer({ |
| b69ab31 | | | 59 | type: 'subscribe', |
| b69ab31 | | | 60 | kind: 'uncommittedChanges', |
| b69ab31 | | | 61 | subscriptionID: expect.anything(), |
| b69ab31 | | | 62 | }); |
| b69ab31 | | | 63 | simulateUncommittedChangedFiles({ |
| b69ab31 | | | 64 | value: [ |
| b69ab31 | | | 65 | {path: 'file1.js', status: 'M'}, |
| b69ab31 | | | 66 | {path: 'src/file2.js', status: 'A'}, |
| b69ab31 | | | 67 | {path: 'src/file3.js', status: 'A'}, |
| b69ab31 | | | 68 | {path: 'src/a/foo.js', status: 'M'}, |
| b69ab31 | | | 69 | {path: 'src/b/foo.js', status: 'M'}, |
| b69ab31 | | | 70 | {path: 'src/subfolder/file4.js', status: 'R'}, |
| b69ab31 | | | 71 | {path: 'src/subfolder/another/yet/another/file5.js', status: 'R'}, |
| b69ab31 | | | 72 | ], |
| b69ab31 | | | 73 | }); |
| b69ab31 | | | 74 | }); |
| b69ab31 | | | 75 | }); |
| b69ab31 | | | 76 | |
| b69ab31 | | | 77 | function openChangedFileStatusPicker() { |
| b69ab31 | | | 78 | const picker = screen.getByTestId('changed-file-display-type-picker'); |
| b69ab31 | | | 79 | expect(picker).toBeInTheDocument(); |
| b69ab31 | | | 80 | |
| b69ab31 | | | 81 | act(() => { |
| b69ab31 | | | 82 | fireEvent.click(picker); |
| b69ab31 | | | 83 | }); |
| b69ab31 | | | 84 | } |
| b69ab31 | | | 85 | |
| b69ab31 | | | 86 | it('Allows picking changed files display type', () => { |
| b69ab31 | | | 87 | openChangedFileStatusPicker(); |
| b69ab31 | | | 88 | expect(screen.getByText('Short file names')).toBeInTheDocument(); |
| b69ab31 | | | 89 | expect(screen.getByText('Full file paths')).toBeInTheDocument(); |
| b69ab31 | | | 90 | expect(screen.getByText('Tree')).toBeInTheDocument(); |
| b69ab31 | | | 91 | expect(screen.getByText('One-letter directories')).toBeInTheDocument(); |
| b69ab31 | | | 92 | }); |
| b69ab31 | | | 93 | |
| b69ab31 | | | 94 | it('Persists choice for display type', () => { |
| b69ab31 | | | 95 | openChangedFileStatusPicker(); |
| b69ab31 | | | 96 | act(() => { |
| b69ab31 | | | 97 | fireEvent.click(screen.getByText('Tree')); |
| b69ab31 | | | 98 | }); |
| b69ab31 | | | 99 | expectMessageSentToServer({ |
| b69ab31 | | | 100 | type: 'setConfig', |
| b69ab31 | | | 101 | name: 'isl.changedFilesDisplayType', |
| b69ab31 | | | 102 | value: '"tree"', |
| b69ab31 | | | 103 | }); |
| b69ab31 | | | 104 | }); |
| b69ab31 | | | 105 | |
| b69ab31 | | | 106 | it('Updates when config is fetched', () => { |
| b69ab31 | | | 107 | openChangedFileStatusPicker(); |
| b69ab31 | | | 108 | act(() => { |
| b69ab31 | | | 109 | simulateMessageFromServer({ |
| b69ab31 | | | 110 | type: 'gotConfig', |
| b69ab31 | | | 111 | name: 'isl.changedFilesDisplayType', |
| b69ab31 | | | 112 | value: '"fullPaths"', |
| b69ab31 | | | 113 | }); |
| b69ab31 | | | 114 | }); |
| b69ab31 | | | 115 | expect(screen.getByText(ignoreRTL('src/file2.js'))).toBeInTheDocument(); |
| b69ab31 | | | 116 | }); |
| b69ab31 | | | 117 | |
| b69ab31 | | | 118 | it('Uses LTR markers to render paths correctly', () => { |
| b69ab31 | | | 119 | act(() => { |
| b69ab31 | | | 120 | simulateUncommittedChangedFiles({ |
| b69ab31 | | | 121 | value: [ |
| b69ab31 | | | 122 | {path: '.gitignore', status: 'M'}, |
| b69ab31 | | | 123 | {path: 'src/.gitignore', status: 'A'}, |
| b69ab31 | | | 124 | ], |
| b69ab31 | | | 125 | }); |
| b69ab31 | | | 126 | }); |
| b69ab31 | | | 127 | expect(screen.getByText('\u200E.gitignore\u200E')).toBeInTheDocument(); |
| b69ab31 | | | 128 | expect(screen.getByText('\u200Esrc/.gitignore\u200E')).toBeInTheDocument(); |
| b69ab31 | | | 129 | }); |
| b69ab31 | | | 130 | |
| b69ab31 | | | 131 | describe('default changed files', () => { |
| b69ab31 | | | 132 | it('disambiguates file paths', () => { |
| b69ab31 | | | 133 | expect(screen.getByText(ignoreRTL('file1.js'))).toBeInTheDocument(); |
| b69ab31 | | | 134 | expect(screen.getByText(ignoreRTL('file2.js'))).toBeInTheDocument(); |
| b69ab31 | | | 135 | expect(screen.getByText(ignoreRTL('a/foo.js'))).toBeInTheDocument(); |
| b69ab31 | | | 136 | expect(screen.getByText(ignoreRTL('b/foo.js'))).toBeInTheDocument(); |
| b69ab31 | | | 137 | |
| b69ab31 | | | 138 | expect(screen.queryByText(ignoreRTL('src/file2.js'))).not.toBeInTheDocument(); |
| b69ab31 | | | 139 | }); |
| b69ab31 | | | 140 | }); |
| b69ab31 | | | 141 | |
| b69ab31 | | | 142 | describe('full file paths', () => { |
| b69ab31 | | | 143 | it('shows full paths', () => { |
| b69ab31 | | | 144 | openChangedFileStatusPicker(); |
| b69ab31 | | | 145 | act(() => { |
| b69ab31 | | | 146 | fireEvent.click(screen.getByText('Full file paths')); |
| b69ab31 | | | 147 | }); |
| b69ab31 | | | 148 | |
| b69ab31 | | | 149 | expect(screen.getByText(ignoreRTL('file1.js'))).toBeInTheDocument(); |
| b69ab31 | | | 150 | expect(screen.getByText(ignoreRTL('src/file2.js'))).toBeInTheDocument(); |
| b69ab31 | | | 151 | expect(screen.getByText(ignoreRTL('src/a/foo.js'))).toBeInTheDocument(); |
| b69ab31 | | | 152 | expect(screen.getByText(ignoreRTL('src/b/foo.js'))).toBeInTheDocument(); |
| b69ab31 | | | 153 | expect( |
| b69ab31 | | | 154 | screen.getByText(ignoreRTL('src/subfolder/another/yet/another/file5.js')), |
| b69ab31 | | | 155 | ).toBeInTheDocument(); |
| b69ab31 | | | 156 | }); |
| b69ab31 | | | 157 | |
| b69ab31 | | | 158 | it('shows full paths when holding alt', () => { |
| b69ab31 | | | 159 | expect(screen.queryByText(ignoreRTL('src/b/foo.js'))).not.toBeInTheDocument(); |
| b69ab31 | | | 160 | act(() => { |
| b69ab31 | | | 161 | userEvent.keyboard('{Alt>}'); // '>' means keep pressed |
| b69ab31 | | | 162 | }); |
| b69ab31 | | | 163 | expect(screen.getByText(ignoreRTL('file1.js'))).toBeInTheDocument(); |
| b69ab31 | | | 164 | expect(screen.getByText(ignoreRTL('src/file2.js'))).toBeInTheDocument(); |
| b69ab31 | | | 165 | expect(screen.getByText(ignoreRTL('src/a/foo.js'))).toBeInTheDocument(); |
| b69ab31 | | | 166 | expect(screen.getByText(ignoreRTL('src/b/foo.js'))).toBeInTheDocument(); |
| b69ab31 | | | 167 | expect( |
| b69ab31 | | | 168 | screen.getByText(ignoreRTL('src/subfolder/another/yet/another/file5.js')), |
| b69ab31 | | | 169 | ).toBeInTheDocument(); |
| b69ab31 | | | 170 | }); |
| b69ab31 | | | 171 | }); |
| b69ab31 | | | 172 | |
| b69ab31 | | | 173 | describe('one-letter-per-directory file paths', () => { |
| b69ab31 | | | 174 | it('shows one-letter-per-directory file paths', () => { |
| b69ab31 | | | 175 | openChangedFileStatusPicker(); |
| b69ab31 | | | 176 | act(() => { |
| b69ab31 | | | 177 | fireEvent.click(screen.getByText('One-letter directories')); |
| b69ab31 | | | 178 | }); |
| b69ab31 | | | 179 | |
| b69ab31 | | | 180 | expect(screen.getByText(ignoreRTL('file1.js'))).toBeInTheDocument(); |
| b69ab31 | | | 181 | expect(screen.getByText(ignoreRTL('s/file2.js'))).toBeInTheDocument(); |
| b69ab31 | | | 182 | expect(screen.getByText(ignoreRTL('s/a/foo.js'))).toBeInTheDocument(); |
| b69ab31 | | | 183 | expect(screen.getByText(ignoreRTL('s/b/foo.js'))).toBeInTheDocument(); |
| b69ab31 | | | 184 | expect(screen.getByText(ignoreRTL('s/s/file4.js'))).toBeInTheDocument(); |
| b69ab31 | | | 185 | expect(screen.getByText(ignoreRTL('s/s/a/y/a/file5.js'))).toBeInTheDocument(); |
| b69ab31 | | | 186 | }); |
| b69ab31 | | | 187 | }); |
| b69ab31 | | | 188 | |
| b69ab31 | | | 189 | describe('tree', () => { |
| b69ab31 | | | 190 | beforeEach(() => { |
| b69ab31 | | | 191 | openChangedFileStatusPicker(); |
| b69ab31 | | | 192 | act(() => { |
| b69ab31 | | | 193 | fireEvent.click(screen.getByText('Tree')); |
| b69ab31 | | | 194 | }); |
| b69ab31 | | | 195 | }); |
| b69ab31 | | | 196 | |
| b69ab31 | | | 197 | it('shows non-disambiguated file basenames', () => { |
| b69ab31 | | | 198 | expect(screen.getByText(ignoreRTL('file1.js'))).toBeInTheDocument(); |
| b69ab31 | | | 199 | expect(screen.getByText(ignoreRTL('file2.js'))).toBeInTheDocument(); |
| b69ab31 | | | 200 | expect(screen.getByText(ignoreRTL('file3.js'))).toBeInTheDocument(); |
| b69ab31 | | | 201 | expect(screen.getAllByText(ignoreRTL('foo.js'))).toHaveLength(2); |
| b69ab31 | | | 202 | expect(screen.getByText(ignoreRTL('file4.js'))).toBeInTheDocument(); |
| b69ab31 | | | 203 | expect(screen.getByText(ignoreRTL('file5.js'))).toBeInTheDocument(); |
| b69ab31 | | | 204 | }); |
| b69ab31 | | | 205 | |
| b69ab31 | | | 206 | it('shows folder names', () => { |
| b69ab31 | | | 207 | expect(screen.getByText(ignoreRTL('src'))).toBeInTheDocument(); |
| b69ab31 | | | 208 | expect(screen.getByText(ignoreRTL('a'))).toBeInTheDocument(); |
| b69ab31 | | | 209 | expect(screen.getByText(ignoreRTL('b'))).toBeInTheDocument(); |
| b69ab31 | | | 210 | expect(screen.getByText(ignoreRTL('subfolder'))).toBeInTheDocument(); |
| b69ab31 | | | 211 | expect(screen.getByText(ignoreRTL('another/yet/another'))).toBeInTheDocument(); |
| b69ab31 | | | 212 | }); |
| b69ab31 | | | 213 | |
| b69ab31 | | | 214 | it('clicking folder name hides contents', () => { |
| b69ab31 | | | 215 | act(() => { |
| b69ab31 | | | 216 | fireEvent.click(screen.getByText('subfolder')); |
| b69ab31 | | | 217 | }); |
| b69ab31 | | | 218 | expect(screen.queryByText(ignoreRTL('file4.js'))).not.toBeInTheDocument(); |
| b69ab31 | | | 219 | expect(screen.queryByText(ignoreRTL('file5.js'))).not.toBeInTheDocument(); |
| b69ab31 | | | 220 | |
| b69ab31 | | | 221 | expect(screen.getByText(ignoreRTL('file1.js'))).toBeInTheDocument(); |
| b69ab31 | | | 222 | expect(screen.getByText(ignoreRTL('file2.js'))).toBeInTheDocument(); |
| b69ab31 | | | 223 | expect(screen.getByText(ignoreRTL('file3.js'))).toBeInTheDocument(); |
| b69ab31 | | | 224 | }); |
| b69ab31 | | | 225 | |
| b69ab31 | | | 226 | it('clicking folders with the same name do not collapse each other', () => { |
| b69ab31 | | | 227 | act(() => { |
| b69ab31 | | | 228 | simulateUncommittedChangedFiles({ |
| b69ab31 | | | 229 | value: [ |
| b69ab31 | | | 230 | {path: 'a/foo/file1.js', status: 'M'}, |
| b69ab31 | | | 231 | {path: 'a/file2.js', status: 'M'}, |
| b69ab31 | | | 232 | {path: 'b/foo/file3.js', status: 'M'}, |
| b69ab31 | | | 233 | {path: 'b/file4.js', status: 'M'}, |
| b69ab31 | | | 234 | ], |
| b69ab31 | | | 235 | }); |
| b69ab31 | | | 236 | }); |
| b69ab31 | | | 237 | act(() => { |
| b69ab31 | | | 238 | fireEvent.click(screen.getAllByText('foo')[0]); |
| b69ab31 | | | 239 | }); |
| b69ab31 | | | 240 | expect(screen.queryByText(ignoreRTL('file1.js'))).not.toBeInTheDocument(); |
| b69ab31 | | | 241 | expect(screen.queryByText(ignoreRTL('file3.js'))).toBeInTheDocument(); |
| b69ab31 | | | 242 | }); |
| b69ab31 | | | 243 | }); |
| b69ab31 | | | 244 | |
| b69ab31 | | | 245 | describe('truncated list of changed files', () => { |
| b69ab31 | | | 246 | function makeFiles(n: number): Array<RepoRelativePath> { |
| b69ab31 | | | 247 | return new Array(n).fill(null).map((_, i) => `file${leftPad(i, 3, '0')}.txt`); |
| b69ab31 | | | 248 | } |
| b69ab31 | | | 249 | |
| b69ab31 | | | 250 | function withStatus( |
| b69ab31 | | | 251 | changes: Array<RepoRelativePath>, |
| b69ab31 | | | 252 | status: ChangedFileStatus, |
| b69ab31 | | | 253 | ): UncommittedChanges { |
| b69ab31 | | | 254 | return changes.map(path => ({path, status})); |
| b69ab31 | | | 255 | } |
| b69ab31 | | | 256 | |
| b69ab31 | | | 257 | it('only first 500 files are shown', () => { |
| b69ab31 | | | 258 | act(() => { |
| b69ab31 | | | 259 | simulateUncommittedChangedFiles({ |
| b69ab31 | | | 260 | value: withStatus(makeFiles(510), 'M'), |
| b69ab31 | | | 261 | }); |
| b69ab31 | | | 262 | }); |
| b69ab31 | | | 263 | const files = screen.getAllByText(/file\d+\.txt/); |
| b69ab31 | | | 264 | expect(files).toHaveLength(500); |
| b69ab31 | | | 265 | }); |
| b69ab31 | | | 266 | |
| b69ab31 | | | 267 | it('banner is shown if some files are hidden', () => { |
| b69ab31 | | | 268 | act(() => { |
| b69ab31 | | | 269 | simulateUncommittedChangedFiles({ |
| b69ab31 | | | 270 | value: withStatus(makeFiles(700), 'M'), |
| b69ab31 | | | 271 | }); |
| b69ab31 | | | 272 | }); |
| b69ab31 | | | 273 | expect(screen.getByText('Showing first 500 files out of 700 total')).toBeInTheDocument(); |
| b69ab31 | | | 274 | }); |
| b69ab31 | | | 275 | |
| b69ab31 | | | 276 | it('if more than 500 files are provided, there are page navigation buttons', () => { |
| b69ab31 | | | 277 | act(() => { |
| b69ab31 | | | 278 | simulateUncommittedChangedFiles({ |
| b69ab31 | | | 279 | value: withStatus(makeFiles(510), 'M'), |
| b69ab31 | | | 280 | }); |
| b69ab31 | | | 281 | }); |
| b69ab31 | | | 282 | expect(screen.getByTestId('changed-files-next-page')).toBeInTheDocument(); |
| b69ab31 | | | 283 | expect(screen.getByTestId('changed-files-previous-page')).toBeInTheDocument(); |
| b69ab31 | | | 284 | expect(screen.getByTestId('changed-files-previous-page')).toBeDisabled(); |
| b69ab31 | | | 285 | expect(screen.getByText('Showing first 500 files out of 510 total')).toBeInTheDocument(); |
| b69ab31 | | | 286 | }); |
| b69ab31 | | | 287 | |
| b69ab31 | | | 288 | it('can click buttons to navigate pages', () => { |
| b69ab31 | | | 289 | act(() => { |
| b69ab31 | | | 290 | simulateUncommittedChangedFiles({ |
| b69ab31 | | | 291 | value: withStatus(makeFiles(1010), 'M'), |
| b69ab31 | | | 292 | }); |
| b69ab31 | | | 293 | }); |
| b69ab31 | | | 294 | fireEvent.click(screen.getByTestId('changed-files-next-page')); |
| b69ab31 | | | 295 | expect(screen.getByText('Showing files 501 – 1000 out of 1010 total')).toBeInTheDocument(); |
| b69ab31 | | | 296 | fireEvent.click(screen.getByTestId('changed-files-next-page')); |
| b69ab31 | | | 297 | expect(screen.getByText('Showing files 1001 – 1010 out of 1010 total')).toBeInTheDocument(); |
| b69ab31 | | | 298 | |
| b69ab31 | | | 299 | expect(screen.getByTestId('changed-files-next-page')).toBeDisabled(); |
| b69ab31 | | | 300 | |
| b69ab31 | | | 301 | fireEvent.click(screen.getByTestId('changed-files-previous-page')); |
| b69ab31 | | | 302 | expect(screen.getByText('Showing files 501 – 1000 out of 1010 total')).toBeInTheDocument(); |
| b69ab31 | | | 303 | fireEvent.click(screen.getByTestId('changed-files-previous-page')); |
| b69ab31 | | | 304 | expect(screen.getByText('Showing first 500 files out of 1010 total')).toBeInTheDocument(); |
| b69ab31 | | | 305 | }); |
| b69ab31 | | | 306 | |
| b69ab31 | | | 307 | it("if more than 500 files exist, but only 500 are provided, don't show pagination buttons", () => { |
| b69ab31 | | | 308 | act(() => { |
| b69ab31 | | | 309 | simulateUncommittedChangedFiles({ |
| b69ab31 | | | 310 | value: [], |
| b69ab31 | | | 311 | }); |
| b69ab31 | | | 312 | simulateCommits({ |
| b69ab31 | | | 313 | value: [ |
| b69ab31 | | | 314 | COMMIT('1', 'some public base', '0', {phase: 'public'}), |
| b69ab31 | | | 315 | COMMIT('a', 'Commit', '1', { |
| b69ab31 | | | 316 | isDot: true, |
| b69ab31 | | | 317 | filePathsSample: makeFiles(500), |
| b69ab31 | | | 318 | totalFileCount: 1010, |
| b69ab31 | | | 319 | }), |
| b69ab31 | | | 320 | ], |
| b69ab31 | | | 321 | }); |
| b69ab31 | | | 322 | CommitInfoTestUtils.openCommitInfoSidebar(); |
| b69ab31 | | | 323 | }); |
| b69ab31 | | | 324 | |
| b69ab31 | | | 325 | const changedFiles = CommitInfoTestUtils.withinCommitInfo().getByTestId('changed-files'); |
| b69ab31 | | | 326 | expect(changedFiles).toBeInTheDocument(); |
| b69ab31 | | | 327 | |
| b69ab31 | | | 328 | // banner shows truncation |
| b69ab31 | | | 329 | expect( |
| b69ab31 | | | 330 | CommitInfoTestUtils.withinCommitInfo().getByText( |
| b69ab31 | | | 331 | 'Showing first 500 files out of 1010 total', |
| b69ab31 | | | 332 | ), |
| b69ab31 | | | 333 | ).toBeInTheDocument(); |
| b69ab31 | | | 334 | |
| b69ab31 | | | 335 | // but no pagination buttons, since we only provide first 25 anyway |
| b69ab31 | | | 336 | expect( |
| b69ab31 | | | 337 | CommitInfoTestUtils.withinCommitInfo().queryByTestId('changed-files-next-page'), |
| b69ab31 | | | 338 | ).not.toBeInTheDocument(); |
| b69ab31 | | | 339 | expect( |
| b69ab31 | | | 340 | CommitInfoTestUtils.withinCommitInfo().queryByTestId('changed-files-previous-page'), |
| b69ab31 | | | 341 | ).not.toBeInTheDocument(); |
| b69ab31 | | | 342 | }); |
| b69ab31 | | | 343 | |
| b69ab31 | | | 344 | it('if the number of files changes, restrict the page number to fit', () => { |
| b69ab31 | | | 345 | act(() => { |
| b69ab31 | | | 346 | simulateUncommittedChangedFiles({ |
| b69ab31 | | | 347 | value: withStatus(makeFiles(2020), 'M'), |
| b69ab31 | | | 348 | }); |
| b69ab31 | | | 349 | }); |
| b69ab31 | | | 350 | fireEvent.click(screen.getByTestId('changed-files-next-page')); |
| b69ab31 | | | 351 | fireEvent.click(screen.getByTestId('changed-files-next-page')); |
| b69ab31 | | | 352 | fireEvent.click(screen.getByTestId('changed-files-next-page')); |
| b69ab31 | | | 353 | fireEvent.click(screen.getByTestId('changed-files-next-page')); |
| b69ab31 | | | 354 | expect(screen.getByText('Showing files 2001 – 2020 out of 2020 total')).toBeInTheDocument(); |
| b69ab31 | | | 355 | |
| b69ab31 | | | 356 | // now some file changes are removed (e.g. discarded) |
| b69ab31 | | | 357 | act(() => { |
| b69ab31 | | | 358 | simulateUncommittedChangedFiles({ |
| b69ab31 | | | 359 | value: withStatus(makeFiles(700), 'M'), |
| b69ab31 | | | 360 | }); |
| b69ab31 | | | 361 | }); |
| b69ab31 | | | 362 | |
| b69ab31 | | | 363 | // ranges are remapped |
| b69ab31 | | | 364 | expect(screen.getByText('Showing files 501 – 700 out of 700 total')).toBeInTheDocument(); |
| b69ab31 | | | 365 | }); |
| b69ab31 | | | 366 | }); |
| b69ab31 | | | 367 | }); |