diff --git a/README.md b/README.md index d21e7e7f..2c4bc240 100644 --- a/README.md +++ b/README.md @@ -224,7 +224,7 @@ All available languages are currently listed in the [i18n](https://github.com/di ### Push to git (gonna be deprecated) -A prompt to ushing to git is on by default but if you would like to turn it off just use: +A prompt for pushing to git is on by default but if you would like to turn it off just use: ```sh oco config set OCO_GITPUSH=false diff --git a/src/commands/commit.ts b/src/commands/commit.ts index 5bb9de85..8d098818 100644 --- a/src/commands/commit.ts +++ b/src/commands/commit.ts @@ -107,13 +107,16 @@ ${chalk.grey('——————————————————')}` const remotes = await getGitRemotes(); + // user isn't pushing, return early + if (config.OCO_GITPUSH === false) return; + if (!remotes.length) { const { stdout } = await execa('git', ['push']); if (stdout) outro(stdout); process.exit(0); } - if (remotes.length === 1 && config.OCO_GITPUSH !== true) { + if (remotes.length === 1) { const isPushConfirmedByUser = await confirm({ message: 'Do you want to run `git push`?' }); diff --git a/test/e2e/gitPush.test.ts b/test/e2e/gitPush.test.ts new file mode 100644 index 00000000..611f8d04 --- /dev/null +++ b/test/e2e/gitPush.test.ts @@ -0,0 +1,205 @@ +import path from 'path'; +import 'cli-testing-library/extend-expect'; +import { exec } from 'child_process'; +import { prepareTempDir } from './utils'; +import { promisify } from 'util'; +import { render } from 'cli-testing-library'; +import { resolve } from 'path'; +import { rm } from 'fs'; +const fsExec = promisify(exec); +const fsRemove = promisify(rm); + +/** + * git remote -v + * + * [no remotes] + */ +const prepareNoRemoteGitRepository = async (): Promise<{ + gitDir: string; + cleanup: () => Promise; +}> => { + const tempDir = await prepareTempDir(); + await fsExec('git init test', { cwd: tempDir }); + const gitDir = path.resolve(tempDir, 'test'); + + const cleanup = async () => { + return fsRemove(tempDir, { recursive: true }); + }; + return { + gitDir, + cleanup + }; +}; + +/** + * git remote -v + * + * origin /tmp/remote.git (fetch) + * origin /tmp/remote.git (push) + */ +const prepareOneRemoteGitRepository = async (): Promise<{ + gitDir: string; + cleanup: () => Promise; +}> => { + const tempDir = await prepareTempDir(); + await fsExec('git init --bare remote.git', { cwd: tempDir }); + await fsExec('git clone remote.git test', { cwd: tempDir }); + const gitDir = path.resolve(tempDir, 'test'); + + const cleanup = async () => { + return fsRemove(tempDir, { recursive: true }); + }; + return { + gitDir, + cleanup + }; +}; + +/** + * git remote -v + * + * origin /tmp/remote.git (fetch) + * origin /tmp/remote.git (push) + * other ../remote2.git (fetch) + * other ../remote2.git (push) + */ +const prepareTwoRemotesGitRepository = async (): Promise<{ + gitDir: string; + cleanup: () => Promise; +}> => { + const tempDir = await prepareTempDir(); + await fsExec('git init --bare remote.git', { cwd: tempDir }); + await fsExec('git init --bare other.git', { cwd: tempDir }); + await fsExec('git clone remote.git test', { cwd: tempDir }); + const gitDir = path.resolve(tempDir, 'test'); + await fsExec('git remote add other ../other.git', { cwd: gitDir }); + + const cleanup = async () => { + return fsRemove(tempDir, { recursive: true }); + }; + return { + gitDir, + cleanup + }; +}; + +describe('cli flow to push git branch', () => { + it('do nothing when OCO_GITPUSH is set to false', async () => { + const { gitDir, cleanup } = await prepareNoRemoteGitRepository(); + + await render('echo', [`'console.log("Hello World");' > index.ts`], { + cwd: gitDir + }); + await render('git', ['add index.ts'], { cwd: gitDir }); + + const { queryByText, findByText, userEvent } = await render( + `OCO_AI_PROVIDER='test' OCO_GITPUSH='false' node`, + [resolve('./out/cli.cjs')], + { cwd: gitDir } + ); + expect(await findByText('Confirm the commit message?')).toBeInTheConsole(); + userEvent.keyboard('[Enter]'); + + expect( + await queryByText('Choose a remote to push to') + ).not.toBeInTheConsole(); + expect( + await queryByText('Do you want to run `git push`?') + ).not.toBeInTheConsole(); + expect( + await queryByText('Successfully pushed all commits to origin') + ).not.toBeInTheConsole(); + expect( + await queryByText('Command failed with exit code 1') + ).not.toBeInTheConsole(); + + await cleanup(); + }); + + it('push and cause error when there is no remote', async () => { + const { gitDir, cleanup } = await prepareNoRemoteGitRepository(); + + await render('echo', [`'console.log("Hello World");' > index.ts`], { + cwd: gitDir + }); + await render('git', ['add index.ts'], { cwd: gitDir }); + + const { queryByText, findByText, userEvent } = await render( + `OCO_AI_PROVIDER='test' node`, + [resolve('./out/cli.cjs')], + { cwd: gitDir } + ); + expect(await findByText('Confirm the commit message?')).toBeInTheConsole(); + userEvent.keyboard('[Enter]'); + + expect( + await queryByText('Choose a remote to push to') + ).not.toBeInTheConsole(); + expect( + await queryByText('Do you want to run `git push`?') + ).not.toBeInTheConsole(); + expect( + await queryByText('Successfully pushed all commits to origin') + ).not.toBeInTheConsole(); + + expect( + await findByText('Command failed with exit code 1') + ).toBeInTheConsole(); + + await cleanup(); + }); + + it('push when one remote is set', async () => { + const { gitDir, cleanup } = await prepareOneRemoteGitRepository(); + + await render('echo', [`'console.log("Hello World");' > index.ts`], { + cwd: gitDir + }); + await render('git', ['add index.ts'], { cwd: gitDir }); + + const { findByText, userEvent } = await render( + `OCO_AI_PROVIDER='test' node`, + [resolve('./out/cli.cjs')], + { cwd: gitDir } + ); + expect(await findByText('Confirm the commit message?')).toBeInTheConsole(); + userEvent.keyboard('[Enter]'); + + expect( + await findByText('Do you want to run `git push`?') + ).toBeInTheConsole(); + userEvent.keyboard('[Enter]'); + + expect( + await findByText('Successfully pushed all commits to origin') + ).toBeInTheConsole(); + + await cleanup(); + }); + + it('push when two remotes are set', async () => { + const { gitDir, cleanup } = await prepareTwoRemotesGitRepository(); + + await render('echo', [`'console.log("Hello World");' > index.ts`], { + cwd: gitDir + }); + await render('git', ['add index.ts'], { cwd: gitDir }); + + const { findByText, userEvent } = await render( + `OCO_AI_PROVIDER='test' node`, + [resolve('./out/cli.cjs')], + { cwd: gitDir } + ); + expect(await findByText('Confirm the commit message?')).toBeInTheConsole(); + userEvent.keyboard('[Enter]'); + + expect(await findByText('Choose a remote to push to')).toBeInTheConsole(); + userEvent.keyboard('[Enter]'); + + expect( + await findByText('Successfully pushed all commits to origin') + ).toBeInTheConsole(); + + await cleanup(); + }); +}); diff --git a/test/e2e/oneFile.test.ts b/test/e2e/oneFile.test.ts index ddfbc10a..b3e25f96 100644 --- a/test/e2e/oneFile.test.ts +++ b/test/e2e/oneFile.test.ts @@ -17,7 +17,7 @@ it('cli flow to generate commit message for 1 new file (staged)', async () => { expect(await findByText('Confirm the commit message?')).toBeInTheConsole(); userEvent.keyboard('[Enter]'); - expect(await findByText('Choose a remote to push to')).toBeInTheConsole(); + expect(await findByText('Do you want to run `git push`?')).toBeInTheConsole(); userEvent.keyboard('[Enter]'); expect(await findByText('Successfully pushed all commits to origin')).toBeInTheConsole(); @@ -46,7 +46,7 @@ it('cli flow to generate commit message for 1 changed file (not staged)', async expect(await findByText('Successfully committed')).toBeInTheConsole(); - expect(await findByText('Choose a remote to push to')).toBeInTheConsole(); + expect(await findByText('Do you want to run `git push`?')).toBeInTheConsole(); userEvent.keyboard('[Enter]'); expect(await findByText('Successfully pushed all commits to origin')).toBeInTheConsole(); diff --git a/test/e2e/prompt-module/commitlint.test.ts b/test/e2e/prompt-module/commitlint.test.ts index a78ebb61..ab849994 100644 --- a/test/e2e/prompt-module/commitlint.test.ts +++ b/test/e2e/prompt-module/commitlint.test.ts @@ -209,7 +209,7 @@ describe('cli flow to generate commit message using @commitlint prompt-module', oco.userEvent.keyboard('[Enter]'); expect( - await oco.findByText('Choose a remote to push to') + await oco.findByText('Do you want to run `git push`?') ).toBeInTheConsole(); oco.userEvent.keyboard('[Enter]'); diff --git a/test/e2e/utils.ts b/test/e2e/utils.ts index 73f909c5..6ae56633 100644 --- a/test/e2e/utils.ts +++ b/test/e2e/utils.ts @@ -15,7 +15,7 @@ export const prepareEnvironment = async (): Promise<{ gitDir: string; cleanup: () => Promise; }> => { - const tempDir = await fsMakeTempDir(path.join(tmpdir(), 'opencommit-test-')); + const tempDir = await prepareTempDir(); // Create a remote git repository int the temp directory. This is necessary to execute the `git push` command await fsExec('git init --bare remote.git', { cwd: tempDir }); await fsExec('git clone remote.git test', { cwd: tempDir }); @@ -30,4 +30,8 @@ export const prepareEnvironment = async (): Promise<{ } } +export const prepareTempDir = async(): Promise => { + return await fsMakeTempDir(path.join(tmpdir(), 'opencommit-test-')); +} + export const wait = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));