OrganizationLayout.test.tsx272 lines · main
1import { fireEvent, screen } from '@testing-library/react'
2import { LOCAL_STORAGE_KEYS } from 'common'
3import { beforeEach, describe, expect, it, vi } from 'vitest'
4
5import OrganizationLayout from './OrganizationLayout'
6import { MANAGED_BY } from '@/lib/constants/infrastructure'
7import { createMockOrganization, render } from '@/tests/helpers'
8
9const {
10 mockUseAwsRedirectQuery,
11 mockUseCustomContent,
12 mockUseLocalStorageQuery,
13 mockSetIsBannerDismissed,
14 mockUseRegisterOrgMenu,
15 mockUseSelectedOrganizationQuery,
16 mockUseVercelRedirectQuery,
17} = vi.hoisted(() => ({
18 mockUseAwsRedirectQuery: vi.fn(),
19 mockUseCustomContent: vi.fn(),
20 mockUseLocalStorageQuery: vi.fn(),
21 mockSetIsBannerDismissed: vi.fn(),
22 mockUseRegisterOrgMenu: vi.fn(),
23 mockUseSelectedOrganizationQuery: vi.fn(),
24 mockUseVercelRedirectQuery: vi.fn(),
25}))
26
27vi.mock('@/hooks/misc/useSelectedOrganization', () => ({
28 useSelectedOrganizationQuery: mockUseSelectedOrganizationQuery,
29}))
30
31vi.mock('@/data/integrations/vercel-redirect-query', () => ({
32 useVercelRedirectQuery: mockUseVercelRedirectQuery,
33}))
34
35vi.mock('@/data/integrations/aws-redirect-query', () => ({
36 useAwsRedirectQuery: mockUseAwsRedirectQuery,
37}))
38
39vi.mock('@/hooks/misc/useLocalStorage', () => ({
40 useLocalStorageQuery: mockUseLocalStorageQuery,
41}))
42
43vi.mock('@/hooks/custom-content/useCustomContent', () => ({
44 useCustomContent: mockUseCustomContent,
45}))
46
47vi.mock('@/hooks/misc/withAuth', () => ({
48 withAuth: (Component: any) => Component,
49}))
50
51vi.mock('./OrganizationLayout/useRegisterOrgMenu', () => ({
52 useRegisterOrgMenu: mockUseRegisterOrgMenu,
53}))
54
55vi.mock('@/components/ui/PartnerIcon', () => ({
56 default: () => <div data-testid="partner-icon" />,
57}))
58
59const renderLayout = () =>
60 render(
61 <OrganizationLayout title="General">
62 <div>Organization content</div>
63 </OrganizationLayout>
64 )
65
66describe('OrganizationLayout', () => {
67 beforeEach(() => {
68 vi.clearAllMocks()
69
70 mockUseLocalStorageQuery.mockReturnValue([
71 false,
72 mockSetIsBannerDismissed,
73 { isSuccess: true, isLoading: false, isError: false, error: null },
74 ])
75 mockUseCustomContent.mockReturnValue({ appTitle: 'Briven' })
76 mockUseVercelRedirectQuery.mockReturnValue({ data: undefined, isSuccess: false })
77 mockUseAwsRedirectQuery.mockReturnValue({ data: undefined, isSuccess: false })
78 })
79
80 it('renders the exact Vercel banner copy and manage URL', () => {
81 mockUseSelectedOrganizationQuery.mockReturnValue({
82 data: createMockOrganization({
83 managed_by: MANAGED_BY.VERCEL_MARKETPLACE,
84 partner_id: 'vercel-installation-id',
85 }),
86 })
87 mockUseVercelRedirectQuery.mockReturnValue({
88 data: { url: 'https://vercel.com/manage-org' },
89 isSuccess: true,
90 })
91
92 renderLayout()
93
94 expect(screen.getByText('This organization is managed via Vercel Marketplace')).toBeTruthy()
95 expect(
96 screen.getByText('Billing and some organization access settings are managed in Vercel.')
97 ).toBeTruthy()
98 expect(screen.getByRole('link', { name: 'Manage' }).getAttribute('href')).toBe(
99 'https://vercel.com/manage-org'
100 )
101 expect(mockUseVercelRedirectQuery).toHaveBeenCalledWith(
102 { installationId: 'vercel-installation-id' },
103 expect.objectContaining({ enabled: true })
104 )
105 expect(mockUseLocalStorageQuery).toHaveBeenCalledWith(
106 LOCAL_STORAGE_KEYS.ORGANIZATION_MARKETPLACE_BANNER_DISMISSED(
107 'abcdefghijklmnopqrst',
108 MANAGED_BY.VERCEL_MARKETPLACE
109 ),
110 false
111 )
112 expect(mockUseAwsRedirectQuery).toHaveBeenCalledWith(
113 { organizationSlug: 'abcdefghijklmnopqrst' },
114 expect.objectContaining({ enabled: false })
115 )
116 })
117
118 it('renders the exact AWS banner copy and manage URL', () => {
119 mockUseSelectedOrganizationQuery.mockReturnValue({
120 data: createMockOrganization({
121 managed_by: MANAGED_BY.AWS_MARKETPLACE,
122 slug: 'aws-org',
123 }),
124 })
125 mockUseAwsRedirectQuery.mockReturnValue({
126 data: { url: 'https://console.aws.amazon.com/billing/home' },
127 isSuccess: true,
128 })
129
130 renderLayout()
131
132 expect(screen.getByText('This organization is billed via AWS Marketplace')).toBeTruthy()
133 expect(
134 screen.getByText('Changes to billing and payment details must be made in AWS.')
135 ).toBeTruthy()
136 expect(screen.getByRole('link', { name: 'Manage' }).getAttribute('href')).toBe(
137 'https://console.aws.amazon.com/billing/home'
138 )
139 expect(mockUseAwsRedirectQuery).toHaveBeenCalledWith(
140 { organizationSlug: 'aws-org' },
141 expect.objectContaining({ enabled: true })
142 )
143 expect(mockUseLocalStorageQuery).toHaveBeenCalledWith(
144 LOCAL_STORAGE_KEYS.ORGANIZATION_MARKETPLACE_BANNER_DISMISSED(
145 'aws-org',
146 MANAGED_BY.AWS_MARKETPLACE
147 ),
148 false
149 )
150 expect(mockUseVercelRedirectQuery).toHaveBeenCalledWith(
151 { installationId: undefined },
152 expect.objectContaining({ enabled: false })
153 )
154 })
155
156 it('does not render Manage for Vercel when redirect URL is unavailable', () => {
157 mockUseSelectedOrganizationQuery.mockReturnValue({
158 data: createMockOrganization({
159 managed_by: MANAGED_BY.VERCEL_MARKETPLACE,
160 partner_id: 'vercel-installation-id',
161 }),
162 })
163 mockUseVercelRedirectQuery.mockReturnValue({
164 data: undefined,
165 isSuccess: false,
166 })
167
168 renderLayout()
169
170 expect(screen.getByText('This organization is managed via Vercel Marketplace')).toBeTruthy()
171 expect(screen.queryByRole('link', { name: 'Manage' })).toBeNull()
172 })
173
174 it('does not render Manage for AWS when redirect URL is unavailable', () => {
175 mockUseSelectedOrganizationQuery.mockReturnValue({
176 data: createMockOrganization({
177 managed_by: MANAGED_BY.AWS_MARKETPLACE,
178 slug: 'aws-org',
179 }),
180 })
181 mockUseAwsRedirectQuery.mockReturnValue({
182 data: undefined,
183 isSuccess: false,
184 })
185
186 renderLayout()
187
188 expect(screen.getByText('This organization is billed via AWS Marketplace')).toBeTruthy()
189 expect(screen.queryByRole('link', { name: 'Manage' })).toBeNull()
190 })
191
192 it('does not render a banner for Briven-managed organizations', () => {
193 mockUseSelectedOrganizationQuery.mockReturnValue({
194 data: createMockOrganization({
195 managed_by: MANAGED_BY.BRIVEN,
196 }),
197 })
198
199 renderLayout()
200
201 expect(screen.queryByRole('link', { name: 'Manage' })).toBeNull()
202 expect(screen.queryByText('This organization is managed via Vercel Marketplace')).toBeNull()
203 expect(screen.queryByText('This organization is billed via AWS Marketplace')).toBeNull()
204 })
205
206 it('renders Stripe connected copy with no Manage button', () => {
207 mockUseSelectedOrganizationQuery.mockReturnValue({
208 data: createMockOrganization({
209 managed_by: MANAGED_BY.STRIPE_PROJECTS,
210 }),
211 })
212
213 renderLayout()
214
215 expect(screen.getByText('This organization is connected to Stripe')).toBeTruthy()
216 expect(
217 screen.getByText('Changes here will be reflected in your connected Stripe account.')
218 ).toBeTruthy()
219 expect(screen.queryByRole('link', { name: 'Manage' })).toBeNull()
220 expect(mockUseVercelRedirectQuery).toHaveBeenCalledWith(
221 { installationId: undefined },
222 expect.objectContaining({ enabled: false })
223 )
224 expect(mockUseLocalStorageQuery).toHaveBeenCalledWith(
225 LOCAL_STORAGE_KEYS.ORGANIZATION_MARKETPLACE_BANNER_DISMISSED(
226 'abcdefghijklmnopqrst',
227 MANAGED_BY.STRIPE_PROJECTS
228 ),
229 false
230 )
231 expect(mockUseAwsRedirectQuery).toHaveBeenCalledWith(
232 { organizationSlug: 'abcdefghijklmnopqrst' },
233 expect.objectContaining({ enabled: false })
234 )
235 })
236
237 it('hides banner when dismissal state is persisted', () => {
238 mockUseLocalStorageQuery.mockReturnValue([
239 true,
240 mockSetIsBannerDismissed,
241 { isSuccess: true, isLoading: false, isError: false, error: null },
242 ])
243 mockUseSelectedOrganizationQuery.mockReturnValue({
244 data: createMockOrganization({
245 managed_by: MANAGED_BY.VERCEL_MARKETPLACE,
246 partner_id: 'vercel-installation-id',
247 }),
248 })
249
250 renderLayout()
251
252 expect(screen.queryByRole('link', { name: 'Manage' })).toBeNull()
253 expect(screen.queryByText('This organization is managed via Vercel Marketplace')).toBeNull()
254 })
255
256 it('dismisses the banner and persists the state', () => {
257 mockUseSelectedOrganizationQuery.mockReturnValue({
258 data: createMockOrganization({
259 managed_by: MANAGED_BY.AWS_MARKETPLACE,
260 }),
261 })
262 mockUseAwsRedirectQuery.mockReturnValue({
263 data: { url: 'https://console.aws.amazon.com/billing/home' },
264 isSuccess: true,
265 })
266
267 renderLayout()
268
269 fireEvent.click(screen.getByRole('button', { name: 'Dismiss banner' }))
270 expect(mockSetIsBannerDismissed).toHaveBeenCalledWith(true)
271 })
272})