import { screen } from '@testing-library/react'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { ProjectDropdown } from './ProjectDropdown'
import { MANAGED_BY } from '@/lib/constants/infrastructure'
import { createMockOrganization, render } from '@/tests/helpers'
const { mockSelectedOrganization, mockSelectedProject, mockSelectorProject } = vi.hoisted(() => ({
mockSelectedOrganization: vi.fn(),
mockSelectedProject: vi.fn(),
mockSelectorProject: vi.fn(),
}))
const mockPush = vi.hoisted(() => vi.fn())
vi.mock('common', async (importOriginal) => {
const original = (await importOriginal()) as typeof import('common')
return {
...original,
useParams: () => ({ ref: 'proj_1' }),
}
})
vi.mock('next/router', () => ({
useRouter: () => ({
route: '/project/[ref]/settings',
query: { ref: 'proj_1' },
push: mockPush,
}),
}))
vi.mock('@/lib/constants', async (importOriginal) => {
const original = (await importOriginal()) as typeof import('@/lib/constants')
return { ...original, IS_PLATFORM: true }
})
vi.mock('@/hooks/misc/useSelectedProject', () => ({
useSelectedProjectQuery: () => ({
data: mockSelectedProject(),
isPending: false,
}),
}))
vi.mock('@/data/projects/project-detail-query', () => ({
useProjectDetailQuery: () => ({ data: undefined, isPending: false }),
}))
vi.mock('@/hooks/misc/useSelectedOrganization', () => ({
useSelectedOrganizationQuery: () => ({ data: mockSelectedOrganization() }),
}))
vi.mock('@/hooks/misc/useIsFeatureEnabled', () => ({
useIsFeatureEnabled: () => false,
}))
vi.mock('@/components/ui/OrganizationProjectSelector', () => ({
OrganizationProjectSelector: ({ renderRow, renderTrigger }: any) => (
{renderTrigger?.({})}
{renderRow?.(mockSelectorProject())}
),
}))
vi.mock('@/components/ui/PartnerIcon', () => ({
default: ({ organization }: { organization: { managed_by: string } }) =>
organization.managed_by === MANAGED_BY.BRIVEN ? null : (
),
}))
describe('ProjectDropdown', () => {
beforeEach(() => {
vi.clearAllMocks()
mockSelectedOrganization.mockReturnValue(
createMockOrganization({
slug: 'briven-org',
managed_by: MANAGED_BY.BRIVEN,
})
)
mockSelectedProject.mockReturnValue({
ref: 'proj_1',
name: 'Hammer',
parentRef: 'proj_1',
parent_project_ref: undefined,
integration_source: 'stripe_projects',
})
mockSelectorProject.mockReturnValue({
ref: 'proj_1',
name: 'Hammer',
status: 'ACTIVE_HEALTHY',
integration_source: 'stripe_projects',
})
})
it('uses project detail integration_source for the selected pill and project row data for selector rows', () => {
mockSelectedOrganization.mockReturnValue(
createMockOrganization({
slug: 'stripe-org',
billing_partner: null,
integration_source: 'stripe_projects',
managed_by: MANAGED_BY.STRIPE_PROJECTS,
})
)
render()
expect(screen.getAllByTestId('partner-icon')).toHaveLength(2)
})
it('does not fall back to org-level integration state when matching project data is unavailable', () => {
mockSelectedOrganization.mockReturnValue(
createMockOrganization({
slug: 'stripe-org',
billing_partner: null,
integration_source: 'stripe_projects',
managed_by: MANAGED_BY.STRIPE_PROJECTS,
})
)
mockSelectedProject.mockReturnValue({
ref: 'proj_2',
name: 'Mallet',
parentRef: 'proj_2',
parent_project_ref: undefined,
integration_source: null,
})
mockSelectorProject.mockReturnValue({
ref: 'proj_2',
name: 'Mallet',
status: 'ACTIVE_HEALTHY',
integration_source: null,
})
render()
expect(screen.queryAllByTestId('partner-icon')).toHaveLength(0)
})
it('falls back to the organization-level state for partner-billed orgs', () => {
mockSelectedOrganization.mockReturnValue(
createMockOrganization({
slug: 'partner-org',
billing_partner: 'vercel_marketplace',
managed_by: MANAGED_BY.VERCEL_MARKETPLACE,
})
)
mockSelectedProject.mockReturnValue({
ref: 'proj_2',
name: 'Mallet',
parentRef: 'proj_2',
parent_project_ref: undefined,
integration_source: null,
})
mockSelectorProject.mockReturnValue({
ref: 'proj_2',
name: 'Mallet',
status: 'ACTIVE_HEALTHY',
integration_source: null,
})
render()
expect(screen.getAllByTestId('partner-icon')).toHaveLength(1)
expect(screen.getByTestId('partner-icon')).toHaveAttribute(
'data-managed-by',
MANAGED_BY.VERCEL_MARKETPLACE
)
})
})