Skip to content

Commit b2f666a

Browse files
authored
test(e2e): remove hardcoded resources from hot paths for e2e testing (#558)
1 parent 221fe05 commit b2f666a

File tree

19 files changed

+276
-170
lines changed

19 files changed

+276
-170
lines changed

.env.example

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,16 @@
1+
# Though working on the SDK doesn't require these environment variables,
2+
# writing and debugging Playwright tests for features does.
3+
#
4+
# Copy this file to `.env.local` (`cp .env.example .env.local`) and fill in the values there
5+
# (`.env.local` is ignored by git)
6+
7+
# This is a write token that allows Playwright to interact with the kitchensink app / project as an authenticated user
8+
# You can generate your own token by heading over to the tokens-section of
9+
# https://www.sanity.work/manage/, or
10+
# by using your CLI user token (`SANITY_INTERNAL_ENV=staging sanity debug --secrets`)
111
SDK_E2E_SESSION_TOKEN=
12+
SDK_E2E_PROJECT_ID=3j6vt2rg
13+
14+
# we test with multiple Resource configurations at once. For now, these are in the same project
15+
SDK_E2E_DATASET_0=production
16+
SDK_E2E_DATASET_1=testing

.github/workflows/depcheck.yml

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,3 @@ jobs:
2828

2929
- name: Depcheck
3030
run: pnpm depcheck
31-
env:
32-
CI: true
33-
SDK_E2E_USER_ID: ${{ secrets.SDK_E2E_USER_ID }}
34-
SDK_E2E_USER_PASSWORD: ${{ secrets.SDK_E2E_USER_PASSWORD }}
35-
RECAPTCHA_E2E_STAGING_KEY: ${{ secrets.RECAPTCHA_E2E_STAGING_KEY }}

apps/kitchensink-react/e2e/authenticated.spec.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ test.describe('Authenticated', () => {
55
test('Kitchen sink loads when authenticated', async ({page}) => {
66
await page.goto('/')
77

8+
// wait a bit -- the redirect can happen too quickly and then be misleading
9+
await page.waitForTimeout(1000)
10+
811
// should be able to see the component beneath the AuthBoundary
912
await expect(page.getByTestId('project-auth-home')).toBeVisible()
1013
// Verify we're authenticated by checking for the absence of the sign-in link

apps/kitchensink-react/playwright.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ export default createPlaywrightConfig({
44
testDir: './e2e',
55
/* Run your local dev server before starting the tests */
66
webServer: {
7-
command: 'pnpm dev',
7+
command: 'pnpm dev --mode e2e',
88
url: 'http://localhost:3333',
99
reuseExistingServer: !process.env['CI'],
1010
stdout: 'pipe',

apps/kitchensink-react/src/App.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {type JSX, Suspense} from 'react'
55
import {BrowserRouter, useNavigate} from 'react-router'
66

77
import {AppRoutes} from './AppRoutes'
8-
import {devConfig, e2eConfig} from './sanityConfig'
8+
import {devConfigs, e2eConfigs} from './sanityConfigs'
99

1010
const theme = buildTheme({})
1111

@@ -22,7 +22,7 @@ export default function App(): JSX.Element {
2222
<ThemeProvider theme={theme}>
2323
<SanityApp
2424
fallback={<Spinner />}
25-
config={import.meta.env['VITE_IS_CI'] ? e2eConfig : devConfig}
25+
config={import.meta.env['VITE_IS_E2E'] ? e2eConfigs : devConfigs}
2626
>
2727
<BrowserRouter>
2828
<Suspense>

apps/kitchensink-react/src/DocumentCollection/DocumentEditorRoute.tsx

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,27 @@
11
/* eslint-disable no-console */
22
import {
33
createDocument,
4-
createDocumentHandle,
54
deleteDocument,
65
discardDocument,
6+
type DocumentHandle,
77
editDocument,
88
publishDocument,
99
unpublishDocument,
1010
useApplyDocumentActions,
1111
useDocument,
1212
useDocumentEvent,
1313
useDocumentPermissions,
14+
useDocuments,
1415
useDocumentSyncStatus,
1516
useEditDocument,
1617
} from '@sanity/sdk-react'
1718
import {Box, Button, TextInput, Tooltip} from '@sanity/ui'
1819
import {JsonData, JsonEditor} from 'json-edit-react'
1920
import {type JSX, useState} from 'react'
2021

21-
const docHandle = createDocumentHandle({
22-
documentType: 'author',
23-
documentId: 'db06bc9e-4608-465a-9551-a10cef478037',
24-
projectId: 'ppsg7ml5',
25-
dataset: 'test',
26-
})
22+
function DocumentEditor({docHandle}: {docHandle: DocumentHandle<'author'>}) {
23+
const [value, setValue] = useState('')
2724

28-
function Editor() {
2925
useDocumentEvent({...docHandle, onEvent: (e) => console.log(e)})
3026
const synced = useDocumentSyncStatus(docHandle)
3127
const apply = useApplyDocumentActions()
@@ -40,9 +36,7 @@ function Editor() {
4036
const {data: name = ''} = useDocument({...docHandle, path: 'name'})
4137
const setName = useEditDocument({...docHandle, path: 'name'})
4238

43-
const [value, setValue] = useState('')
44-
45-
const {data: document} = useDocument({...docHandle})
39+
const {data: document} = useDocument(docHandle)
4640
const setDocument = useEditDocument(docHandle)
4741

4842
return (
@@ -125,6 +119,25 @@ function Editor() {
125119
)
126120
}
127121

122+
function Editor() {
123+
const {data: documents} = useDocuments({
124+
documentType: 'author',
125+
batchSize: 1,
126+
})
127+
128+
const docHandle = documents[0] ?? null
129+
130+
if (!docHandle) {
131+
return <Box padding={4}>No documents found</Box>
132+
}
133+
134+
if (!docHandle) {
135+
return <Box padding={4}>Loading...</Box>
136+
}
137+
138+
return <DocumentEditor docHandle={docHandle} />
139+
}
140+
128141
export function DocumentEditorRoute(): JSX.Element {
129142
return <Editor />
130143
}

apps/kitchensink-react/src/DocumentCollection/MultiResourceRoute.tsx

Lines changed: 122 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -1,110 +1,138 @@
1-
import {createDocumentHandle, useDocument, useEditDocument} from '@sanity/sdk-react'
2-
import {TextInput} from '@sanity/ui'
1+
import {type DocumentHandle, useDocument, useDocuments, useEditDocument} from '@sanity/sdk-react'
2+
import {Box, TextInput} from '@sanity/ui'
33
import {JSX} from 'react'
44

5-
const doc = createDocumentHandle({
6-
documentType: 'author',
7-
documentId: 'db06bc9e-4608-465a-9551-a10cef478037',
8-
projectId: 'ppsg7ml5',
9-
dataset: 'test',
10-
})
5+
import {devConfigs, e2eConfigs} from '../sanityConfigs'
116

12-
const doc2 = createDocumentHandle({
13-
documentType: 'player',
14-
documentId: 'a1b3019b-a0e0-49d5-8212-9d85b9661202',
15-
projectId: 'd45jg133',
16-
dataset: 'production',
17-
})
7+
function AuthorEditor({docHandle}: {docHandle: DocumentHandle<'author'>}) {
8+
const {data: author} = useDocument(docHandle)
9+
const setAuthorName = useEditDocument({...docHandle, path: 'name'})
10+
11+
return (
12+
<div
13+
style={{
14+
padding: '2rem',
15+
borderRadius: '8px',
16+
backgroundColor: '#3f0067',
17+
boxShadow: '0 2px 4px rgba(0,0,0,0.1)',
18+
minWidth: '300px',
19+
flex: 1,
20+
color: '#fff',
21+
}}
22+
>
23+
<h2 style={{marginBottom: '1rem'}}>
24+
Author Document ({docHandle.projectId}.{docHandle.dataset})
25+
</h2>
26+
<a
27+
style={{display: 'block', marginBottom: '1rem', color: '#3e41e7'}}
28+
href={`https://test-studio.sanity.build/${docHandle.dataset}/structure/author;${author?._id}`}
29+
target="_blank"
30+
rel="noopener noreferrer"
31+
>
32+
View in Studio →
33+
</a>
34+
<h3 style={{fontSize: '1.5rem', marginBottom: '0.5rem'}}>{author?.name}</h3>
35+
<TextInput
36+
label="Name"
37+
type="text"
38+
value={author?.name}
39+
onChange={(e) => setAuthorName(e.currentTarget.value)}
40+
/>
41+
{author?.role && <p style={{color: '#fff', marginBottom: '1rem'}}>Role: {author.role}</p>}
42+
{author?.awards && author.awards.length > 0 && (
43+
<div>
44+
<h4 style={{marginBottom: '0.5rem'}}>Awards</h4>
45+
<ul style={{paddingLeft: '1.5rem'}}>
46+
{author.awards.map((award: string, index: number) => (
47+
<li key={index}>{award}</li>
48+
))}
49+
</ul>
50+
</div>
51+
)}
52+
</div>
53+
)
54+
}
55+
56+
function PlayerEditor({docHandle}: {docHandle: DocumentHandle<'player'>}) {
57+
const {data: player} = useDocument(docHandle)
58+
const setPlayerName = useEditDocument({...docHandle, path: 'name'})
59+
60+
return (
61+
<div
62+
style={{
63+
padding: '2rem',
64+
borderRadius: '8px',
65+
backgroundColor: '#b4e6ef',
66+
boxShadow: '0 2px 4px rgba(0,0,0,0.1)',
67+
minWidth: '300px',
68+
flex: 1,
69+
color: '#444',
70+
}}
71+
>
72+
<h2 style={{marginBottom: '1rem', color: '#2a2a2a'}}>
73+
Player Document ({docHandle.projectId}.{docHandle.dataset})
74+
</h2>
75+
<a
76+
style={{display: 'block', marginBottom: '1rem', color: '#3e41e7'}}
77+
href={`https://autofoos.com/structure/player;${player?._id}`}
78+
target="_blank"
79+
rel="noopener noreferrer"
80+
>
81+
View in Studio →
82+
</a>
83+
84+
<h3 style={{fontSize: '1.5rem', marginBottom: '0.5rem'}}>{player?.name}</h3>
85+
<TextInput
86+
label="Name"
87+
type="text"
88+
value={player?.name}
89+
onChange={(e) => setPlayerName(e.currentTarget.value)}
90+
/>
91+
<div style={{color: '#444', marginBottom: '1rem'}}>
92+
{player?.slackUserId && `Slack User ID: ${player.slackUserId}`}
93+
</div>
94+
</div>
95+
)
96+
}
1897

1998
export function MultiResourceRoute(): JSX.Element {
20-
const {data: author} = useDocument(doc)
21-
const {data: player} = useDocument(doc2)
22-
const setAuthorName = useEditDocument({...doc, path: 'name'})
23-
const setPlayerName = useEditDocument({...doc2, path: 'name'})
99+
const configs = import.meta.env['VITE_IS_E2E'] ? e2eConfigs : devConfigs
100+
const {data: authorDocuments} = useDocuments({
101+
documentType: 'author',
102+
batchSize: 1,
103+
projectId: configs[0].projectId,
104+
dataset: configs[0].dataset,
105+
})
106+
107+
const {data: playerDocuments} = useDocuments({
108+
documentType: 'player',
109+
batchSize: 1,
110+
projectId: configs[1].projectId,
111+
dataset: configs[1].dataset,
112+
})
113+
114+
const authorHandle = authorDocuments[0] ?? null
115+
const playerHandle = playerDocuments[0] ?? null
116+
117+
if (!authorDocuments.length || !playerDocuments.length) {
118+
return <Box padding={4}>No documents found in one or both datasets</Box>
119+
}
120+
121+
if (!authorHandle || !playerHandle) {
122+
return <Box padding={4}>Loading...</Box>
123+
}
24124

25125
return (
26126
<div>
27127
<p style={{marginBottom: '2rem'}}>
28128
This route demonstrates how to use multiple resources in a single page.
29129
<br />
30-
Note you must have access to both resources (ppsg7ml5.test and d45jg133.production) to see
31-
the documents.
130+
Note you must have access to both resources ({configs[0].projectId}.{configs[0].dataset} and{' '}
131+
{configs[1].projectId}.{configs[1].dataset}) to see the documents.
32132
</p>
33133
<div style={{display: 'flex', gap: '2rem', flexWrap: 'wrap'}}>
34-
<div
35-
style={{
36-
padding: '2rem',
37-
borderRadius: '8px',
38-
backgroundColor: '#3f0067',
39-
boxShadow: '0 2px 4px rgba(0,0,0,0.1)',
40-
minWidth: '300px',
41-
flex: 1,
42-
color: '#fff',
43-
}}
44-
>
45-
<h2 style={{marginBottom: '1rem'}}>Author Document (ppsg7ml5.test)</h2>
46-
<a
47-
style={{display: 'block', marginBottom: '1rem', color: '#3e41e7'}}
48-
href={`https://test-studio.sanity.build/test/structure/author;${author?._id}`}
49-
target="_blank"
50-
rel="noopener noreferrer"
51-
>
52-
View in Studio →
53-
</a>
54-
<h3 style={{fontSize: '1.5rem', marginBottom: '0.5rem'}}>{author?.name}</h3>
55-
<TextInput
56-
label="Name"
57-
type="text"
58-
value={author?.name}
59-
onChange={(e) => setAuthorName(e.currentTarget.value)}
60-
/>
61-
{author?.role && <p style={{color: '#fff', marginBottom: '1rem'}}>Role: {author.role}</p>}
62-
{author?.awards && author.awards.length > 0 && (
63-
<div>
64-
<h4 style={{marginBottom: '0.5rem'}}>Awards</h4>
65-
<ul style={{paddingLeft: '1.5rem'}}>
66-
{author.awards.map((award, index) => (
67-
<li key={index}>{award}</li>
68-
))}
69-
</ul>
70-
</div>
71-
)}
72-
</div>
73-
74-
<div
75-
style={{
76-
padding: '2rem',
77-
borderRadius: '8px',
78-
backgroundColor: '#b4e6ef',
79-
boxShadow: '0 2px 4px rgba(0,0,0,0.1)',
80-
minWidth: '300px',
81-
flex: 1,
82-
color: '#444',
83-
}}
84-
>
85-
<h2 style={{marginBottom: '1rem', color: '#2a2a2a'}}>
86-
Player Document (d45jg133.production)
87-
</h2>
88-
<a
89-
style={{display: 'block', marginBottom: '1rem', color: '#3e41e7'}}
90-
href={`https://autofoos.com/structure/player;${player?._id}`}
91-
target="_blank"
92-
rel="noopener noreferrer"
93-
>
94-
View in Studio →
95-
</a>
96-
97-
<h3 style={{fontSize: '1.5rem', marginBottom: '0.5rem'}}>{player?.name}</h3>
98-
<TextInput
99-
label="Name"
100-
type="text"
101-
value={player?.name}
102-
onChange={(e) => setPlayerName(e.currentTarget.value)}
103-
/>
104-
<div style={{color: '#444', marginBottom: '1rem'}}>
105-
{player?.slackUserId && `Slack User ID: ${player.slackUserId}`}
106-
</div>
107-
</div>
134+
<AuthorEditor docHandle={authorHandle} />
135+
<PlayerEditor docHandle={playerHandle} />
108136
</div>
109137
</div>
110138
)

apps/kitchensink-react/src/sanityConfig.ts

Lines changed: 0 additions & 22 deletions
This file was deleted.

0 commit comments

Comments
 (0)