chore(plugin-stripe): scaffolds tests (#4510)
This commit is contained in:
@@ -1,6 +0,0 @@
|
|||||||
PAYLOAD_PUBLIC_CMS_URL=http://localhost:3000
|
|
||||||
DATABASE_URI=mongodb://localhost/payload-plugin-stripe
|
|
||||||
PAYLOAD_SECRET=
|
|
||||||
STRIPE_SECRET_KEY=
|
|
||||||
STRIPE_WEBHOOKS_ENDPOINT_SECRET=
|
|
||||||
PAYLOAD_PUBLIC_IS_STRIPE_TEST_KEY=true
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
{
|
|
||||||
"exec": "ts-node src/server.ts",
|
|
||||||
"ext": "ts"
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "payload-starter-typescript",
|
|
||||||
"description": "Blank template - no collections",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"main": "dist/server.js",
|
|
||||||
"license": "MIT",
|
|
||||||
"scripts": {
|
|
||||||
"dev": "cross-env PAYLOAD_CONFIG_PATH=src/payload.config.ts nodemon",
|
|
||||||
"build:payload": "cross-env PAYLOAD_CONFIG_PATH=src/payload.config.ts payload build",
|
|
||||||
"build:server": "tsc",
|
|
||||||
"build": "yarn build:payload && yarn build:server",
|
|
||||||
"serve": "cross-env PAYLOAD_CONFIG_PATH=dist/demo/src/payload.config.js NODE_ENV=production node dist/demo/src/server.js",
|
|
||||||
"generate:types": "cross-env PAYLOAD_CONFIG_PATH=src/payload.config.ts payload generate:types",
|
|
||||||
"clean": "rm -rf node_modules/@payloadcms/bundler-vite/node_modules/.vite build dist"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@payloadcms/bundler-vite": "^0.1.4",
|
|
||||||
"@payloadcms/bundler-webpack": "^1.0.5",
|
|
||||||
"@payloadcms/db-mongodb": "^1.0.6",
|
|
||||||
"@payloadcms/richtext-lexical": "^0.1.16",
|
|
||||||
"dotenv": "^8.2.0",
|
|
||||||
"express": "^4.17.1",
|
|
||||||
"payload": "^2.2.1",
|
|
||||||
"stripe": "^10.10.0"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@types/express": "^4.17.9",
|
|
||||||
"cross-env": "^7.0.3",
|
|
||||||
"nodemon": "^2.0.6",
|
|
||||||
"ts-node": "^9.1.1",
|
|
||||||
"typescript": "^4.1.3"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
BIN
packages/plugin-stripe/demo/src/.DS_Store
vendored
BIN
packages/plugin-stripe/demo/src/.DS_Store
vendored
Binary file not shown.
@@ -1,26 +0,0 @@
|
|||||||
import dotenv from 'dotenv'
|
|
||||||
import express from 'express'
|
|
||||||
import payload from 'payload'
|
|
||||||
|
|
||||||
dotenv.config()
|
|
||||||
const app = express()
|
|
||||||
|
|
||||||
// Redirect root to Admin panel
|
|
||||||
app.get('/', (_, res) => {
|
|
||||||
res.redirect('/admin')
|
|
||||||
})
|
|
||||||
|
|
||||||
// Initialize Payload
|
|
||||||
const start = async (): Promise<void> => {
|
|
||||||
await payload.init({
|
|
||||||
secret: process.env.PAYLOAD_SECRET,
|
|
||||||
express: app,
|
|
||||||
onInit: () => {
|
|
||||||
payload.logger.info(`Payload Admin URL: ${payload.getAdminURL()}`)
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
app.listen(3000)
|
|
||||||
}
|
|
||||||
|
|
||||||
start()
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"target": "es5",
|
|
||||||
"lib": ["dom", "dom.iterable", "esnext"],
|
|
||||||
"strict": false,
|
|
||||||
"esModuleInterop": true,
|
|
||||||
"skipLibCheck": true,
|
|
||||||
"outDir": "./dist",
|
|
||||||
"rootDir": "../",
|
|
||||||
"jsx": "react"
|
|
||||||
},
|
|
||||||
"ts-node": {
|
|
||||||
"transpileOnly": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
import type { UIField } from 'payload/dist/fields/config/types'
|
import type { UIField } from 'payload/dist/fields/config/types'
|
||||||
|
|
||||||
import { useFormFields } from 'payload/components/forms'
|
import { useFormFields } from 'payload/components/forms'
|
||||||
import CopyToClipboard from 'payload/dist/admin/components/elements/CopyToClipboard'
|
// TODO: fix this import to work in dev mode within the monorepo in a way that is backwards compatible with 1.x
|
||||||
|
// import CopyToClipboard from 'payload/dist/admin/components/elements/CopyToClipboard'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
|
||||||
export const LinkToDoc: React.FC<
|
export const LinkToDoc: React.FC<
|
||||||
@@ -32,7 +33,7 @@ export const LinkToDoc: React.FC<
|
|||||||
View in Stripe
|
View in Stripe
|
||||||
</span>
|
</span>
|
||||||
{/* @ts-ignore */}
|
{/* @ts-ignore */}
|
||||||
<CopyToClipboard value={href} />
|
{/* <CopyToClipboard value={href} /> */}
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
|
|||||||
@@ -20,5 +20,5 @@
|
|||||||
"src/**/*.spec.tsx"
|
"src/**/*.spec.tsx"
|
||||||
],
|
],
|
||||||
"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.d.ts", "src/**/*.json"],
|
"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.d.ts", "src/**/*.json"],
|
||||||
"references": [{ "path": "../payload" }] // db-mongodb depends on payload
|
"references": [{ "path": "../payload" }]
|
||||||
}
|
}
|
||||||
|
|||||||
5
pnpm-lock.yaml
generated
5
pnpm-lock.yaml
generated
@@ -8834,6 +8834,7 @@ packages:
|
|||||||
which-boxed-primitive: 1.0.2
|
which-boxed-primitive: 1.0.2
|
||||||
which-collection: 1.0.1
|
which-collection: 1.0.1
|
||||||
which-typed-array: 1.1.11
|
which-typed-array: 1.1.11
|
||||||
|
dev: false
|
||||||
|
|
||||||
/deep-equal@2.2.3:
|
/deep-equal@2.2.3:
|
||||||
resolution: {integrity: sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==}
|
resolution: {integrity: sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==}
|
||||||
@@ -14252,7 +14253,7 @@ packages:
|
|||||||
css-minimizer-webpack-plugin: 5.0.1(webpack@5.88.2)
|
css-minimizer-webpack-plugin: 5.0.1(webpack@5.88.2)
|
||||||
dataloader: 2.2.2
|
dataloader: 2.2.2
|
||||||
date-fns: 2.30.0
|
date-fns: 2.30.0
|
||||||
deep-equal: 2.2.2
|
deep-equal: 2.2.3
|
||||||
deepmerge: 4.3.1
|
deepmerge: 4.3.1
|
||||||
dotenv: 8.6.0
|
dotenv: 8.6.0
|
||||||
express: 4.18.2
|
express: 4.18.2
|
||||||
@@ -14341,7 +14342,7 @@ packages:
|
|||||||
uuid: 8.3.2
|
uuid: 8.3.2
|
||||||
webpack: 5.88.2(@swc/core@1.3.78)(webpack-cli@4.10.0)
|
webpack: 5.88.2(@swc/core@1.3.78)(webpack-cli@4.10.0)
|
||||||
webpack-bundle-analyzer: 4.9.1
|
webpack-bundle-analyzer: 4.9.1
|
||||||
webpack-cli: 4.10.0(webpack@5.88.2)
|
webpack-cli: 4.10.0(webpack-bundle-analyzer@4.9.1)(webpack@5.88.2)
|
||||||
webpack-dev-middleware: 6.0.1(webpack@5.88.2)
|
webpack-dev-middleware: 6.0.1(webpack@5.88.2)
|
||||||
webpack-hot-middleware: 2.25.4
|
webpack-hot-middleware: 2.25.4
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
import { CollectionConfig } from 'payload/types'
|
import type { CollectionConfig } from '../../../packages/payload/src/collections/config/types'
|
||||||
import { LinkToDoc } from '../../../src/ui/LinkToDoc'
|
|
||||||
|
|
||||||
const Customers: CollectionConfig = {
|
import { LinkToDoc } from '../../../packages/plugin-stripe/src/ui/LinkToDoc'
|
||||||
slug: 'customers',
|
import { customersSlug } from '../shared'
|
||||||
|
|
||||||
|
export const Customers: CollectionConfig = {
|
||||||
|
slug: customersSlug,
|
||||||
timestamps: true,
|
timestamps: true,
|
||||||
admin: {
|
admin: {
|
||||||
useAsTitle: 'email',
|
useAsTitle: 'email',
|
||||||
@@ -32,7 +34,6 @@ const Customers: CollectionConfig = {
|
|||||||
type: 'ui',
|
type: 'ui',
|
||||||
admin: {
|
admin: {
|
||||||
components: {
|
components: {
|
||||||
// @ts-expect-error
|
|
||||||
Field: (args) =>
|
Field: (args) =>
|
||||||
LinkToDoc({
|
LinkToDoc({
|
||||||
...args,
|
...args,
|
||||||
@@ -109,5 +110,3 @@ const Customers: CollectionConfig = {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Customers
|
|
||||||
@@ -1,7 +1,9 @@
|
|||||||
import { CollectionConfig } from 'payload/types'
|
import type { CollectionConfig } from '../../../packages/payload/src/collections/config/types'
|
||||||
|
|
||||||
const Products: CollectionConfig = {
|
import { productsSlug } from '../shared'
|
||||||
slug: 'products',
|
|
||||||
|
export const Products: CollectionConfig = {
|
||||||
|
slug: productsSlug,
|
||||||
timestamps: true,
|
timestamps: true,
|
||||||
admin: {
|
admin: {
|
||||||
defaultColumns: ['name'],
|
defaultColumns: ['name'],
|
||||||
@@ -35,5 +37,3 @@ const Products: CollectionConfig = {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Products
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { CollectionConfig } from 'payload/types'
|
import type { CollectionConfig } from '../../../packages/payload/src/collections/config/types'
|
||||||
|
|
||||||
const Users: CollectionConfig = {
|
export const Users: CollectionConfig = {
|
||||||
slug: 'users',
|
slug: 'users',
|
||||||
auth: true,
|
auth: true,
|
||||||
admin: {
|
admin: {
|
||||||
@@ -16,5 +16,3 @@ const Users: CollectionConfig = {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Users
|
|
||||||
@@ -1,36 +1,39 @@
|
|||||||
import path from 'path'
|
import stripePlugin from '../../packages/plugin-stripe/src'
|
||||||
import { buildConfig } from 'payload/config'
|
import { buildConfigWithDefaults } from '../buildConfigWithDefaults'
|
||||||
import { viteBundler } from '@payloadcms/bundler-vite'
|
import { devUser } from '../credentials'
|
||||||
// import { webpackBundler } from '@payloadcms/bundler-webpack'
|
import { Customers } from './collections/Customers'
|
||||||
import { mongooseAdapter } from '@payloadcms/db-mongodb'
|
import { Products } from './collections/Products'
|
||||||
import { lexicalEditor } from '@payloadcms/richtext-lexical'
|
import { Users } from './collections/Users'
|
||||||
|
import { seed } from './seed'
|
||||||
import stripePlugin from '../../src'
|
|
||||||
import Customers from './collections/Customers'
|
|
||||||
import Products from './collections/Products'
|
|
||||||
import Users from './collections/Users'
|
|
||||||
import { subscriptionCreatedOrUpdated } from './webhooks/subscriptionCreatedOrUpdated'
|
import { subscriptionCreatedOrUpdated } from './webhooks/subscriptionCreatedOrUpdated'
|
||||||
import { subscriptionDeleted } from './webhooks/subscriptionDeleted'
|
import { subscriptionDeleted } from './webhooks/subscriptionDeleted'
|
||||||
import { syncPriceJSON } from './webhooks/syncPriceJSON'
|
import { syncPriceJSON } from './webhooks/syncPriceJSON'
|
||||||
|
|
||||||
export default buildConfig({
|
process.env.STRIPE_WEBHOOKS_ENDPOINT_SECRET = 'whsec_123'
|
||||||
serverURL: process.env.PAYLOAD_PUBLIC_CMS_URL,
|
process.env.STRIPE_SECRET_KEY = 'sk_test_123'
|
||||||
admin: {
|
|
||||||
user: Users.slug,
|
export default buildConfigWithDefaults({
|
||||||
bundler: viteBundler(),
|
collections: [Users, Products, Customers],
|
||||||
// bundler: webpackBundler(),
|
|
||||||
},
|
|
||||||
collections: [Users, Customers, Products],
|
|
||||||
editor: lexicalEditor({}),
|
|
||||||
localization: {
|
localization: {
|
||||||
locales: ['en', 'es', 'de'],
|
|
||||||
defaultLocale: 'en',
|
defaultLocale: 'en',
|
||||||
fallback: true,
|
fallback: true,
|
||||||
|
locales: ['en', 'es', 'de'],
|
||||||
|
},
|
||||||
|
onInit: async (payload) => {
|
||||||
|
await payload.create({
|
||||||
|
collection: 'users',
|
||||||
|
data: {
|
||||||
|
email: devUser.email,
|
||||||
|
password: devUser.password,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
await seed(payload)
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
stripePlugin({
|
stripePlugin({
|
||||||
stripeSecretKey: process.env.STRIPE_SECRET_KEY,
|
stripeSecretKey: process.env.STRIPE_SECRET_KEY,
|
||||||
isTestKey: process.env.PAYLOAD_PUBLIC_IS_STRIPE_TEST_KEY === 'true',
|
isTestKey: true,
|
||||||
logs: true,
|
logs: true,
|
||||||
sync: [
|
sync: [
|
||||||
{
|
{
|
||||||
@@ -82,10 +85,4 @@ export default buildConfig({
|
|||||||
stripeWebhooksEndpointSecret: process.env.STRIPE_WEBHOOKS_ENDPOINT_SECRET,
|
stripeWebhooksEndpointSecret: process.env.STRIPE_WEBHOOKS_ENDPOINT_SECRET,
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
typescript: {
|
|
||||||
outputFile: path.resolve(__dirname, 'payload-types.ts'),
|
|
||||||
},
|
|
||||||
db: mongooseAdapter({
|
|
||||||
url: process.env.DATABASE_URI,
|
|
||||||
}),
|
|
||||||
})
|
})
|
||||||
32
test/plugin-stripe/int.spec.ts
Normal file
32
test/plugin-stripe/int.spec.ts
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import payload from '../../packages/payload/src'
|
||||||
|
import { initPayloadTest } from '../helpers/configHelpers'
|
||||||
|
|
||||||
|
describe('Stripe Plugin', () => {
|
||||||
|
beforeAll(async () => {
|
||||||
|
await initPayloadTest({ __dirname, init: { local: true } })
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should create products', async () => {
|
||||||
|
const product = await payload.create({
|
||||||
|
collection: 'products',
|
||||||
|
data: {
|
||||||
|
name: 'Test Product',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(product).toHaveProperty('name', 'Test Product')
|
||||||
|
})
|
||||||
|
|
||||||
|
// Test various common API calls like `products.create`, etc.
|
||||||
|
// Send the requests through the Payload->Stripe proxy
|
||||||
|
// Query Stripe directly to ensure the data is as expected
|
||||||
|
it.todo('should open REST API proxy')
|
||||||
|
|
||||||
|
// Test various common webhook events like `product.created`, etc.
|
||||||
|
// These could potentially be mocked
|
||||||
|
it.todo('should handle incoming Stripe webhook events')
|
||||||
|
|
||||||
|
// Test that the data is synced to Stripe automatically without the use of custom hooks/proxy
|
||||||
|
// I.e. the `sync` config option
|
||||||
|
it.todo('should auto-sync data based on config')
|
||||||
|
})
|
||||||
23
test/plugin-stripe/seed/index.ts
Normal file
23
test/plugin-stripe/seed/index.ts
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import type { Payload } from '../../../packages/payload/src'
|
||||||
|
import type { PayloadRequest } from '../../../packages/payload/types'
|
||||||
|
|
||||||
|
export const seed = async (payload: Payload): Promise<boolean> => {
|
||||||
|
payload.logger.info('Seeding data...')
|
||||||
|
const req = {} as PayloadRequest
|
||||||
|
|
||||||
|
try {
|
||||||
|
await payload.create({
|
||||||
|
collection: 'users',
|
||||||
|
data: {
|
||||||
|
email: 'demo@payloadcms.com',
|
||||||
|
password: 'demo',
|
||||||
|
},
|
||||||
|
req,
|
||||||
|
})
|
||||||
|
|
||||||
|
return true
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
5
test/plugin-stripe/shared.ts
Normal file
5
test/plugin-stripe/shared.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
export const pagesSlug = 'pages'
|
||||||
|
|
||||||
|
export const productsSlug = 'products'
|
||||||
|
|
||||||
|
export const customersSlug = 'customers'
|
||||||
@@ -1,7 +1,12 @@
|
|||||||
import { APIError } from 'payload/errors'
|
import { APIError } from '../../../packages/payload/errors'
|
||||||
|
|
||||||
export const subscriptionCreatedOrUpdated = async (args) => {
|
export const subscriptionCreatedOrUpdated = async (args) => {
|
||||||
const { event, payload, stripe, stripeConfig } = args
|
const {
|
||||||
|
event,
|
||||||
|
payload,
|
||||||
|
// stripe,
|
||||||
|
// stripeConfig
|
||||||
|
} = args
|
||||||
|
|
||||||
const customerStripeID = event.data.object.customer
|
const customerStripeID = event.data.object.customer
|
||||||
|
|
||||||
@@ -1,7 +1,12 @@
|
|||||||
import { APIError } from 'payload/errors'
|
import { APIError } from '../../../packages/payload/src/errors'
|
||||||
|
|
||||||
export const subscriptionDeleted = async (args) => {
|
export const subscriptionDeleted = async (args) => {
|
||||||
const { event, payload, stripe, stripeConfig } = args
|
const {
|
||||||
|
event,
|
||||||
|
payload,
|
||||||
|
// stripe,
|
||||||
|
// stripeConfig
|
||||||
|
} = args
|
||||||
|
|
||||||
const customerStripeID = event.data.object.customer
|
const customerStripeID = event.data.object.customer
|
||||||
|
|
||||||
@@ -9,7 +14,10 @@ export const subscriptionDeleted = async (args) => {
|
|||||||
`🪝 A new subscription was deleted in Stripe on customer ID: ${customerStripeID}, deleting from Payload...`,
|
`🪝 A new subscription was deleted in Stripe on customer ID: ${customerStripeID}, deleting from Payload...`,
|
||||||
)
|
)
|
||||||
|
|
||||||
const { id: eventID, plan } = event.data.object
|
const {
|
||||||
|
id: eventID,
|
||||||
|
// plan
|
||||||
|
} = event.data.object
|
||||||
|
|
||||||
// Now look up the customer in Payload
|
// Now look up the customer in Payload
|
||||||
try {
|
try {
|
||||||
@@ -31,17 +31,18 @@
|
|||||||
},
|
},
|
||||||
"composite": true, // Required for references to work
|
"composite": true, // Required for references to work
|
||||||
"references": [
|
"references": [
|
||||||
{ "path": "./packages/db-mongodb" },
|
|
||||||
// if your tsconfig is something different
|
// if your tsconfig is something different
|
||||||
|
{ "path": "./packages/db-mongodb" },
|
||||||
{ "path": "./packages/db-postgres" },
|
{ "path": "./packages/db-postgres" },
|
||||||
{ "path": "./packages/richtext-slate" },
|
{ "path": "./packages/live-preview" },
|
||||||
{ "path": "./packages/richtext-lexical" },
|
{ "path": "./packages/live-preview-react" },
|
||||||
{ "path": "./packages/payload" },
|
{ "path": "./packages/payload" },
|
||||||
{ "path": "./packages/plugin-nested-docs" },
|
|
||||||
{ "path": "./packages/plugin-form-builder" },
|
|
||||||
{ "path": "./packages/plugin-cloud-storage" },
|
{ "path": "./packages/plugin-cloud-storage" },
|
||||||
{ "path": "./packages/plugin-cloud" },
|
{ "path": "./packages/plugin-cloud" },
|
||||||
{ "path": "./packages/live-preview" },
|
{ "path": "./packages/plugin-form-builder" },
|
||||||
{ "path": "./packages/live-preview-react" }
|
{ "path": "./packages/plugin-nested-docs" },
|
||||||
|
{ "path": "./packages/plugin-stripe" },
|
||||||
|
{ "path": "./packages/richtext-slate" },
|
||||||
|
{ "path": "./packages/richtext-lexical" }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user