Skip to content

Built for people who want to own their automations. Join the waitlist for an invite.

Package listing

@kody/gitlab

tests/auth-locators.test.ts

190 lines · 6.0 KB · TypeScript
import assert from 'node:assert/strict'
import { readFileSync } from 'node:fs'
import { dirname, join } from 'node:path'
import test from 'node:test'
import { fileURLToPath } from 'node:url'
import {
	DEFAULT_GITLAB_API_BASE_URL,
	DEFAULT_GITLAB_INTEGRATION_NAME,
	DEFAULT_GITLAB_SECRET_NAME,
	GITLAB_OAUTH_CONNECT_URL,
	GITLAB_PAT_SETUP_URL,
	buildOauthConnectUrl,
	buildPatSetupUrl,
	resolveApiBaseUrl,
	resolveGitlabAuth,
} from '../src/auth.ts'
import {
	encodeProjectId,
	normalizeIssueLocator,
	normalizeMergeRequestLocator,
	normalizePipelineLocator,
	normalizeProjectLocator,
} from '../src/locators.ts'

const root = join(dirname(fileURLToPath(import.meta.url)), '..')

test('default auth is OAuth integration gitlab', () => {
	const auth = resolveGitlabAuth()
	assert.equal(auth.mode, 'oauth')
	assert.equal(auth.integrationName, DEFAULT_GITLAB_INTEGRATION_NAME)
	assert.equal(auth.apiBaseUrl, DEFAULT_GITLAB_API_BASE_URL)
	assert.equal(auth.apiHost, 'gitlab.com')
})

test('secretName selects the PAT lane and ignores integrationName', () => {
	const auth = resolveGitlabAuth({
		secretName: DEFAULT_GITLAB_SECRET_NAME,
		integrationName: 'gitlab-work',
	})
	assert.equal(auth.mode, 'pat')
	assert.equal(auth.secretName, DEFAULT_GITLAB_SECRET_NAME)
	assert.equal(auth.integrationName, null)
	assert.equal(auth.label, DEFAULT_GITLAB_SECRET_NAME)
})

test('multi-account OAuth uses gitlab-* integration names', () => {
	const auth = resolveGitlabAuth({ integrationName: 'gitlab-work' })
	assert.equal(auth.mode, 'oauth')
	assert.equal(auth.integrationName, 'gitlab-work')
	assert.equal(auth.label, 'gitlab-work')
})

test('account aliases integrationName', () => {
	const auth = resolveGitlabAuth({ account: 'gitlab-bot' })
	assert.equal(auth.integrationName, 'gitlab-bot')
})

test('self-hosted instanceUrl becomes /api/v4', () => {
	assert.equal(
		resolveApiBaseUrl({ instanceUrl: 'https://gitlab.example.com' }),
		'https://gitlab.example.com/api/v4',
	)
	assert.equal(
		resolveApiBaseUrl({ apiBaseUrl: 'https://gitlab.example.com/api/v4/' }),
		'https://gitlab.example.com/api/v4',
	)
})

test('rejects non-https API bases', () => {
	assert.throws(() => resolveApiBaseUrl({ instanceUrl: 'http://gitlab.example.com' }), /https/)
})

test('connect URLs are prefilled and generic', () => {
	assert.match(GITLAB_OAUTH_CONNECT_URL, /^https:\/\/kody\.codes\/connect\/oauth\?/)
	assert.match(GITLAB_OAUTH_CONNECT_URL, /provider=gitlab/)
	assert.match(GITLAB_OAUTH_CONNECT_URL, /authorizeUrl=https%3A%2F%2Fgitlab.com%2Foauth%2Fauthorize/)
	assert.match(GITLAB_OAUTH_CONNECT_URL, /tokenUrl=https%3A%2F%2Fgitlab.com%2Foauth%2Ftoken/)
	assert.match(GITLAB_OAUTH_CONNECT_URL, /allowedHosts=gitlab.com/)
	assert.match(GITLAB_PAT_SETUP_URL, /^https:\/\/kody\.codes\/account\/secrets\/new\?/)
	assert.match(GITLAB_PAT_SETUP_URL, /name=gitlabAccessToken/)
	assert.match(GITLAB_PAT_SETUP_URL, /allowedHosts=gitlab.com/)

	const work = buildOauthConnectUrl({ provider: 'gitlab-work' })
	assert.match(work, /provider=gitlab-work/)
	const selfHosted = buildOauthConnectUrl({
		provider: 'gitlab',
		instanceUrl: 'https://gitlab.example.com',
	})
	assert.match(selfHosted, /gitlab.example.com%2Foauth%2Fauthorize/)
	assert.equal(
		buildPatSetupUrl('gitlabAccessTokenWork', 'gitlab.example.com').includes(
			'allowedHosts=gitlab.example.com',
		),
		true,
	)
})

