Files
payload/templates/plugin/dev/int.spec.ts
Sasha d8a62b7022 feat: plugin template (#10150)
Updates the plugin template and adds it to the monorepo

Includes:
* Integration testing setup 
* Adding custom client / server components via a plugin
* The same building setup that we use for our plugins in the monorepo
* `create-payload-app` dynamically configures the project based on the
name:`dev/tsconfig.json`, `src/index.ts`, `dev/payload.config.ts`
For example, from project name: `payload-plugin-cool`
`src/index.ts`:
```ts
export type PayloadPluginCoolConfig = {
  /**
   * List of collections to add a custom field
   */
  collections?: Partial<Record<CollectionSlug, true>>
  disabled?: boolean
}

export const payloadPluginCool =
  (pluginOptions: PayloadPluginCoolConfig) =>
/// ...
```
`dev/tsconfig.json`:
```json
{
  "extends": "../tsconfig.json",
  "exclude": [],
  "include": [
    "**/*.ts",
    "**/*.tsx",
    "../src/**/*.ts",
    "../src/**/*.tsx",
    "next.config.mjs",
    ".next/types/**/*.ts"
  ],
  "compilerOptions": {
    "baseUrl": "./",
    "paths": {
      "@payload-config": [
        "./payload.config.ts"
      ],
      "payload-plugin-cool": [
        "../src/index.ts"
      ],
      "payload-plugin-cool/client": [
        "../src/exports/client.ts"
      ],
      "payload-plugin-cool/rsc": [
        "../src/exports/rsc.ts"
      ]
    },
    "noEmit": true
  }
}

```

`./dev/payload.config.ts`
```
import { payloadPluginCool } from 'payload-plugin-cool'
///
 plugins: [
    payloadPluginCool({
      collections: {
        posts: true,
      },
    }),
  ],
```

Example of published plugin
https://www.npmjs.com/package/payload-plugin-cool
2024-12-27 14:25:08 +00:00

91 lines
2.4 KiB
TypeScript

/* eslint-disable no-console */
/**
* Here are your integration tests for the plugin.
* They don't require running your Next.js so they are fast
* Yet they still can test the Local API and custom endpoints using NextRESTClient helper.
*/
import type { Payload } from 'payload'
import dotenv from 'dotenv'
import { MongoMemoryReplSet } from 'mongodb-memory-server'
import path from 'path'
import { getPayload } from 'payload'
import { fileURLToPath } from 'url'
import { NextRESTClient } from './helpers/NextRESTClient.js'
const dirname = path.dirname(fileURLToPath(import.meta.url))
let payload: Payload
let restClient: NextRESTClient
let memoryDB: MongoMemoryReplSet | undefined
describe('Plugin tests', () => {
beforeAll(async () => {
process.env.DISABLE_PAYLOAD_HMR = 'true'
process.env.PAYLOAD_DROP_DATABASE = 'true'
dotenv.config({
path: path.resolve(dirname, './.env'),
})
if (!process.env.DATABASE_URI) {
console.log('Starting memory database')
memoryDB = await MongoMemoryReplSet.create({
replSet: {
count: 3,
dbName: 'payloadmemory',
},
})
console.log('Memory database started')
process.env.DATABASE_URI = `${memoryDB.getUri()}&retryWrites=true`
}
const { default: config } = await import('./payload.config.js')
payload = await getPayload({ config })
restClient = new NextRESTClient(payload.config)
})
afterAll(async () => {
if (payload.db.destroy) {
await payload.db.destroy()
}
if (memoryDB) {
await memoryDB.stop()
}
})
it('should query added by plugin custom endpoint', async () => {
const response = await restClient.GET('/my-plugin-endpoint')
expect(response.status).toBe(200)
const data = await response.json()
expect(data).toMatchObject({
message: 'Hello from custom endpoint',
})
})
it('can create post with a custom text field added by plugin', async () => {
const post = await payload.create({
collection: 'posts',
data: {
addedByPlugin: 'added by plugin',
},
})
expect(post.addedByPlugin).toBe('added by plugin')
})
it('plugin creates and seeds plugin-collection', async () => {
expect(payload.collections['plugin-collection']).toBeDefined()
const { docs } = await payload.find({ collection: 'plugin-collection' })
expect(docs).toHaveLength(1)
})
})