Skip to content

Commit cd6689d

Browse files
committed
test(e2e): create e2e tests for recent source changes
1 parent 6845df6 commit cd6689d

File tree

13 files changed

+581
-165
lines changed

13 files changed

+581
-165
lines changed

.env.example

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,19 @@ SDK_E2E_DATASET_0=production
1919
SDK_E2E_DATASET_1=testing
2020

2121

22+
# The media library ID provisioned for e2e testing
23+
SDK_E2E_MEDIA_LIBRARY_ID=mlyobHbSHBsj
24+
25+
2226
# This is a write token that allows us to use the client to create / destroy / edit resources
2327
# (which Playwright will then load in the kitchensink app to test against)
2428
# You can generate your own token by heading over to the tokens section of
2529
# https://www.sanity.work/manage/, or
2630
# by using your CLI user token (`SANITY_INTERNAL_ENV=staging sanity debug --secrets`)
2731
SDK_E2E_SESSION_TOKEN=
2832

33+
# This is a write token that allows us to use the media library client to create / destroy / edit resources
34+
# This is generated on the org admin page. If you are a user with media library permissions, you can just
35+
# use the same user session token you used above.
36+
SDK_E2E_MEDIA_LIBRARY_TOKEN=
37+

.github/workflows/e2e.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ jobs:
7070
SDK_E2E_ORGANIZATION_ID: ${{ secrets.SDK_E2E_ORGANIZATION_ID }}
7171
SDK_E2E_DATASET_0: ${{ github.event_name == 'pull_request' && format('pr-{0}-{1}-{2}', github.event.number, matrix.browser, github.run_id) || format('main-{0}-{1}', matrix.browser, github.run_id) }}
7272
SDK_E2E_DATASET_1: ${{ github.event_name == 'pull_request' && format('pr-{0}-{1}-secondary-{2}', github.event.number, matrix.browser, github.run_id) || format('main-{0}-secondary-{1}', matrix.browser, github.run_id) }}
73+
SDK_E2E_MEDIA_LIBRARY_ID: ${{ secrets.SDK_E2E_MEDIA_LIBRARY_ID }}
74+
SDK_E2E_MEDIA_LIBRARY_TOKEN: ${{ secrets.SDK_E2E_MEDIA_LIBRARY_TOKEN }}
7375
SDK_E2E_SESSION_TOKEN: ${{ secrets.SDK_E2E_SESSION_TOKEN }}
7476
SDK_E2E_USER_ID: ${{ secrets.SDK_E2E_USER_ID }}
7577
SDK_E2E_USER_PASSWORD: ${{ secrets.SDK_E2E_USER_PASSWORD }}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import {expect, test} from '@repo/e2e'
2+
3+
test.describe('Media Library', () => {
4+
test('can patch media library asset and see updates in useQuery and projection', async ({
5+
page,
6+
getPageContext,
7+
getMediaLibraryClient,
8+
}) => {
9+
// Navigate to the media library route
10+
await page.goto('./media-library')
11+
const pageContext = await getPageContext(page)
12+
13+
// Wait for the query results to be visible
14+
const queryResultsElement = pageContext.getByTestId('query-results')
15+
await queryResultsElement.waitFor({timeout: 15000})
16+
17+
const projectionResultsElement = pageContext.getByTestId('projection-results')
18+
await projectionResultsElement.waitFor({timeout: 15000})
19+
20+
// Extract the JSON text from the query results
21+
const queryJsonText = await queryResultsElement.textContent()
22+
expect(queryJsonText).toBeTruthy()
23+
24+
// Parse the JSON to get the query results
25+
const queryResults = JSON.parse(queryJsonText!)
26+
27+
// Get the first asset's _id
28+
const firstAsset = queryResults[0]
29+
expect(firstAsset).toHaveProperty('_id')
30+
const assetId = firstAsset._id
31+
expect(assetId).toBeTruthy()
32+
33+
// Verify the projection results are showing for the same asset
34+
const projectionJsonText = await projectionResultsElement.textContent()
35+
expect(projectionJsonText).toBeTruthy()
36+
const projectionData = JSON.parse(projectionJsonText!)
37+
expect(projectionData).toBeTruthy()
38+
39+
// Create a media library client
40+
const mediaLibraryClient = getMediaLibraryClient()
41+
42+
// Create a unique hash key for this test run (for parallel test execution)
43+
const testHash = `test_hash_${Date.now()}_${Math.random().toString(36).substring(7)}`
44+
const testValue = 'test-value'
45+
46+
// Patch the asset with an arbitrary value using a unique hash key, so we can check real-time updates in useQuery and projection.
47+
await mediaLibraryClient
48+
.patch(assetId)
49+
.set({arbitraryValues: {[testHash]: testValue}})
50+
.commit()
51+
52+
// Wait for useQuery to update with the new value
53+
await expect(async () => {
54+
const updatedQueryText = await queryResultsElement.textContent()
55+
expect(updatedQueryText).toBeTruthy()
56+
57+
const updatedQueryResults = JSON.parse(updatedQueryText!)
58+
const updatedAsset = updatedQueryResults.find((asset: {_id: string}) => asset._id === assetId)
59+
60+
expect(updatedAsset).toBeTruthy()
61+
expect(updatedAsset.arbitraryValues).toBeTruthy()
62+
expect(updatedAsset.arbitraryValues[testHash]).toBe(testValue)
63+
}).toPass({timeout: 10000})
64+
65+
// Wait for projection to update with the new value
66+
await expect(async () => {
67+
const updatedProjectionText = await projectionResultsElement.textContent()
68+
expect(updatedProjectionText).toBeTruthy()
69+
70+
const updatedProjectionData = JSON.parse(updatedProjectionText!)
71+
72+
expect(updatedProjectionData).toBeTruthy()
73+
expect(updatedProjectionData.arbitraryValues).toBeTruthy()
74+
expect(updatedProjectionData.arbitraryValues[testHash]).toBe(testValue)
75+
}).toPass({timeout: 10000})
76+
77+
// Cleanup: Remove the test hash from arbitrary values
78+
await mediaLibraryClient
79+
.patch(assetId)
80+
.unset([`arbitraryValues.${testHash}`])
81+
.commit()
82+
})
83+
})
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
import {expect, test} from '@repo/e2e'
2+
import {getVersionId} from 'sanity'
3+
4+
test.describe('Releases Route', () => {
5+
test('can create base documents and release versions', async ({
6+
page,
7+
getClient,
8+
createDocuments,
9+
getPageContext,
10+
}) => {
11+
const client = getClient()
12+
13+
// First create the bestFriend author document so we can test references across docs
14+
const {
15+
documentIds: [bestFriendId],
16+
} = await createDocuments(
17+
[
18+
{
19+
_type: 'author',
20+
name: 'Base Best Friend',
21+
},
22+
],
23+
{asDraft: false},
24+
)
25+
26+
// Create the main test document
27+
const {
28+
documentIds: [testDocId],
29+
} = await createDocuments(
30+
[
31+
{
32+
_type: 'author',
33+
name: 'Base Test Author',
34+
bestFriend: {_type: 'reference', _ref: bestFriendId, _weak: true},
35+
},
36+
],
37+
{asDraft: false},
38+
)
39+
40+
await page.goto('./releases')
41+
const pageContext = await getPageContext(page)
42+
const heading = pageContext.getByText('Releases', {exact: true}).first()
43+
await expect(heading).toBeVisible({timeout: 30000})
44+
45+
// Create the release
46+
const {releaseId} = await client.releases.create({
47+
metadata: {
48+
title: 'Test Release',
49+
releaseType: 'scheduled',
50+
},
51+
})
52+
53+
// Create release version documents
54+
await createDocuments(
55+
[
56+
{
57+
_id: getVersionId(bestFriendId, releaseId),
58+
_type: 'author',
59+
name: 'Release Best Friend',
60+
},
61+
{
62+
_id: getVersionId(testDocId, releaseId),
63+
_type: 'author',
64+
name: 'Release Test Author',
65+
bestFriend: {_type: 'reference', _ref: bestFriendId, _weak: true},
66+
},
67+
],
68+
{asDraft: false},
69+
)
70+
71+
// Verify the release document exists and is being listened to live
72+
const autocompleteInput = pageContext.locator('input[placeholder="Type to find release …"]')
73+
await expect(autocompleteInput).toBeVisible()
74+
75+
await autocompleteInput.click()
76+
await autocompleteInput.fill('Test')
77+
78+
const releaseIdText = pageContext.getByText(`Release ID: ${releaseId}`)
79+
await expect(releaseIdText).toBeVisible({timeout: 10000})
80+
81+
const releaseButton = pageContext.getByRole('button', {
82+
name: new RegExp(`Test Release.*Release ID: ${releaseId}`),
83+
})
84+
await expect(releaseButton).toBeVisible()
85+
await releaseButton.click()
86+
87+
await expect(autocompleteInput).toHaveValue('Test Release', {timeout: 10000})
88+
89+
const selectedPerspectiveHeading = pageContext.getByText('Selected Perspective')
90+
await expect(selectedPerspectiveHeading).toBeVisible()
91+
92+
const releaseIdInPerspective = pageContext.getByText(releaseId).first()
93+
await expect(releaseIdInPerspective).toBeVisible({timeout: 10000})
94+
95+
// Enter the test document ID in the "View Document across different perspectives" input
96+
const documentPerspectiveHeading = pageContext.getByText(
97+
'View Document across different perspectives',
98+
)
99+
await expect(documentPerspectiveHeading).toBeVisible()
100+
101+
const documentIdInput = pageContext.locator('input[placeholder="Enter document ID"]')
102+
await expect(documentIdInput).toBeVisible()
103+
await documentIdInput.fill(testDocId)
104+
await page.waitForTimeout(2000)
105+
106+
const projectionCard = pageContext.getByTestId('document-projection-card')
107+
await projectionCard.scrollIntoViewIfNeeded()
108+
109+
// Verify the projection also shows the release version
110+
await expect(async () => {
111+
const projectionContent = await projectionCard.textContent()
112+
expect(projectionContent).toContain('"bestFriend": "Release Best Friend"')
113+
}).toPass({timeout: 15000})
114+
115+
await client.action([
116+
{
117+
actionType: 'sanity.action.document.edit',
118+
draftId: getVersionId(bestFriendId, releaseId),
119+
publishedId: bestFriendId,
120+
patch: {
121+
set: {
122+
name: 'Updated Release Best Friend',
123+
},
124+
},
125+
},
126+
])
127+
128+
await expect(async () => {
129+
const projectionContent = await projectionCard.textContent()
130+
expect(projectionContent).toContain('"bestFriend": "Updated Release Best Friend"')
131+
}).toPass({timeout: 20000, intervals: [2000, 3000, 5000]})
132+
133+
await client.action([
134+
{
135+
actionType: 'sanity.action.document.edit',
136+
draftId: getVersionId(testDocId, releaseId),
137+
publishedId: testDocId,
138+
patch: {
139+
set: {
140+
name: 'Updated Release Test Author',
141+
},
142+
},
143+
},
144+
])
145+
146+
await expect(async () => {
147+
const projectionContent = await projectionCard.textContent()
148+
expect(projectionContent).toContain('"name": "Updated Release Test Author"')
149+
}).toPass({timeout: 20000, intervals: [2000, 3000, 5000]})
150+
})
151+
})

0 commit comments

Comments
 (0)