test('encodes namespace/project paths once', () => {
	assert.equal(encodeProjectId(42), '42')
	assert.equal(encodeProjectId('example-group/example-project'), 'example-group%2Fexample-project')
	assert.equal(encodeProjectId('example-group%2Fexample-project'), 'example-group%2Fexample-project')
})

test('project locators accept id, path, and URL', () => {
	assert.deepEqual(normalizeProjectLocator({ project: 99 }), {
		projectId: '99',
		projectPath: '99',
	})
	assert.deepEqual(normalizeProjectLocator({ project: 'example-group/nested/example-project' }), {
		projectId: 'example-group%2Fnested%2Fexample-project',
		projectPath: 'example-group/nested/example-project',
	})
	assert.deepEqual(
		normalizeProjectLocator({
			projectUrl: 'https://gitlab.com/example-group/example-project/-/issues/3',
		}),
		{
			projectId: 'example-group%2Fexample-project',
			projectPath: 'example-group/example-project',
		},
	)
})

test('issue, merge request, and pipeline locators parse GitLab URLs', () => {
	assert.deepEqual(
		normalizeIssueLocator({
			issueUrl: 'https://gitlab.com/example-group/nested/example-project/-/issues/12',
		}),
		{
			projectId: 'example-group%2Fnested%2Fexample-project',
			projectPath: 'example-group/nested/example-project',
			issueIid: 12,
		},
	)
	assert.deepEqual(
		normalizeMergeRequestLocator({
			project: 'example-group/example-project',
			mrIid: 4,
		}),
		{
			projectId: 'example-group%2Fexample-project',
			projectPath: 'example-group/example-project',
			mergeRequestIid: 4,
		},
	)
	assert.deepEqual(
		normalizePipelineLocator({
			pipelineUrl: 'https://gitlab.example.com/example-group/example-project/-/pipelines/88',
		}),
		{
			projectId: 'example-group%2Fexample-project',
			projectPath: 'example-group/example-project',
			pipelineId: 88,
		},
	)
})

test('rejects GitHub URLs', () => {
	assert.throws(
		() =>
			normalizeProjectLocator({
				projectUrl: 'https://github.com/example-org/example',
			}),
		/not GitHub/,
	)
})

test('source and docs stay generic', () => {
	const files = [
		'README.md',
		'package.json',
		'src/index.ts',
		'src/auth.ts',
		'src/locators.ts',
		'src/issues/create.ts',
		'src/merge-requests/create.ts',
	]
	for (const file of files) {
		const text = readFileSync(join(root, file), 'utf8')
		assert.doesNotMatch(text, /kentcdodds/i)
		assert.doesNotMatch(text, /kent-explicit/)
		assert.doesNotMatch(text, /epicweb/i)
		assert.doesNotMatch(text, /\/community\/[0-9a-f-]{36}/)
	}
	const readme = readFileSync(join(root, 'README.md'), 'utf8')
	assert.match(readme, /^## Intent$/m)
	assert.match(readme, /https:\/\/kody\.codes\/@kody\/gitlab/)
	assert.match(readme, /https:\/\/kody\.codes\/connect\/oauth\?provider=gitlab/)
	assert.match(readme, /https:\/\/kody\.codes\/account\/secrets\/new\?name=gitlabAccessToken/)
})