diff options
Diffstat (limited to '__test__/git-auth-helper.test.ts')
| -rw-r--r-- | __test__/git-auth-helper.test.ts | 296 |
1 files changed, 251 insertions, 45 deletions
diff --git a/__test__/git-auth-helper.test.ts b/__test__/git-auth-helper.test.ts index fab9f37..68926f2 100644 --- a/__test__/git-auth-helper.test.ts +++ b/__test__/git-auth-helper.test.ts @@ -8,10 +8,13 @@ import {IGitSourceSettings} from '../lib/git-source-settings' const testWorkspace = path.join(__dirname, '_temp', 'git-auth-helper') const originalRunnerTemp = process.env['RUNNER_TEMP'] +const originalHome = process.env['HOME'] let workspace: string -let gitConfigPath: string +let localGitConfigPath: string +let globalGitConfigPath: string let runnerTemp: string -let git: IGitCommandManager +let tempHomedir: string +let git: IGitCommandManager & {env: {[key: string]: string}} let settings: IGitSourceSettings describe('git-auth-helper tests', () => { @@ -23,11 +26,24 @@ describe('git-auth-helper tests', () => { beforeEach(() => { // Mock setSecret jest.spyOn(core, 'setSecret').mockImplementation((secret: string) => {}) + + // Mock error/warning/info/debug + jest.spyOn(core, 'error').mockImplementation(jest.fn()) + jest.spyOn(core, 'warning').mockImplementation(jest.fn()) + jest.spyOn(core, 'info').mockImplementation(jest.fn()) + jest.spyOn(core, 'debug').mockImplementation(jest.fn()) }) afterEach(() => { // Unregister mocks jest.restoreAllMocks() + + // Restore HOME + if (originalHome) { + process.env['HOME'] = originalHome + } else { + delete process.env['HOME'] + } }) afterAll(() => { @@ -38,10 +54,11 @@ describe('git-auth-helper tests', () => { } }) - const configuresAuthHeader = 'configures auth header' - it(configuresAuthHeader, async () => { + const configureAuth_configuresAuthHeader = + 'configureAuth configures auth header' + it(configureAuth_configuresAuthHeader, async () => { // Arrange - await setup(configuresAuthHeader) + await setup(configureAuth_configuresAuthHeader) expect(settings.authToken).toBeTruthy() // sanity check const authHelper = gitAuthHelper.createAuthHelper(git, settings) @@ -49,7 +66,9 @@ describe('git-auth-helper tests', () => { await authHelper.configureAuth() // Assert config - const configContent = (await fs.promises.readFile(gitConfigPath)).toString() + const configContent = ( + await fs.promises.readFile(localGitConfigPath) + ).toString() const basicCredential = Buffer.from( `x-access-token:${settings.authToken}`, 'utf8' @@ -61,32 +80,39 @@ describe('git-auth-helper tests', () => { ).toBeGreaterThanOrEqual(0) }) - const configuresAuthHeaderEvenWhenPersistCredentialsFalse = - 'configures auth header even when persist credentials false' - it(configuresAuthHeaderEvenWhenPersistCredentialsFalse, async () => { - // Arrange - await setup(configuresAuthHeaderEvenWhenPersistCredentialsFalse) - expect(settings.authToken).toBeTruthy() // sanity check - settings.persistCredentials = false - const authHelper = gitAuthHelper.createAuthHelper(git, settings) + const configureAuth_configuresAuthHeaderEvenWhenPersistCredentialsFalse = + 'configureAuth configures auth header even when persist credentials false' + it( + configureAuth_configuresAuthHeaderEvenWhenPersistCredentialsFalse, + async () => { + // Arrange + await setup( + configureAuth_configuresAuthHeaderEvenWhenPersistCredentialsFalse + ) + expect(settings.authToken).toBeTruthy() // sanity check + settings.persistCredentials = false + const authHelper = gitAuthHelper.createAuthHelper(git, settings) - // Act - await authHelper.configureAuth() + // Act + await authHelper.configureAuth() - // Assert config - const configContent = (await fs.promises.readFile(gitConfigPath)).toString() - expect( - configContent.indexOf( - `http.https://github.com/.extraheader AUTHORIZATION` - ) - ).toBeGreaterThanOrEqual(0) - }) + // Assert config + const configContent = ( + await fs.promises.readFile(localGitConfigPath) + ).toString() + expect( + configContent.indexOf( + `http.https://github.com/.extraheader AUTHORIZATION` + ) + ).toBeGreaterThanOrEqual(0) + } + ) - const registersBasicCredentialAsSecret = - 'registers basic credential as secret' - it(registersBasicCredentialAsSecret, async () => { + const configureAuth_registersBasicCredentialAsSecret = + 'configureAuth registers basic credential as secret' + it(configureAuth_registersBasicCredentialAsSecret, async () => { // Arrange - await setup(registersBasicCredentialAsSecret) + await setup(configureAuth_registersBasicCredentialAsSecret) expect(settings.authToken).toBeTruthy() // sanity check const authHelper = gitAuthHelper.createAuthHelper(git, settings) @@ -103,14 +129,139 @@ describe('git-auth-helper tests', () => { expect(setSecretSpy).toHaveBeenCalledWith(expectedSecret) }) - const removesToken = 'removes token' - it(removesToken, async () => { + const configureGlobalAuth_copiesGlobalGitConfig = + 'configureGlobalAuth copies global git config' + it(configureGlobalAuth_copiesGlobalGitConfig, async () => { + // Arrange + await setup(configureGlobalAuth_copiesGlobalGitConfig) + await fs.promises.writeFile(globalGitConfigPath, 'value-from-global-config') + const authHelper = gitAuthHelper.createAuthHelper(git, settings) + + // Act + await authHelper.configureAuth() + await authHelper.configureGlobalAuth() + + // Assert original global config not altered + let configContent = ( + await fs.promises.readFile(globalGitConfigPath) + ).toString() + expect(configContent).toBe('value-from-global-config') + + // Assert temporary global config + expect(git.env['HOME']).toBeTruthy() + const basicCredential = Buffer.from( + `x-access-token:${settings.authToken}`, + 'utf8' + ).toString('base64') + configContent = ( + await fs.promises.readFile(path.join(git.env['HOME'], '.gitconfig')) + ).toString() + expect( + configContent.indexOf('value-from-global-config') + ).toBeGreaterThanOrEqual(0) + expect( + configContent.indexOf( + `http.https://github.com/.extraheader AUTHORIZATION: basic ${basicCredential}` + ) + ).toBeGreaterThanOrEqual(0) + }) + + const configureGlobalAuth_createsNewGlobalGitConfigWhenGlobalDoesNotExist = + 'configureGlobalAuth creates new git config when global does not exist' + it( + configureGlobalAuth_createsNewGlobalGitConfigWhenGlobalDoesNotExist, + async () => { + // Arrange + await setup( + configureGlobalAuth_createsNewGlobalGitConfigWhenGlobalDoesNotExist + ) + await io.rmRF(globalGitConfigPath) + const authHelper = gitAuthHelper.createAuthHelper(git, settings) + + // Act + await authHelper.configureAuth() + await authHelper.configureGlobalAuth() + + // Assert original global config not recreated + try { + await fs.promises.stat(globalGitConfigPath) + throw new Error( + `Did not expect file to exist: '${globalGitConfigPath}'` + ) + } catch (err) { + if (err.code !== 'ENOENT') { + throw err + } + } + + // Assert temporary global config + expect(git.env['HOME']).toBeTruthy() + const basicCredential = Buffer.from( + `x-access-token:${settings.authToken}`, + 'utf8' + ).toString('base64') + const configContent = ( + await fs.promises.readFile(path.join(git.env['HOME'], '.gitconfig')) + ).toString() + expect( + configContent.indexOf( + `http.https://github.com/.extraheader AUTHORIZATION: basic ${basicCredential}` + ) + ).toBeGreaterThanOrEqual(0) + } + ) + + const configureSubmoduleAuth_doesNotConfigureTokenWhenPersistCredentialsFalse = + 'configureSubmoduleAuth does not configure token when persist credentials false' + it( + configureSubmoduleAuth_doesNotConfigureTokenWhenPersistCredentialsFalse, + async () => { + // Arrange + await setup( + configureSubmoduleAuth_doesNotConfigureTokenWhenPersistCredentialsFalse + ) + settings.persistCredentials = false + const authHelper = gitAuthHelper.createAuthHelper(git, settings) + await authHelper.configureAuth() + ;(git.submoduleForeach as jest.Mock<any, any>).mockClear() // reset calls + + // Act + await authHelper.configureSubmoduleAuth() + + // Assert + expect(git.submoduleForeach).not.toHaveBeenCalled() + } + ) + + const configureSubmoduleAuth_configuresTokenWhenPersistCredentialsTrue = + 'configureSubmoduleAuth configures token when persist credentials true' + it( + configureSubmoduleAuth_configuresTokenWhenPersistCredentialsTrue, + async () => { + // Arrange + await setup( + configureSubmoduleAuth_configuresTokenWhenPersistCredentialsTrue + ) + const authHelper = gitAuthHelper.createAuthHelper(git, settings) + await authHelper.configureAuth() + ;(git.submoduleForeach as jest.Mock<any, any>).mockClear() // reset calls + + // Act + await authHelper.configureSubmoduleAuth() + + // Assert + expect(git.submoduleForeach).toHaveBeenCalledTimes(1) + } + ) + + const removeAuth_removesToken = 'removeAuth removes token' + it(removeAuth_removesToken, async () => { // Arrange - await setup(removesToken) + await setup(removeAuth_removesToken) const authHelper = gitAuthHelper.createAuthHelper(git, settings) await authHelper.configureAuth() let gitConfigContent = ( - await fs.promises.readFile(gitConfigPath) + await fs.promises.readFile(localGitConfigPath) ).toString() expect(gitConfigContent.indexOf('http.')).toBeGreaterThanOrEqual(0) // sanity check @@ -118,9 +269,37 @@ describe('git-auth-helper tests', () => { await authHelper.removeAuth() // Assert git config - gitConfigContent = (await fs.promises.readFile(gitConfigPath)).toString() + gitConfigContent = ( + await fs.promises.readFile(localGitConfigPath) + ).toString() expect(gitConfigContent.indexOf('http.')).toBeLessThan(0) }) + + const removeGlobalAuth_removesOverride = 'removeGlobalAuth removes override' + it(removeGlobalAuth_removesOverride, async () => { + // Arrange + await setup(removeGlobalAuth_removesOverride) + const authHelper = gitAuthHelper.createAuthHelper(git, settings) + await authHelper.configureAuth() + await authHelper.configureGlobalAuth() + const homeOverride = git.env['HOME'] // Sanity check + expect(homeOverride).toBeTruthy() + await fs.promises.stat(path.join(git.env['HOME'], '.gitconfig')) + + // Act + await authHelper.removeGlobalAuth() + + // Assert + expect(git.env['HOME']).toBeUndefined() + try { + await fs.promises.stat(homeOverride) + throw new Error(`Should have been deleted '${homeOverride}'`) + } catch (err) { + if (err.code !== 'ENOENT') { + throw err + } + } + }) }) async function setup(testName: string): Promise<void> { @@ -129,14 +308,19 @@ async function setup(testName: string): Promise<void> { // Directories workspace = path.join(testWorkspace, testName, 'workspace') runnerTemp = path.join(testWorkspace, testName, 'runner-temp') + tempHomedir = path.join(testWorkspace, testName, 'home-dir') await fs.promises.mkdir(workspace, {recursive: true}) await fs.promises.mkdir(runnerTemp, {recursive: true}) + await fs.promises.mkdir(tempHomedir, {recursive: true}) process.env['RUNNER_TEMP'] = runnerTemp + process.env['HOME'] = tempHomedir // Create git config - gitConfigPath = path.join(workspace, '.git', 'config') - await fs.promises.mkdir(path.join(workspace, '.git'), {recursive: true}) - await fs.promises.writeFile(path.join(workspace, '.git', 'config'), '') + globalGitConfigPath = path.join(tempHomedir, '.gitconfig') + await fs.promises.writeFile(globalGitConfigPath, '') + localGitConfigPath = path.join(workspace, '.git', 'config') + await fs.promises.mkdir(path.dirname(localGitConfigPath), {recursive: true}) + await fs.promises.writeFile(localGitConfigPath, '') git = { branchDelete: jest.fn(), @@ -144,12 +328,20 @@ async function setup(testName: string): Promise<void> { branchList: jest.fn(), checkout: jest.fn(), checkoutDetach: jest.fn(), - config: jest.fn(async (key: string, value: string) => { - await fs.promises.appendFile(gitConfigPath, `\n${key} ${value}`) - }), + config: jest.fn( + async (key: string, value: string, globalConfig?: boolean) => { + const configPath = globalConfig + ? path.join(git.env['HOME'] || tempHomedir, '.gitconfig') + : localGitConfigPath + await fs.promises.appendFile(configPath, `\n${key} ${value}`) + } + ), configExists: jest.fn( - async (key: string): Promise<boolean> => { - const content = await fs.promises.readFile(gitConfigPath) + async (key: string, globalConfig?: boolean): Promise<boolean> => { + const configPath = globalConfig + ? path.join(git.env['HOME'] || tempHomedir, '.gitconfig') + : localGitConfigPath + const content = await fs.promises.readFile(configPath) const lines = content .toString() .split('\n') @@ -157,6 +349,7 @@ async function setup(testName: string): Promise<void> { return lines.some(x => x.startsWith(key)) } ), + env: {}, fetch: jest.fn(), getWorkingDirectory: jest.fn(() => workspace), init: jest.fn(), @@ -165,18 +358,29 @@ async function setup(testName: string): Promise<void> { lfsInstall: jest.fn(), log1: jest.fn(), remoteAdd: jest.fn(), - setEnvironmentVariable: jest.fn(), + removeEnvironmentVariable: jest.fn((name: string) => delete git.env[name]), + setEnvironmentVariable: jest.fn((name: string, value: string) => { + git.env[name] = value + }), + submoduleForeach: jest.fn(async () => { + return '' + }), + submoduleSync: jest.fn(), + submoduleUpdate: jest.fn(), tagExists: jest.fn(), tryClean: jest.fn(), tryConfigUnset: jest.fn( - async (key: string): Promise<boolean> => { - let content = await fs.promises.readFile(gitConfigPath) + async (key: string, globalConfig?: boolean): Promise<boolean> => { + const configPath = globalConfig + ? path.join(git.env['HOME'] || tempHomedir, '.gitconfig') + : localGitConfigPath + let content = await fs.promises.readFile(configPath) let lines = content .toString() .split('\n') .filter(x => x) .filter(x => !x.startsWith(key)) - await fs.promises.writeFile(gitConfigPath, lines.join('\n')) + await fs.promises.writeFile(configPath, lines.join('\n')) return true } ), @@ -191,6 +395,8 @@ async function setup(testName: string): Promise<void> { commit: '', fetchDepth: 1, lfs: false, + submodules: false, + nestedSubmodules: false, persistCredentials: true, ref: 'refs/heads/master', repositoryName: 'my-repo', |
