Skip to content

Commit 87c7952

Browse files
authored
feat(templates): added int and e2e tests to blank and website templates (#12866)
This PR adds int tests with vitest and e2e tests with playwright directly into our templates. The following are also updated: - bumps core turbo to 2.5.4 in monorepo - blank and website templates moved up to be part of the monorepo workspace - this means we now have thes templates filtered out in pnpm commands in package.json - they will now by default use workspace packages which we can use for manual testing and int and e2e tests - note that turbo doesnt work with these for dev in monorepo context - CPA script will fetch latest version and then replace `workspace:*` or the pinned version in the package.json before installation - blank template no longer uses _template as a base, this is to simplify management for workspace - updated the generate template variations script
1 parent 141133a commit 87c7952

File tree

85 files changed

+8017
-538
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

85 files changed

+8017
-538
lines changed

.github/workflows/main.yml

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -523,24 +523,30 @@ jobs:
523523
# report-tag: ${{ matrix.suite }}
524524
# job-summary: true
525525

526-
# Build listed templates with packed local packages
527-
build-templates:
526+
# Build listed templates with packed local packages and then runs their int and e2e tests
527+
build-and-test-templates:
528528
runs-on: ubuntu-24.04
529529
needs: build
530530
strategy:
531+
fail-fast: false
531532
matrix:
532533
include:
533534
- template: blank
534535
database: mongodb
536+
535537
- template: website
536538
database: mongodb
539+
537540
- template: with-payload-cloud
538541
database: mongodb
542+
539543
- template: with-vercel-mongodb
540544
database: mongodb
545+
541546
# Postgres
542547
- template: with-postgres
543548
database: postgres
549+
544550
- template: with-vercel-postgres
545551
database: postgres
546552

@@ -615,6 +621,45 @@ jobs:
615621
env:
616622
NODE_OPTIONS: --max-old-space-size=8096
617623

624+
- name: Store Playwright's Version
625+
run: |
626+
# Extract the version number using a more targeted regex pattern with awk
627+
PLAYWRIGHT_VERSION=$(pnpm ls @playwright/test --depth=0 | awk '/@playwright\/test/ {print $2}')
628+
echo "Playwright's Version: $PLAYWRIGHT_VERSION"
629+
echo "PLAYWRIGHT_VERSION=$PLAYWRIGHT_VERSION" >> $GITHUB_ENV
630+
631+
- name: Cache Playwright Browsers for Playwright's Version
632+
id: cache-playwright-browsers
633+
uses: actions/cache@v4
634+
with:
635+
path: ~/.cache/ms-playwright
636+
key: playwright-browsers-${{ env.PLAYWRIGHT_VERSION }}
637+
638+
- name: Setup Playwright - Browsers and Dependencies
639+
if: steps.cache-playwright-browsers.outputs.cache-hit != 'true'
640+
run: pnpm exec playwright install --with-deps chromium
641+
642+
- name: Setup Playwright - Dependencies-only
643+
if: steps.cache-playwright-browsers.outputs.cache-hit == 'true'
644+
run: pnpm exec playwright install-deps chromium
645+
646+
- name: Runs Template Int Tests
647+
run: pnpm --filter ${{ matrix.template }} run test:int
648+
env:
649+
NODE_OPTIONS: --max-old-space-size=8096
650+
PAYLOAD_DATABASE: ${{ matrix.database }}
651+
POSTGRES_URL: ${{ env.POSTGRES_URL }}
652+
MONGODB_URL: mongodb://localhost:27017/payloadtests
653+
654+
- name: Runs Template E2E Tests
655+
run: PLAYWRIGHT_JSON_OUTPUT_NAME=results_${{ matrix.template }}.json pnpm --filter ${{ matrix.template }} test:e2e
656+
env:
657+
NODE_OPTIONS: --max-old-space-size=8096
658+
PAYLOAD_DATABASE: ${{ matrix.database }}
659+
POSTGRES_URL: ${{ env.POSTGRES_URL }}
660+
MONGODB_URL: mongodb://localhost:27017/payloadtests
661+
NEXT_TELEMETRY_DISABLED: 1
662+
618663
tests-type-generation:
619664
runs-on: ubuntu-24.04
620665
needs: [changes, build]
@@ -650,7 +695,7 @@ jobs:
650695
needs:
651696
- lint
652697
- build
653-
- build-templates
698+
- build-and-test-templates
654699
- tests-unit
655700
- tests-int
656701
- tests-e2e

docs/plugins/sentry.mdx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,7 @@ import * as Sentry from '@sentry/nextjs'
7575
const config = buildConfig({
7676
collections: [Pages, Media],
7777
plugins: [
78-
sentryPlugin({
79-
Sentry,
80-
}),
78+
sentryPlugin({ Sentry })
8179
],
8280
})
8381

@@ -101,7 +99,7 @@ export default buildConfig({
10199
pg, // Inject the patched pg driver for Sentry instrumentation
102100
}),
103101
plugins: [
104-
sentryPlugin({ Sentry }),
102+
sentryPlugin({ Sentry })
105103
],
106104
})
107105
```

examples/astro/website/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"name": "website",
2+
"name": "astro-website",
33
"version": "0.0.1",
44
"type": "module",
55
"scripts": {

package.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@
1111
"bf": "pnpm run build:force",
1212
"build": "pnpm run build:core",
1313
"build:admin-bar": "turbo build --filter \"@payloadcms/admin-bar\"",
14-
"build:all": "turbo build",
14+
"build:all": "turbo build --filter \"!blank\" --filter \"!website\"",
1515
"build:app": "next build",
1616
"build:app:analyze": "cross-env ANALYZE=true next build",
1717
"build:clean": "pnpm clean:build",
18-
"build:core": "turbo build --filter \"!@payloadcms/plugin-*\" --filter \"!@payloadcms/storage-*\"",
18+
"build:core": "turbo build --filter \"!@payloadcms/plugin-*\" --filter \"!@payloadcms/storage-*\" --filter \"!blank\" --filter \"!website\"",
1919
"build:core:force": "pnpm clean:build && pnpm build:core --no-cache --force",
2020
"build:create-payload-app": "turbo build --filter create-payload-app",
2121
"build:db-mongodb": "turbo build --filter \"@payloadcms/db-mongodb\"",
@@ -79,9 +79,9 @@
7979
"docker:start": "docker compose -f test/docker-compose.yml up -d",
8080
"docker:stop": "docker compose -f test/docker-compose.yml down",
8181
"force:build": "pnpm run build:core:force",
82-
"lint": "turbo run lint --log-order=grouped --continue",
82+
"lint": "turbo run lint --log-order=grouped --continue --filter \"!blank\" --filter \"!website\"",
8383
"lint-staged": "lint-staged",
84-
"lint:fix": "turbo run lint:fix --log-order=grouped --continue",
84+
"lint:fix": "turbo run lint:fix --log-order=grouped --continue --filter \"!blank\" --filter \"!website\"",
8585
"obliterate-playwright-cache-macos": "rm -rf ~/Library/Caches/ms-playwright && find /System/Volumes/Data/private/var/folders -type d -name 'playwright*' -exec rm -rf {} +",
8686
"prepare": "husky",
8787
"prepare-run-test-against-prod": "pnpm bf && rm -rf test/packed && rm -rf test/node_modules && rm -rf app && rm -f test/pnpm-lock.yaml && pnpm run script:pack --all --no-build --dest test/packed && pnpm runts test/setupProd.ts && cd test && pnpm i --ignore-workspace && cd ..",
@@ -181,7 +181,7 @@
181181
"tempy": "1.0.1",
182182
"tstyche": "^3.1.1",
183183
"tsx": "4.19.2",
184-
"turbo": "^2.3.3",
184+
"turbo": "^2.5.4",
185185
"typescript": "5.7.3"
186186
},
187187
"packageManager": "pnpm@9.7.1",

packages/create-payload-app/src/lib/create-project.spec.ts

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import path from 'path'
77

88
import type { CliArgs, DbType, ProjectExample, ProjectTemplate } from '../types.js'
99

10-
import { createProject } from './create-project.js'
10+
import { createProject, updatePackageJSONDependencies } from './create-project.js'
1111
import { dbReplacements } from './replacements.js'
1212
import { getValidTemplates } from './templates.js'
1313

@@ -179,5 +179,37 @@ describe('createProject', () => {
179179
expect(content).toContain(dbReplacement.configReplacement().join('\n'))
180180
})
181181
})
182+
183+
describe('updates package.json', () => {
184+
it('updates package name and bumps workspace versions', async () => {
185+
const latestVersion = '3.0.0'
186+
const initialJSON = {
187+
name: 'test-project',
188+
version: '1.0.0',
189+
dependencies: {
190+
'@payloadcms/db-mongodb': 'workspace:*',
191+
payload: 'workspace:*',
192+
'@payloadcms/ui': 'workspace:*',
193+
},
194+
}
195+
196+
const correctlyModifiedJSON = {
197+
name: 'test-project',
198+
version: '1.0.0',
199+
dependencies: {
200+
'@payloadcms/db-mongodb': `${latestVersion}`,
201+
payload: `${latestVersion}`,
202+
'@payloadcms/ui': `${latestVersion}`,
203+
},
204+
}
205+
206+
updatePackageJSONDependencies({
207+
latestVersion,
208+
packageJson: initialJSON,
209+
})
210+
211+
expect(initialJSON).toEqual(correctlyModifiedJSON)
212+
})
213+
})
182214
})
183215
})

packages/create-payload-app/src/lib/create-project.ts

Lines changed: 94 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,11 @@ export async function createProject(
129129
const spinner = p.spinner()
130130
spinner.start('Checking latest Payload version...')
131131

132-
await updatePackageJSON({ projectDir, projectName })
132+
const payloadVersion = await getLatestPackageVersion({ packageName: 'payload' })
133+
134+
spinner.stop(`Found latest version of Payload ${payloadVersion}`)
135+
136+
await updatePackageJSON({ latestVersion: payloadVersion, projectDir, projectName })
133137

134138
if ('template' in args) {
135139
if (args.template.type === 'plugin') {
@@ -177,17 +181,105 @@ export async function createProject(
177181
}
178182
}
179183

184+
/**
185+
* Reads the package.json file into an object and then does the following:
186+
* - Sets the `name` property to the provided `projectName`.
187+
* - Bumps the payload packages from workspace:* to the latest version.
188+
* - Writes the updated object back to the package.json file.
189+
*/
180190
export async function updatePackageJSON(args: {
191+
/**
192+
* The latest version of Payload to use in the package.json.
193+
*/
194+
latestVersion: string
181195
projectDir: string
196+
/**
197+
* The name of the project to set in package.json.
198+
*/
182199
projectName: string
183200
}): Promise<void> {
184-
const { projectDir, projectName } = args
201+
const { latestVersion, projectDir, projectName } = args
185202
const packageJsonPath = path.resolve(projectDir, 'package.json')
186203
try {
187204
const packageObj = await fse.readJson(packageJsonPath)
188205
packageObj.name = projectName
206+
207+
updatePackageJSONDependencies({
208+
latestVersion,
209+
packageJson: packageObj,
210+
})
211+
189212
await fse.writeJson(packageJsonPath, packageObj, { spaces: 2 })
190213
} catch (err: unknown) {
191214
warning(`Unable to update name in package.json. ${err instanceof Error ? err.message : ''}`)
192215
}
193216
}
217+
218+
/**
219+
* Recursively updates a JSON object to replace all instances of `workspace:` with the latest version pinned.
220+
*
221+
* Does not return and instead modifies the `packageJson` object in place.
222+
*/
223+
export function updatePackageJSONDependencies(args: {
224+
latestVersion: string
225+
packageJson: Record<string, unknown>
226+
}): void {
227+
const { latestVersion, packageJson } = args
228+
229+
const updatedDependencies = Object.entries(packageJson.dependencies || {}).reduce(
230+
(acc, [key, value]) => {
231+
if (typeof value === 'string' && value.startsWith('workspace:')) {
232+
acc[key] = `${latestVersion}`
233+
} else if (key === 'payload' || key.startsWith('@payloadcms')) {
234+
acc[key] = `${latestVersion}`
235+
} else {
236+
acc[key] = value
237+
}
238+
return acc
239+
},
240+
{} as Record<string, string>,
241+
)
242+
packageJson.dependencies = updatedDependencies
243+
}
244+
245+
/**
246+
* Fetches the latest version of a package from the NPM registry.
247+
*
248+
* Used in determining the latest version of Payload to use in the generated templates.
249+
*/
250+
async function getLatestPackageVersion({
251+
packageName = 'payload',
252+
}: {
253+
/**
254+
* Package name to fetch the latest version for based on the NPM registry URL
255+
*
256+
* Eg. for `'payload'`, it will fetch the version from `https://registry.npmjs.org/payload`
257+
*
258+
* @default 'payload'
259+
*/
260+
packageName?: string
261+
}): Promise<string> {
262+
try {
263+
const response = await fetch(`https://registry.npmjs.org/-/package/${packageName}/dist-tags`)
264+
const data = await response.json()
265+
266+
// Monster chaining for type safety just checking for data.latest
267+
const latestVersion =
268+
data &&
269+
typeof data === 'object' &&
270+
'latest' in data &&
271+
data.latest &&
272+
typeof data.latest === 'string'
273+
? data.latest
274+
: null
275+
276+
if (!latestVersion) {
277+
throw new Error(`No latest version found for package: ${packageName}`)
278+
}
279+
280+
return latestVersion
281+
} catch (error) {
282+
console.error('Error fetching Payload version:', error)
283+
throw error
284+
}
285+
}

