Files
supabase/apps/studio/tests
Danny WhiteandJoshen Lim 6b1fc3d11d recover failed Vercel deploy connections (#48474)
## What kind of change does this PR introduce?

Bug fix.

## What is the current behavior?

A failed Vercel connection after project creation is only logged,
leaving the project-creation screen in its loading state.

## What is the new behavior?

The flow preserves the created project and shows the connection error
with retry and open-project actions in the standard project-creation
footer.

Project-creation failures remain ordinary inline form errors. Connection
failures are owned by this flow without a duplicate toast or a no-op
error handler.

| Before | After |
| --- | --- |
| ![Create Vercel Project
Supabase](https://github.com/user-attachments/assets/18dfb6d1-614a-4298-bf28-8399d86c7bca)
| <img width="1024" height="563" alt="Create Vercel Project Supabase"
src="https://github.com/user-attachments/assets/b7d3fdca-d7a0-4b50-9231-3cf7dc371a87"
/> |

## To test

### Before on master

1. Switch to `master`.
2. With local Studio running and while signed in, open an organisation
you can access. Copy its slug from
`http://localhost:8082/org/<YOUR_ORG_SLUG>`.
3. Open
`apps/studio/components/interfaces/ProjectCreation/ProjectCreationForm.tsx`.
4. Find `isSuccessNewProject={isSuccessNewProject}` in the
`ProjectCreationFooter` props and temporarily change it to:
   ```tsx
   isSuccessNewProject={true}
   ```
5. Replace `<YOUR_ORG_SLUG>` in this URL with the slug from step 2, then
open it:
`http://localhost:8082/integrations/vercel/<YOUR_ORG_SLUG>/deploy-button/new-project`.
6. Confirm **Create new project** remains in its loading state and there
is no error, retry action, or route to the created project. This
represents the current stuck state.
7. Revert the temporary edit before switching branches.

### After on this branch

1. Switch to `dnywh/vercel-deploy-recovery`.
2. With local Studio running and while signed in, open an organisation
you can access. Copy its slug from
`http://localhost:8082/org/<YOUR_ORG_SLUG>`.
3. Open
`apps/studio/pages/integrations/vercel/[slug]/deploy-button/new-project.tsx`.
4. Find the conditional beginning with `newProjectRef === undefined`
inside `InterstitialLayout`.
5. Replace that whole conditional with:
   ```tsx
   <VercelConnectionError
     projectRef="abcdefghijklmnopqrst"
     message="Connection request failed"
     onRetry={() => undefined}
   />
   ```
6. Replace `<YOUR_ORG_SLUG>` in this URL with the slug from step 2, then
open it:
`http://localhost:8082/integrations/vercel/<YOUR_ORG_SLUG>/deploy-button/new-project`.
7. Confirm the admonition says **Unable to connect to Vercel** and
**Your Supabase project was still created. Error: Connection request
failed**.
8. Confirm **Open project** and **Retry connection** appear as compact,
right-aligned footer buttons. The retry action is intentionally inert in
this visual-only mock, and no project or Vercel connection is created.
9. Revert the temporary edit.

## Additional context

Follows #48473. The consistency follow-up #48640 is stacked on this PR.



<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **New Features**
- Added inline error messages to project creation forms for integration,
API, and validation failures.
- Added clear Vercel connection states, including waiting, connecting,
success, and error screens.
  - Added retry actions and links to open successfully created projects.

- **Bug Fixes**
- Improved error handling so Vercel connection issues remain visible in
context instead of appearing only as notifications.

- **Tests**
- Added coverage for partial-success messaging, project links, and retry
behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
2026-08-06 10:49:50 +10:00
..

UI Testing Notes

Rules

  • All tests should be run consistently (avoid situations whereby tests fails "sometimes")

  • Group tests in folders based on the feature they are testing. Avoid file/folder based folder names since those can change and we will forget to update the tests.

Examples: /logs /reports /projects /database-settings /auth

Custom Render and Custom Render Hook

customRender and customRenderHook are wrappers around render and renderHook that add some necessary providers like QueryClientProvider, TooltipProvider and NuqsTestingAdapter.

Generally use those instead of the default render and renderHook functions.

import { customRender, customRenderHook } from 'tests/lib/custom-render'

customRender(<MyComponent />)
customRenderHook(() => useMyHook())

Mocking API Requests

To mock API requests, we use the msw library.

Global mocks can be found in tests/lib/msw-global-api-mocks.ts.

To mock an endpoint you can use the addAPIMock function. Make sure to add the mock in the beforeEach hook. It won't work with beforeAll if you have many tests.

beforeEach(() => {
  addAPIMock({
    method: 'get',
    path: '/api/my-endpoint',
    response: {
      data: { foo: 'bar' },
    },
  })
})

API Mocking Tips:

  • Keep mocks in the same folder as the tests that use them
  • Add a test to verify the mock is working

This will make debugging and updating the mocks easier.

test('mock is working', async () => {
  const response = await fetch('/api/my-endpoint')
  expect(response.json()).resolves.toEqual({ data: { foo: 'bar' } })
})

Mocking Nuqs URL Parameters

To render a component that uses Nuqs with some predefined query parameters, you can use customRender with the nuqs prop.


customRender(<MyComponent />, {
  nuqs: {
    searchParams: {
      search: 'hello world',
    },
  },
})

<Popover> vs <Dropdown>

When simulating clicks on these components, do the following:

// for Popovers
import userEvent from '@testing-library/user-event'
await userEvent.click('Hello world')

// for Dropdowns
import clickDropdown from 'tests/helpers'
clickDropdown('Hello world')