mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 01:15:03 +03:00
fix(studio): show compute waitlist notice when project is not enrolled (#51224)
Resolves FUNC-941 ## What When a project isn't enrolled in Compute, show a short notice with a link to the waitlist (https://supabase.com/compute) instead of a generic error. ## Why The compute API returns its 404 as `{ "error": { "code", "message" } }`. `handleError` only reads a top-level `message`, so it dropped the status code, `isComputeUnavailable` never matched, and users saw "API error happened while trying to communicate with the server." The query now checks `response.status === 404` directly. ## Testing - [ ] Project not enrolled in Compute: the waitlist notice shows - [ ] Enrolled project: the instance list loads as before
This commit is contained in:
1 parent
4ab54b9359
commit
7353782724
3 files changed
+43
-10
No files matched your search
@@ -4,7 +4,7 @@ import { computeRefetchInterval, parseComputeInstance } from './compute.utils'
|
||||
import { computeKeys } from './keys'
|
||||
import { get, handleError } from '@/data/fetchers'
|
||||
import { IS_PLATFORM } from '@/lib/constants'
|
||||
import type { ResponseError } from '@/types'
|
||||
import { ResponseError } from '@/types'
|
||||
|
||||
export type ComputeVariables = { projectRef?: string }
|
||||
export type ComputeError = ResponseError
|
||||
@@ -12,11 +12,14 @@ export type ComputeError = ResponseError
|
||||
async function getComputeInstances({ projectRef }: ComputeVariables, signal?: AbortSignal) {
|
||||
if (!projectRef) throw new Error('projectRef is required')
|
||||
|
||||
const { data, error } = await get('/v2/projects/{ref}/compute', {
|
||||
const { data, error, response } = await get('/v2/projects/{ref}/compute', {
|
||||
params: { path: { ref: projectRef } },
|
||||
signal,
|
||||
})
|
||||
|
||||
if (response.status === 404) {
|
||||
throw new ResponseError('Compute is not available for this project', 404)
|
||||
}
|
||||
if (error) return handleError(error)
|
||||
return data.data.map((instance) => parseComputeInstance(instance))
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import { useParams } from 'common'
|
||||
import { RefreshCw } from 'lucide-react'
|
||||
import { ExternalLink, RefreshCw } from 'lucide-react'
|
||||
import { useState } from 'react'
|
||||
import { Button } from 'ui'
|
||||
import { Admonition } from 'ui-patterns/Admonition'
|
||||
@@ -79,8 +79,20 @@ const ComputePage: NextPageWithLayout = () => {
|
||||
{isNotEnrolled && (
|
||||
<Admonition
|
||||
type="default"
|
||||
title={`${PRODUCT_NAME} is not enabled for this project`}
|
||||
description={`${PRODUCT_NAME} is in Private Alpha. Contact support to have this project added to the alpha.`}
|
||||
layout="horizontal"
|
||||
title={`You don't have access to ${PRODUCT_NAME} yet`}
|
||||
description="Join the waitlist to get early access."
|
||||
actions={
|
||||
<Button asChild icon={<ExternalLink />}>
|
||||
<a
|
||||
href="https://supabase.com/compute"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Join waitlist
|
||||
</a>
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
)}
|
||||
{isMissingPermission && (
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
import { QueryClient } from '@tanstack/react-query'
|
||||
import { fireEvent, screen } from '@testing-library/react'
|
||||
import type { components } from 'api-types'
|
||||
import { HttpResponse } from 'msw'
|
||||
import { http, HttpResponse } from 'msw'
|
||||
import { beforeEach, describe, expect, it } from 'vitest'
|
||||
|
||||
import { computeQueryOptions } from '@/data/compute/compute-query'
|
||||
import { API_URL } from '@/lib/constants'
|
||||
import { PRODUCT_NAME } from '@/lib/constants/compute'
|
||||
import ComputePage from '@/pages/project/[ref]/compute/index'
|
||||
import { customRender } from '@/tests/lib/custom-render'
|
||||
import { addAPIMock, type APIErrorBody } from '@/tests/lib/msw'
|
||||
import { addAPIMock, mswServer, type APIErrorBody } from '@/tests/lib/msw'
|
||||
import { routerMock } from '@/tests/lib/route-mock'
|
||||
|
||||
type ListComputeInstancesResponse = components['schemas']['V2ListComputeInstancesResponse_Output']
|
||||
@@ -101,12 +102,29 @@ describe('/project/[ref]/compute', () => {
|
||||
expect(await screen.findByRole('link', { name: 'embed' })).toBeVisible()
|
||||
})
|
||||
|
||||
it('explains that a project outside the alpha is not enrolled', async () => {
|
||||
mockComputeInstancesListFailure(404)
|
||||
it('points a project outside the alpha to the waitlist', async () => {
|
||||
mswServer.use(
|
||||
http.get(`${API_URL}/v2/projects/:ref/compute`, () =>
|
||||
HttpResponse.json(
|
||||
{
|
||||
error: {
|
||||
code: 'not_found.compute.not_enabled',
|
||||
message: 'Compute is not available for this project',
|
||||
},
|
||||
},
|
||||
{ status: 404 }
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
await renderComputePage()
|
||||
|
||||
expect(screen.getByText(`${PRODUCT_NAME} is not enabled for this project`)).toBeVisible()
|
||||
expect(screen.getByText(`You don't have access to ${PRODUCT_NAME} yet`)).toBeVisible()
|
||||
expect(screen.getByRole('link', { name: 'Join waitlist' })).toHaveAttribute(
|
||||
'href',
|
||||
'https://supabase.com/compute'
|
||||
)
|
||||
expect(screen.queryByText('Failed to retrieve compute instances')).not.toBeInTheDocument()
|
||||
expect(screen.queryByRole('table')).not.toBeInTheDocument()
|
||||
})
|
||||
|
||||
|
||||
Reference in new issue
Block a user