packages/create-payload-app/src/lib/download-template.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ export async function downloadTemplate({
1717
}) {
1818
const branchOrTag = template.url.split('#')?.[1] || 'latest'
1919
const url = `https://codeload.github.com/payloadcms/payload/tar.gz/${branchOrTag}`
20-
const filter = `payload-${branchOrTag.replace(/^v/, '')}/templates/${template.name}/`
20+
const filter = `payload-${branchOrTag.replace(/^v/, '').replaceAll('/', '-')}/templates/${template.name}/`
2121

2222
if (debug) {
2323
debugLog(`Using template url: ${template.url}`)

packages/next/package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@
2222
],
2323
"type": "module",
2424
"exports": {
25+
"./css": {
26+
"import": "./src/dummy.css",
27+
"default": "./src/dummy.css"
28+
},
2529
".": {
2630
"import": "./src/index.js",
2731
"types": "./src/index.js",

packages/next/src/dummy.css

Whitespace-only changes.

packages/ui/package.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,16 @@
3636
"import": "./src/scss/styles.scss",
3737
"default": "./src/scss/styles.scss"
3838
},
39+
"./icons/*": {
40+
"import": "./src/icons/*/index.tsx",
41+
"types": "./src/icons/*/index.tsx",
42+
"default": "./src/icons/*/index.tsx"
43+
},
44+
"./elements/*": {
45+
"import": "./src/elements/*/index.tsx",
46+
"types": "./src/elements/*/index.tsx",
47+
"default": "./src/elements/*/index.tsx"
48+
},
3949
"./elements/RenderServerComponent": {
4050
"import": "./src/elements/RenderServerComponent/index.tsx",
4151
"types": "./src/elements/RenderServerComponent/index.tsx",

0 commit comments

Comments
 (0)