Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions src/utils/init/config-manual.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,8 @@ export default async function configManual({

const repoPath = await getRepoPath({ repoData })
const repo = {
provider: 'manual',
repo_path: repoPath,
provider: repoData.provider ?? 'manual',
repo_path: repoData.repo ?? repoPath,
repo_branch: repoData.branch,
allowed_branches: [repoData.branch],
deploy_key_id: deployKey.id,
Expand Down
120 changes: 120 additions & 0 deletions tests/unit/utils/get-repo-data.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import { describe, expect, it, vi } from 'vitest'
import type { RepoData } from '../../../src/utils/get-repo-data.js'

vi.mock('../../../src/utils/command-helpers.js', () => ({
log: vi.fn(),
}))

describe('getRepoData', () => {
describe('RepoData structure for different Git providers', () => {
it('should construct correct httpsUrl for GitHub SSH URLs', () => {
const mockRepoData: RepoData = {
name: 'test',
owner: 'ownername',
repo: 'ownername/test',
url: 'git@github.com:ownername/test.git',
branch: 'main',
provider: 'github',
httpsUrl: 'https://github.com/ownername/test',
}

expect(mockRepoData.httpsUrl).toBe('https://github.com/ownername/test')
expect(mockRepoData.provider).toBe('github')
expect(mockRepoData.repo).toBe('ownername/test')
})

it('should construct correct httpsUrl for GitLab SSH URLs', () => {
const mockRepoData: RepoData = {
name: 'test',
owner: 'ownername',
repo: 'ownername/test',
url: 'git@gitlab.com:ownername/test.git',
branch: 'main',
provider: 'gitlab',
httpsUrl: 'https://gitlab.com/ownername/test',
}

expect(mockRepoData.httpsUrl).toBe('https://gitlab.com/ownername/test')
expect(mockRepoData.provider).toBe('gitlab')
expect(mockRepoData.repo).toBe('ownername/test')
})

it('should construct correct httpsUrl for GitHub HTTPS URLs', () => {
const mockRepoData: RepoData = {
name: 'test',
owner: 'ownername',
repo: 'ownername/test',
url: 'https://github.com/ownername/test.git',
branch: 'main',
provider: 'github',
httpsUrl: 'https://github.com/ownername/test',
}

expect(mockRepoData.httpsUrl).toBe('https://github.com/ownername/test')
expect(mockRepoData.provider).toBe('github')
expect(mockRepoData.repo).toBe('ownername/test')
})

it('should construct correct httpsUrl for GitLab HTTPS URLs', () => {
const mockRepoData: RepoData = {
name: 'test',
owner: 'ownername',
repo: 'ownername/test',
url: 'https://gitlab.com/ownername/test.git',
branch: 'main',
provider: 'gitlab',
httpsUrl: 'https://gitlab.com/ownername/test',
}

expect(mockRepoData.httpsUrl).toBe('https://gitlab.com/ownername/test')
expect(mockRepoData.provider).toBe('gitlab')
expect(mockRepoData.repo).toBe('ownername/test')
})

it('should use host as provider for unknown Git hosts', () => {
const mockRepoData: RepoData = {
name: 'test',
owner: 'user',
repo: 'user/test',
url: 'git@custom-git.example.com:user/test.git',
branch: 'main',
provider: 'custom-git.example.com',
httpsUrl: 'https://custom-git.example.com/user/test',
}

expect(mockRepoData.httpsUrl).toBe('https://custom-git.example.com/user/test')
expect(mockRepoData.provider).toBe('custom-git.example.com')
expect(mockRepoData.repo).toBe('user/test')
})
})

describe('provider field mapping', () => {
it('should map github.com to "github" provider', () => {
const mockRepoData: RepoData = {
name: 'test',
owner: 'user',
repo: 'user/test',
url: 'git@github.com:user/test.git',
branch: 'main',
provider: 'github',
httpsUrl: 'https://github.com/user/test',
}

expect(mockRepoData.provider).toBe('github')
})

it('should map gitlab.com to "gitlab" provider', () => {
const mockRepoData: RepoData = {
name: 'test',
owner: 'user',
repo: 'user/test',
url: 'git@gitlab.com:user/test.git',
branch: 'main',
provider: 'gitlab',
httpsUrl: 'https://gitlab.com/user/test',
}

expect(mockRepoData.provider).toBe('gitlab')
})
})
})
167 changes: 167 additions & 0 deletions tests/unit/utils/init/config-manual.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
import { describe, expect, it, vi, beforeEach } from 'vitest'
import type { RepoData } from '../../../../src/utils/get-repo-data.js'
import type { NetlifyAPI } from '@netlify/api'
import type BaseCommand from '../../../../src/commands/base-command.js'

const mockPrompt = vi.fn()
const mockLog = vi.fn()
const mockExit = vi.fn()
const mockCreateDeployKey = vi.fn()
const mockGetBuildSettings = vi.fn()
const mockSaveNetlifyToml = vi.fn()
const mockSetupSite = vi.fn()

vi.mock('inquirer', () => ({
default: {
prompt: mockPrompt,
},
}))

vi.mock('../../../../src/utils/command-helpers.js', () => ({
log: mockLog,
exit: mockExit,
}))

vi.mock('../../../../src/utils/init/utils.js', () => ({
createDeployKey: mockCreateDeployKey,
getBuildSettings: mockGetBuildSettings,
saveNetlifyToml: mockSaveNetlifyToml,
setupSite: mockSetupSite,
}))

describe('config-manual', () => {
let mockApi: Partial<NetlifyAPI>
let mockCommand: Pick<BaseCommand, 'netlify'>

beforeEach(() => {
vi.clearAllMocks()

mockApi = {}
mockCommand = {
netlify: {
api: mockApi as NetlifyAPI,
cachedConfig: { configPath: '/test/netlify.toml' } as BaseCommand['netlify']['cachedConfig'],
config: { plugins: [] } as BaseCommand['netlify']['config'],

Check failure on line 44 in tests/unit/utils/init/config-manual.test.ts

View workflow job for this annotation

GitHub Actions / typecheck

Conversion of type '{ plugins: never[]; }' to type 'NormalizedCachedConfigConfig' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.
repositoryRoot: '/test',
} as BaseCommand['netlify'],
}

mockPrompt.mockResolvedValue({
sshKeyAdded: true,
repoPath: 'git@gitlab.com:test/repo.git',
deployHookAdded: true,
})

mockCreateDeployKey.mockResolvedValue({ id: 'key-123', public_key: 'ssh-rsa test' })
mockGetBuildSettings.mockResolvedValue({
baseDir: '',
buildCmd: 'npm run build',
buildDir: 'dist',
functionsDir: 'functions',
pluginsToInstall: [],
})
mockSaveNetlifyToml.mockResolvedValue(undefined)
mockSetupSite.mockResolvedValue({ deploy_hook: 'https://api.netlify.com/hooks/test' })
})

describe('GitLab repository configuration', () => {
it('should use provider from repoData for GitLab repos', async () => {
const configManual = (await import('../../../../src/utils/init/config-manual.js')).default

const repoData: RepoData = {
name: 'test',
owner: 'ownername',
repo: 'ownername/test',
url: 'git@gitlab.com:ownername/test.git',
branch: 'main',
provider: 'gitlab',
httpsUrl: 'https://gitlab.com/ownername/test',
}

await configManual({
command: mockCommand as BaseCommand,
repoData,
siteId: 'site-123',
})

const setupCall = mockSetupSite.mock.calls[0][0] as { repo: { provider: string; repo_path: string } }
expect(setupCall.repo.provider).toBe('gitlab')
expect(setupCall.repo.repo_path).toBe('ownername/test')
})

it('should use repo path (owner/name format) instead of SSH URL for GitLab', async () => {
const configManual = (await import('../../../../src/utils/init/config-manual.js')).default

const repoData: RepoData = {
name: 'test',
owner: 'ownername',
repo: 'ownername/test',
url: 'git@gitlab.com:ownername/test.git',
branch: 'main',
provider: 'gitlab',
httpsUrl: 'https://gitlab.com/ownername/test',
}

await configManual({
command: mockCommand as BaseCommand,
repoData,
siteId: 'site-123',
})

const setupSiteCall = mockSetupSite.mock.calls[0][0] as {
repo: { repo_path: string }
}
expect(setupSiteCall.repo.repo_path).toBe('ownername/test')
expect(setupSiteCall.repo.repo_path).not.toBe('git@gitlab.com:ownername/test.git')
})

it('should fallback to manual provider when provider is null', async () => {
const configManual = (await import('../../../../src/utils/init/config-manual.js')).default

const repoData: RepoData = {
name: 'test',
owner: 'user',
repo: 'user/test',
url: 'git@custom.com:user/test.git',
branch: 'main',
provider: null,
httpsUrl: 'https://custom.com/user/test',
}

await configManual({
command: mockCommand as BaseCommand,
repoData,
siteId: 'site-123',
})

const setupCall = mockSetupSite.mock.calls[0][0] as { repo: { provider: string } }
expect(setupCall.repo.provider).toBe('manual')
})
})

describe('GitHub repository configuration', () => {
it('should use provider from repoData for GitHub repos', async () => {
const configManual = (await import('../../../../src/utils/init/config-manual.js')).default

const repoData: RepoData = {
name: 'test',
owner: 'user',
repo: 'user/test',
url: 'git@github.com:user/test.git',
branch: 'main',
provider: 'github',
httpsUrl: 'https://github.com/user/test',
}

await configManual({
command: mockCommand as BaseCommand,
repoData,
siteId: 'site-123',
})

const setupCall = mockSetupSite.mock.calls[0][0] as { repo: { provider: string; repo_path: string } }
expect(setupCall.repo.provider).toBe('github')
expect(setupCall.repo.repo_path).toBe('user/test')
})
})
})
Loading