| 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 {act, fireEvent, render, screen, within} from '@testing-library/react'; |
| b69ab31 | | | 9 | import App from '../App'; |
| b69ab31 | | | 10 | import {bookmarksDataStorage} from '../BookmarksData'; |
| b69ab31 | | | 11 | import {writeAtom} from '../jotaiUtils'; |
| b69ab31 | | | 12 | import { |
| b69ab31 | | | 13 | COMMIT, |
| b69ab31 | | | 14 | closeCommitInfoSidebar, |
| b69ab31 | | | 15 | expectMessageSentToServer, |
| b69ab31 | | | 16 | resetTestMessages, |
| b69ab31 | | | 17 | simulateCommits, |
| b69ab31 | | | 18 | simulateRepoConnected, |
| b69ab31 | | | 19 | } from '../testUtils'; |
| b69ab31 | | | 20 | import {succeedableRevset} from '../types'; |
| b69ab31 | | | 21 | |
| b69ab31 | | | 22 | describe('Suggested Rebase button', () => { |
| b69ab31 | | | 23 | beforeEach(() => { |
| b69ab31 | | | 24 | resetTestMessages(); |
| b69ab31 | | | 25 | render(<App />); |
| b69ab31 | | | 26 | act(() => { |
| b69ab31 | | | 27 | simulateRepoConnected(); |
| b69ab31 | | | 28 | closeCommitInfoSidebar(); |
| b69ab31 | | | 29 | expectMessageSentToServer({ |
| b69ab31 | | | 30 | type: 'subscribe', |
| b69ab31 | | | 31 | kind: 'smartlogCommits', |
| b69ab31 | | | 32 | subscriptionID: expect.anything(), |
| b69ab31 | | | 33 | }); |
| b69ab31 | | | 34 | simulateCommits({ |
| b69ab31 | | | 35 | value: [ |
| b69ab31 | | | 36 | COMMIT('1', 'some public base', '0', {phase: 'public'}), |
| b69ab31 | | | 37 | COMMIT('a', 'My Commit', '1'), |
| b69ab31 | | | 38 | COMMIT('b', 'Another Commit', 'a', {isDot: true}), |
| b69ab31 | | | 39 | ], |
| b69ab31 | | | 40 | }); |
| b69ab31 | | | 41 | }); |
| b69ab31 | | | 42 | }); |
| b69ab31 | | | 43 | |
| b69ab31 | | | 44 | it('shows suggested rebase button', () => { |
| b69ab31 | | | 45 | act(() => { |
| b69ab31 | | | 46 | simulateCommits({ |
| b69ab31 | | | 47 | value: [ |
| b69ab31 | | | 48 | COMMIT('main', 'main', '2', {phase: 'public', remoteBookmarks: ['remote/main']}), |
| b69ab31 | | | 49 | COMMIT('1', 'some public base', '0', {phase: 'public'}), |
| b69ab31 | | | 50 | COMMIT('a', 'My Commit', '1'), |
| b69ab31 | | | 51 | COMMIT('b', 'Another Commit', 'a', {isDot: true}), |
| b69ab31 | | | 52 | ], |
| b69ab31 | | | 53 | }); |
| b69ab31 | | | 54 | }); |
| b69ab31 | | | 55 | |
| b69ab31 | | | 56 | expect(screen.getByText(`Rebase onto…`)).toBeInTheDocument(); |
| b69ab31 | | | 57 | }); |
| b69ab31 | | | 58 | |
| b69ab31 | | | 59 | it('does not show suggested rebase button on commits already on a remote bookmark', () => { |
| b69ab31 | | | 60 | act(() => { |
| b69ab31 | | | 61 | simulateCommits({ |
| b69ab31 | | | 62 | value: [ |
| b69ab31 | | | 63 | COMMIT('main', 'main', '2', {phase: 'public', remoteBookmarks: ['remote/main']}), |
| b69ab31 | | | 64 | COMMIT('1', 'some public base', '0', {phase: 'public'}), |
| b69ab31 | | | 65 | COMMIT('a', 'My Commit', '2'), // on remote/main |
| b69ab31 | | | 66 | COMMIT('b', 'Another Commit', 'a', {isDot: true}), |
| b69ab31 | | | 67 | ], |
| b69ab31 | | | 68 | }); |
| b69ab31 | | | 69 | }); |
| b69ab31 | | | 70 | |
| b69ab31 | | | 71 | expect(screen.queryByText('Rebase onto…')).not.toBeInTheDocument(); |
| b69ab31 | | | 72 | }); |
| b69ab31 | | | 73 | |
| b69ab31 | | | 74 | it('does not show suggested rebase button on commits already on a stable location', () => { |
| b69ab31 | | | 75 | act(() => { |
| b69ab31 | | | 76 | simulateCommits({ |
| b69ab31 | | | 77 | value: [ |
| b69ab31 | | | 78 | COMMIT('main', 'main', '2', { |
| b69ab31 | | | 79 | phase: 'public', |
| b69ab31 | | | 80 | stableCommitMetadata: [{value: 'pulled here', description: ''}], |
| b69ab31 | | | 81 | }), |
| b69ab31 | | | 82 | COMMIT('1', 'some public base', '0', {phase: 'public'}), |
| b69ab31 | | | 83 | COMMIT('a', 'My Commit', '2'), // on stable |
| b69ab31 | | | 84 | COMMIT('b', 'Another Commit', 'a', {isDot: true}), |
| b69ab31 | | | 85 | ], |
| b69ab31 | | | 86 | }); |
| b69ab31 | | | 87 | }); |
| b69ab31 | | | 88 | |
| b69ab31 | | | 89 | expect(screen.queryByText('Rebase onto…')).not.toBeInTheDocument(); |
| b69ab31 | | | 90 | }); |
| b69ab31 | | | 91 | |
| b69ab31 | | | 92 | it('shows remote bookmarks as destinations in dropdown', () => { |
| b69ab31 | | | 93 | act(() => { |
| b69ab31 | | | 94 | simulateCommits({ |
| b69ab31 | | | 95 | value: [ |
| b69ab31 | | | 96 | COMMIT('main', 'main', '2', { |
| b69ab31 | | | 97 | phase: 'public', |
| b69ab31 | | | 98 | remoteBookmarks: ['remote/main'], |
| b69ab31 | | | 99 | }), |
| b69ab31 | | | 100 | COMMIT('1', 'some public base', '0', {phase: 'public'}), |
| b69ab31 | | | 101 | COMMIT('a', 'My Commit', '1'), |
| b69ab31 | | | 102 | COMMIT('b', 'Another Commit', 'a', {isDot: true}), |
| b69ab31 | | | 103 | ], |
| b69ab31 | | | 104 | }); |
| b69ab31 | | | 105 | }); |
| b69ab31 | | | 106 | |
| b69ab31 | | | 107 | const rebaseOntoButton = screen.getByText('Rebase onto…'); |
| b69ab31 | | | 108 | fireEvent.click(rebaseOntoButton); |
| b69ab31 | | | 109 | |
| b69ab31 | | | 110 | expect( |
| b69ab31 | | | 111 | within(screen.getByTestId('context-menu-container')).getByText('remote/main'), |
| b69ab31 | | | 112 | ).toBeInTheDocument(); |
| b69ab31 | | | 113 | }); |
| b69ab31 | | | 114 | |
| b69ab31 | | | 115 | it('shows stable locations as destinations in dropdown', () => { |
| b69ab31 | | | 116 | act(() => { |
| b69ab31 | | | 117 | simulateCommits({ |
| b69ab31 | | | 118 | value: [ |
| b69ab31 | | | 119 | COMMIT('main', 'main', '2', { |
| b69ab31 | | | 120 | phase: 'public', |
| b69ab31 | | | 121 | stableCommitMetadata: [{value: 'pulled here', description: ''}], |
| b69ab31 | | | 122 | }), |
| b69ab31 | | | 123 | COMMIT('1', 'some public base', '0', {phase: 'public'}), |
| b69ab31 | | | 124 | COMMIT('a', 'My Commit', '1'), |
| b69ab31 | | | 125 | COMMIT('b', 'Another Commit', 'a', {isDot: true}), |
| b69ab31 | | | 126 | ], |
| b69ab31 | | | 127 | }); |
| b69ab31 | | | 128 | }); |
| b69ab31 | | | 129 | |
| b69ab31 | | | 130 | const rebaseOntoButton = screen.getByText(`Rebase onto…`); |
| b69ab31 | | | 131 | fireEvent.click(rebaseOntoButton); |
| b69ab31 | | | 132 | |
| b69ab31 | | | 133 | expect( |
| b69ab31 | | | 134 | within(screen.getByTestId('context-menu-container')).getByText('pulled here'), |
| b69ab31 | | | 135 | ).toBeInTheDocument(); |
| b69ab31 | | | 136 | }); |
| b69ab31 | | | 137 | |
| b69ab31 | | | 138 | it('clicking suggestion rebase runs operation', () => { |
| b69ab31 | | | 139 | act(() => { |
| b69ab31 | | | 140 | simulateCommits({ |
| b69ab31 | | | 141 | value: [ |
| b69ab31 | | | 142 | COMMIT('main', 'main', '2', { |
| b69ab31 | | | 143 | phase: 'public', |
| b69ab31 | | | 144 | remoteBookmarks: ['remote/main'], |
| b69ab31 | | | 145 | }), |
| b69ab31 | | | 146 | COMMIT('1', 'some public base', '0', {phase: 'public'}), |
| b69ab31 | | | 147 | COMMIT('a', 'My Commit', '1'), |
| b69ab31 | | | 148 | COMMIT('b', 'Another Commit', 'a', {isDot: true}), |
| b69ab31 | | | 149 | ], |
| b69ab31 | | | 150 | }); |
| b69ab31 | | | 151 | }); |
| b69ab31 | | | 152 | |
| b69ab31 | | | 153 | const rebaseOntoButton = screen.getByText('Rebase onto…'); |
| b69ab31 | | | 154 | fireEvent.click(rebaseOntoButton); |
| b69ab31 | | | 155 | |
| b69ab31 | | | 156 | const suggestion = within(screen.getByTestId('context-menu-container')).getByText( |
| b69ab31 | | | 157 | 'remote/main', |
| b69ab31 | | | 158 | ); |
| b69ab31 | | | 159 | fireEvent.click(suggestion); |
| b69ab31 | | | 160 | |
| b69ab31 | | | 161 | expectMessageSentToServer({ |
| b69ab31 | | | 162 | type: 'runOperation', |
| b69ab31 | | | 163 | operation: expect.objectContaining({ |
| b69ab31 | | | 164 | args: ['rebase', '-s', succeedableRevset('a'), '-d', succeedableRevset('remote/main')], |
| b69ab31 | | | 165 | }), |
| b69ab31 | | | 166 | }); |
| b69ab31 | | | 167 | }); |
| b69ab31 | | | 168 | |
| b69ab31 | | | 169 | it('uses hash to run rebase operation if not a remote bookmark', () => { |
| b69ab31 | | | 170 | act(() => { |
| b69ab31 | | | 171 | simulateCommits({ |
| b69ab31 | | | 172 | value: [ |
| b69ab31 | | | 173 | COMMIT('3', 'main', '2', { |
| b69ab31 | | | 174 | phase: 'public', |
| b69ab31 | | | 175 | stableCommitMetadata: [{value: 'pulled here', description: ''}], |
| b69ab31 | | | 176 | }), |
| b69ab31 | | | 177 | COMMIT('1', 'some public base', '0', {phase: 'public'}), |
| b69ab31 | | | 178 | COMMIT('a', 'My Commit', '1'), |
| b69ab31 | | | 179 | COMMIT('b', 'Another Commit', 'a', {isDot: true}), |
| b69ab31 | | | 180 | ], |
| b69ab31 | | | 181 | }); |
| b69ab31 | | | 182 | }); |
| b69ab31 | | | 183 | |
| b69ab31 | | | 184 | const rebaseOntoButton = screen.getByText('Rebase onto…'); |
| b69ab31 | | | 185 | fireEvent.click(rebaseOntoButton); |
| b69ab31 | | | 186 | |
| b69ab31 | | | 187 | const suggestion = within(screen.getByTestId('context-menu-container')).getByText( |
| b69ab31 | | | 188 | 'pulled here', |
| b69ab31 | | | 189 | ); |
| b69ab31 | | | 190 | fireEvent.click(suggestion); |
| b69ab31 | | | 191 | |
| b69ab31 | | | 192 | expectMessageSentToServer({ |
| b69ab31 | | | 193 | type: 'runOperation', |
| b69ab31 | | | 194 | operation: expect.objectContaining({ |
| b69ab31 | | | 195 | args: ['rebase', '-s', succeedableRevset('a'), '-d', succeedableRevset('3')], |
| b69ab31 | | | 196 | }), |
| b69ab31 | | | 197 | }); |
| b69ab31 | | | 198 | }); |
| b69ab31 | | | 199 | |
| b69ab31 | | | 200 | it('includes current stack base as a destination', () => { |
| b69ab31 | | | 201 | act(() => { |
| b69ab31 | | | 202 | simulateCommits({ |
| b69ab31 | | | 203 | value: [ |
| b69ab31 | | | 204 | COMMIT('3', 'main', '2', {phase: 'public'}), |
| b69ab31 | | | 205 | COMMIT('x', 'Commit X', '2', {isDot: true}), |
| b69ab31 | | | 206 | COMMIT('2', 'some public base 2', '0', { |
| b69ab31 | | | 207 | phase: 'public', |
| b69ab31 | | | 208 | remoteBookmarks: ['remote/main'], |
| b69ab31 | | | 209 | }), |
| b69ab31 | | | 210 | COMMIT('1', 'some public base', '0', {phase: 'public'}), |
| b69ab31 | | | 211 | COMMIT('b', 'Another Commit', 'a'), |
| b69ab31 | | | 212 | COMMIT('a', 'My Commit', '1'), |
| b69ab31 | | | 213 | ], |
| b69ab31 | | | 214 | }); |
| b69ab31 | | | 215 | }); |
| b69ab31 | | | 216 | |
| b69ab31 | | | 217 | const rebaseOntoButton = screen.getByText('Rebase onto…'); |
| b69ab31 | | | 218 | fireEvent.click(rebaseOntoButton); |
| b69ab31 | | | 219 | |
| b69ab31 | | | 220 | const suggestion = within(screen.getByTestId('context-menu-container')).getByText( |
| b69ab31 | | | 221 | /Current Stack Base \(.*\), remote\/main/, |
| b69ab31 | | | 222 | ); |
| b69ab31 | | | 223 | fireEvent.click(suggestion); |
| b69ab31 | | | 224 | |
| b69ab31 | | | 225 | expectMessageSentToServer({ |
| b69ab31 | | | 226 | type: 'runOperation', |
| b69ab31 | | | 227 | operation: expect.objectContaining({ |
| b69ab31 | | | 228 | args: ['rebase', '-s', succeedableRevset('a'), '-d', succeedableRevset('remote/main')], |
| b69ab31 | | | 229 | }), |
| b69ab31 | | | 230 | }); |
| b69ab31 | | | 231 | }); |
| b69ab31 | | | 232 | |
| b69ab31 | | | 233 | it('deselected remote bookmarks in bookmark manager hides them as suggested rebases', () => { |
| b69ab31 | | | 234 | act(() => { |
| b69ab31 | | | 235 | writeAtom(bookmarksDataStorage, data => ({ |
| b69ab31 | | | 236 | ...data, |
| b69ab31 | | | 237 | useRecommendedBookmark: false, |
| b69ab31 | | | 238 | })); |
| b69ab31 | | | 239 | |
| b69ab31 | | | 240 | simulateCommits({ |
| b69ab31 | | | 241 | value: [ |
| b69ab31 | | | 242 | COMMIT('3', 'main', '000', {phase: 'public', remoteBookmarks: ['remote/main']}), |
| b69ab31 | | | 243 | COMMIT('2', 'something else', '00', {phase: 'public', remoteBookmarks: ['remote/foo']}), |
| b69ab31 | | | 244 | COMMIT('1', 'base', '0', {phase: 'public'}), |
| b69ab31 | | | 245 | COMMIT('a', 'My Commit', '1'), |
| b69ab31 | | | 246 | COMMIT('b', 'Another Commit', 'a', {isDot: true}), |
| b69ab31 | | | 247 | ], |
| b69ab31 | | | 248 | }); |
| b69ab31 | | | 249 | }); |
| b69ab31 | | | 250 | |
| b69ab31 | | | 251 | fireEvent.click(screen.getByTestId('bookmarks-manager-button')); |
| b69ab31 | | | 252 | |
| b69ab31 | | | 253 | const fooBookmark = within(screen.getByTestId('bookmarks-manager-dropdown')).getByText( |
| b69ab31 | | | 254 | 'remote/foo', |
| b69ab31 | | | 255 | ); |
| b69ab31 | | | 256 | expect(fooBookmark).toBeInTheDocument(); |
| b69ab31 | | | 257 | fireEvent.click(fooBookmark); // deselect |
| b69ab31 | | | 258 | |
| b69ab31 | | | 259 | const rebaseOntoButton = screen.getByText(`Rebase onto…`); |
| b69ab31 | | | 260 | fireEvent.click(rebaseOntoButton); |
| b69ab31 | | | 261 | |
| b69ab31 | | | 262 | expect( |
| b69ab31 | | | 263 | within(screen.getByTestId('context-menu-container')).queryByText('remote/foo'), |
| b69ab31 | | | 264 | ).not.toBeInTheDocument(); |
| b69ab31 | | | 265 | }); |
| b69ab31 | | | 266 | }); |