From ad9ef9d2e777e0f1d0a589e1e79c8477c7faadca Mon Sep 17 00:00:00 2001 From: Jialin Zhang Date: Mon, 13 May 2024 10:41:49 -0700 Subject: [PATCH] fix git initial user and email setup --- .../test-components/GitPanel.spec.tsx | 206 ++++++++++++++++-- src/components/GitPanel.tsx | 2 +- 2 files changed, 193 insertions(+), 15 deletions(-) diff --git a/src/__tests__/test-components/GitPanel.spec.tsx b/src/__tests__/test-components/GitPanel.spec.tsx index 05dbd1b3c..b8e870e6a 100644 --- a/src/__tests__/test-components/GitPanel.spec.tsx +++ b/src/__tests__/test-components/GitPanel.spec.tsx @@ -41,7 +41,11 @@ const mockedResponses: { * @private * @returns mock settings */ -function MockSettings(commitAndPush = true, promptUserIdentity = false) { +function MockSettings( + commitAndPush = true, + promptUserIdentity = false, + simpleStaging = false +) { return { changed: { connect: () => true, @@ -49,7 +53,8 @@ function MockSettings(commitAndPush = true, promptUserIdentity = false) { }, composite: { commitAndPush, - promptUserIdentity + promptUserIdentity, + simpleStaging } }; } @@ -151,8 +156,6 @@ describe('GitPanel', () => { beforeEach(() => { configSpy = props.model.config = jest.fn(); commitSpy = props.model.commit = jest.fn(); - // @ts-expect-error turn off set status - props.model._setStatus = jest.fn(); // @ts-expect-error set a private prop props.model._status = { @@ -173,10 +176,15 @@ describe('GitPanel', () => { state: 0 }; + // @ts-expect-error turn off set status + props.model._setStatus = jest.fn(() => { + props.model["_statusChanged"].emit(props.model["_status"]); + }); + render(); }); - it.skip('should commit when commit message is provided', async () => { + it('should commit when commit message is provided', async () => { configSpy.mockResolvedValue({ options: commitUser }); await userEvent.type(screen.getAllByRole('textbox')[0], commitSummary); @@ -212,16 +220,15 @@ describe('GitPanel', () => { expect(commitSpy).not.toHaveBeenCalled(); }); - it.skip('should prompt for user identity if explicitly configured', async () => { + it('should prompt for user identity if explicitly configured', async () => { configSpy.mockResolvedValue({ options: commitUser }); - props.settings = MockSettings(false, true) as any; - render(); - mockUtils.showDialog.mockResolvedValue(dialogValue); await userEvent.type(screen.getAllByRole('textbox')[0], commitSummary); - await userEvent.click(screen.getByRole('button', { name: 'Commit' })); + await userEvent.click( + screen.getAllByRole('button', { name: 'Commit' })[0] + ); expect(configSpy).toHaveBeenCalledTimes(1); expect(configSpy.mock.calls[0]).toHaveLength(0); @@ -231,7 +238,7 @@ describe('GitPanel', () => { expect(commitSpy).toHaveBeenCalledWith(commitSummary, false, author); }); - it.skip('should prompt for user identity if user.name is not set', async () => { + it('should prompt for user identity if user.name is not set', async () => { configSpy.mockImplementation(mockConfigImplementation('user.email')); mockUtils.showDialog.mockResolvedValue(dialogValue); @@ -247,7 +254,7 @@ describe('GitPanel', () => { expect(commitSpy).toHaveBeenCalledWith(commitSummary, false, null); }); - it.skip('should prompt for user identity if user.email is not set', async () => { + it('should prompt for user identity if user.email is not set', async () => { configSpy.mockImplementation(mockConfigImplementation('user.name')); mockUtils.showDialog.mockResolvedValue(dialogValue); @@ -263,7 +270,7 @@ describe('GitPanel', () => { expect(commitSpy).toHaveBeenCalledWith(commitSummary, false, null); }); - it.skip('should not commit if no user identity is set and the user rejects the dialog', async () => { + it('should not commit if no user identity is set and the user rejects the dialog', async () => { configSpy.mockResolvedValue({ options: {} }); mockUtils.showDialog.mockResolvedValue({ button: { @@ -291,6 +298,177 @@ describe('GitPanel', () => { }); }); + describe('GitPanel when pathRepository is empty string', () => { + const trans = nullTranslator.load('jupyterlab_git'); + + const props: IGitPanelProps = { + model: null as any, + commands: new CommandRegistry(), + settings: null as any, + filebrowser: { + path: '' + } as any, + trans: trans + }; + + beforeEach(async () => { + jest.restoreAllMocks(); + + const mock = git as jest.Mocked; + mock.requestAPI.mockImplementation( + mockedRequestAPI(mockedResponses) as any + ); + + props.model = new GitModel(); + props.model.pathRepository = ''; + + props.settings = MockSettings() as any; + + await props.model.ready; + }); + + describe('#commitFiles()', () => { + let commitSpy: jest.SpyInstance>; + let configSpy: jest.SpyInstance>; + + const commitSummary = 'Fix really stupid bug'; + const commitDescription = 'This will probably break everything :)'; + const commitUser = { + 'user.name': 'John Snow', + 'user.email': 'john.snow@winteris.com' + }; + + const mockUtils = apputils as jest.Mocked; + const dialogValue: apputils.Dialog.IResult = { + button: { + accept: true, + actions: [], + caption: '', + className: '', + displayType: 'default', + iconClass: '', + iconLabel: '', + label: '' + } as any, + isChecked: null, + value: { + name: commitUser['user.name'], + email: commitUser['user.email'] + } + }; + + /** + * Mock identity look up (GitModel.config) + */ + const mockConfigImplementation = (key: 'user.email' | 'user.name') => { + return (options?: JSONObject): Promise => { + const response = { + options: { + [key]: commitUser[key] + } + }; + return Promise.resolve( + (options === undefined + ? response // When getting config options + : null) as any // When setting config options + ); + }; + }; + + beforeEach(() => { + configSpy = props.model.config = jest.fn(); + commitSpy = props.model.commit = jest.fn(); + + // @ts-expect-error set a private prop + props.model._status = { + branch: 'master', + remote: 'origin/master', + ahead: 0, + behind: 0, + files: [ + { + x: 'M', + y: ' ', + to: 'packages/jupyterlab_toastify/README.md', + from: 'packages/jupyterlab_toastify/README.md', + is_binary: false, + status: 'staged' + } + ], + state: 0 + }; + + // @ts-expect-error turn off set status + props.model._setStatus = jest.fn(() => { + props.model["_statusChanged"].emit(props.model["_status"]); + }); + + render(); + }); + + it('should prompt for user identity if user.name is not set', async () => { + configSpy.mockImplementation(mockConfigImplementation('user.email')); + mockUtils.showDialog.mockResolvedValue(dialogValue); + + await userEvent.type(screen.getAllByRole('textbox')[0], commitSummary); + await userEvent.click(screen.getByRole('button', { name: 'Commit' })); + + await waitFor(() => { + expect(configSpy).toHaveBeenCalledTimes(2); + }); + expect(configSpy.mock.calls[0]).toHaveLength(0); + expect(configSpy.mock.calls[1]).toEqual([commitUser]); + expect(commitSpy).toHaveBeenCalledTimes(1); + expect(commitSpy).toHaveBeenCalledWith(commitSummary, false, null); + }); + + it('should prompt for user identity if user.email is not set', async () => { + configSpy.mockImplementation(mockConfigImplementation('user.name')); + mockUtils.showDialog.mockResolvedValue(dialogValue); + + await userEvent.type(screen.getAllByRole('textbox')[0], commitSummary); + await userEvent.click(screen.getByRole('button', { name: 'Commit' })); + + await waitFor(() => { + expect(configSpy).toHaveBeenCalledTimes(2); + }); + expect(configSpy.mock.calls[0]).toHaveLength(0); + expect(configSpy.mock.calls[1]).toEqual([commitUser]); + expect(commitSpy).toHaveBeenCalledTimes(1); + expect(commitSpy).toHaveBeenCalledWith(commitSummary, false, null); + }); + + it('should not commit if no user identity is set and the user rejects the dialog', async () => { + configSpy.mockResolvedValue({ options: {} }); + mockUtils.showDialog.mockResolvedValue({ + button: { + ...dialogValue.button, + accept: false + }, + isChecked: null, + value: null + }); + + await userEvent.type(screen.getAllByRole('textbox')[0], commitSummary); + await userEvent.type( + screen.getAllByRole('textbox')[1], + commitDescription + ); + await userEvent.click(screen.getByRole('button', { name: 'Commit' })); + + await waitFor(() => expect(configSpy).toHaveBeenCalledTimes(1)); + expect(configSpy).toHaveBeenCalledWith(); + expect(commitSpy).not.toHaveBeenCalled(); + + // Should not erase commit message + expect(screen.getAllByRole('textbox')[0]).toHaveValue(commitSummary); + expect(screen.getAllByRole('textbox')[1]).toHaveValue( + commitDescription + ); + }); + }); + }); + describe('#render()', () => { beforeEach(() => { props.model = { @@ -392,4 +570,4 @@ describe('GitPanel', () => { expect(buttons[buttons.length - 2]).toHaveTextContent('Commit'); }); }); -}); +}); \ No newline at end of file diff --git a/src/components/GitPanel.tsx b/src/components/GitPanel.tsx index 2acb17ab1..184a35a2c 100644 --- a/src/components/GitPanel.tsx +++ b/src/components/GitPanel.tsx @@ -842,7 +842,7 @@ export class GitPanel extends React.Component { * @param path - repository path */ private async _hasIdentity(path: string | null): Promise { - if (!path) { + if (path === null) { return null; }