Skip to content
Merged
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
6 changes: 5 additions & 1 deletion src/commands/ci/fetch-default-org-slug.mts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,11 @@ export async function getDefaultOrgSlug(
}
}

const slug = (organizations as any)[keys[0]!]?.name ?? undefined
// Use the org's URL-safe `slug`, not its display `name`: this value is
// exported as SOCKET_ORG_SLUG for the Coana CLI, which resolves the org by
// slug. `name` is the human-readable display name (and may be null), so using
// it here produced a wrong/empty org identifier.
const slug = organizations[0]?.slug ?? undefined
if (!slug) {
return {
ok: false,
Expand Down
89 changes: 89 additions & 0 deletions src/commands/ci/fetch-default-org-slug.test.mts
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import { beforeEach, describe, expect, it, vi } from 'vitest'

import { getDefaultOrgSlug } from './fetch-default-org-slug.mts'
import { fetchOrganization } from '../organization/fetch-organization-list.mts'
import { getConfigValueOrUndef } from '../../utils/config.mts'

Check warning on line 5 in src/commands/ci/fetch-default-org-slug.test.mts

View workflow job for this annotation

GitHub Actions / 🧹 Lint Check

`../../utils/config.mts` import should occur before import of `../organization/fetch-organization-list.mts`

vi.mock('../organization/fetch-organization-list.mts', () => ({
fetchOrganization: vi.fn(),
}))
vi.mock('../../utils/config.mts', () => ({
getConfigValueOrUndef: vi.fn(() => undefined),
}))
// Keep SOCKET_CLI_ORG_SLUG unset so the resolver falls through to the API path.
vi.mock('../../constants.mts', () => ({
default: { ENV: {} },
}))

describe('getDefaultOrgSlug', () => {
beforeEach(() => {
vi.clearAllMocks()
vi.mocked(getConfigValueOrUndef).mockReturnValue(undefined)
})

it('resolves the org slug (not the display name) from the API', async () => {
vi.mocked(fetchOrganization).mockResolvedValue({
ok: true,
data: {
organizations: [
{
id: 'org-id',
name: 'Display Name',
image: null,
plan: 'free',
slug: 'my-org-slug',
},
],
},
} as any)

const result = await getDefaultOrgSlug()

expect(result.ok).toBe(true)
// Regression guard: must be the URL-safe slug, never the display name.
expect(result.ok && result.data).toBe('my-org-slug')
})

it('resolves the slug even when the display name is null', async () => {
vi.mocked(fetchOrganization).mockResolvedValue({
ok: true,
data: {
organizations: [
{
id: 'org-id',
name: null,
image: null,
plan: 'free',
slug: 'slug-only',
},
],
},
} as any)

const result = await getDefaultOrgSlug()

expect(result.ok).toBe(true)
expect(result.ok && result.data).toBe('slug-only')
})

it('prefers the defaultOrg config value without calling the API', async () => {
vi.mocked(getConfigValueOrUndef).mockReturnValue('configured-org')

const result = await getDefaultOrgSlug()

expect(result.ok).toBe(true)
expect(result.ok && result.data).toBe('configured-org')
expect(fetchOrganization).not.toHaveBeenCalled()
})

it('fails when the API returns no organizations', async () => {
vi.mocked(fetchOrganization).mockResolvedValue({
ok: true,
data: { organizations: [] },
} as any)

const result = await getDefaultOrgSlug()

expect(result.ok).toBe(false)
})
})
Loading