feat: passing hooks int test suite
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
import type { Where } from 'payload/types'
|
import type { Where } from 'payload/types'
|
||||||
|
import type { ParsedQs } from 'qs'
|
||||||
|
|
||||||
import QueryString from 'qs'
|
import QueryString from 'qs'
|
||||||
|
|
||||||
@@ -22,13 +23,16 @@ type RequestQuery = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function generateQueryString(query: RequestQuery['query']): string {
|
function generateQueryString(query: RequestQuery['query'], params: ParsedQs): string {
|
||||||
|
const { where, limit, page, sort, ...rest } = params || {}
|
||||||
|
const whereFilter = query?.where || where
|
||||||
return QueryString.stringify(
|
return QueryString.stringify(
|
||||||
{
|
{
|
||||||
...(query?.where ? { where: query.where } : {}),
|
...(rest || {}),
|
||||||
limit: query?.limit,
|
...(whereFilter ? { where: whereFilter } : {}),
|
||||||
page: query?.page,
|
limit: query?.limit || limit || undefined,
|
||||||
sort: query?.sort,
|
page: query?.page || page || undefined,
|
||||||
|
sort: query?.sort || sort || undefined,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
addQueryPrefix: true,
|
addQueryPrefix: true,
|
||||||
@@ -61,25 +65,27 @@ export class NextRESTClient {
|
|||||||
this._GRAPHQL_POST = createGraphqlPOST(config)
|
this._GRAPHQL_POST = createGraphqlPOST(config)
|
||||||
}
|
}
|
||||||
|
|
||||||
private generateRequestParts(path: string): {
|
private generateRequestParts(path: ValidPath): {
|
||||||
|
params?: ParsedQs
|
||||||
slug: string[]
|
slug: string[]
|
||||||
url: string
|
url: string
|
||||||
} {
|
} {
|
||||||
const safePath = path.slice(1)
|
const [slugs, params] = path.slice(1).split('?')
|
||||||
const slug = safePath.split('/')
|
const url = `${this.serverURL}${this.config.routes.api}/${slugs}`
|
||||||
const url = `${this.serverURL}${this.config.routes.api}/${safePath}`
|
|
||||||
return {
|
return {
|
||||||
url,
|
url,
|
||||||
slug,
|
slug: slugs.split('/'),
|
||||||
|
params: params ? QueryString.parse(params) : undefined,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async DELETE(path: ValidPath, options: RequestInit & RequestQuery = {}): Promise<Response> {
|
async DELETE(path: ValidPath, options: RequestInit & RequestQuery = {}): Promise<Response> {
|
||||||
const { url, slug } = this.generateRequestParts(path)
|
const { url, slug, params } = this.generateRequestParts(path)
|
||||||
const { query, ...rest } = options || {}
|
const { query, ...rest } = options || {}
|
||||||
const whereQuery = generateQueryString(query)
|
const queryParams = generateQueryString(query, params)
|
||||||
|
|
||||||
const request = new Request(`${url}${whereQuery}`, {
|
const request = new Request(`${url}${queryParams}`, {
|
||||||
...rest,
|
...rest,
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
headers: {
|
headers: {
|
||||||
@@ -94,11 +100,11 @@ export class NextRESTClient {
|
|||||||
path: ValidPath,
|
path: ValidPath,
|
||||||
options: Omit<RequestInit, 'body'> & RequestQuery = {},
|
options: Omit<RequestInit, 'body'> & RequestQuery = {},
|
||||||
): Promise<Response> {
|
): Promise<Response> {
|
||||||
const { url, slug } = this.generateRequestParts(path)
|
const { url, slug, params } = this.generateRequestParts(path)
|
||||||
const { query, ...rest } = options || {}
|
const { query, ...rest } = options || {}
|
||||||
const whereQuery = generateQueryString(query)
|
const queryParams = generateQueryString(query, params)
|
||||||
|
|
||||||
const request = new Request(`${url}${whereQuery}`, {
|
const request = new Request(`${url}${queryParams}`, {
|
||||||
...rest,
|
...rest,
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: new Headers({
|
headers: new Headers({
|
||||||
@@ -125,11 +131,11 @@ export class NextRESTClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async PATCH(path: ValidPath, options: RequestInit & RequestQuery): Promise<Response> {
|
async PATCH(path: ValidPath, options: RequestInit & RequestQuery): Promise<Response> {
|
||||||
const { url, slug } = this.generateRequestParts(path)
|
const { url, slug, params } = this.generateRequestParts(path)
|
||||||
const { query, ...rest } = options
|
const { query, ...rest } = options
|
||||||
const whereQuery = generateQueryString(query)
|
const queryParams = generateQueryString(query, params)
|
||||||
|
|
||||||
const request = new Request(`${url}${whereQuery}`, {
|
const request = new Request(`${url}${queryParams}`, {
|
||||||
...rest,
|
...rest,
|
||||||
method: 'PATCH',
|
method: 'PATCH',
|
||||||
headers: new Headers({
|
headers: new Headers({
|
||||||
@@ -141,9 +147,10 @@ export class NextRESTClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async POST(path: ValidPath, options: RequestInit = {}): Promise<Response> {
|
async POST(path: ValidPath, options: RequestInit = {}): Promise<Response> {
|
||||||
const { url, slug } = this.generateRequestParts(path)
|
const { url, slug, params } = this.generateRequestParts(path)
|
||||||
|
const queryParams = generateQueryString({}, params)
|
||||||
|
|
||||||
const request = new Request(url, {
|
const request = new Request(`${url}${queryParams}`, {
|
||||||
...options,
|
...options,
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: new Headers({
|
headers: new Headers({
|
||||||
|
|||||||
@@ -13,20 +13,20 @@ const ContextHooks: CollectionConfig = {
|
|||||||
},
|
},
|
||||||
hooks: {
|
hooks: {
|
||||||
beforeOperation: [
|
beforeOperation: [
|
||||||
async ({ context, args }) => {
|
({ context, args }) => {
|
||||||
// eslint-disable-next-line prefer-destructuring
|
// eslint-disable-next-line prefer-destructuring
|
||||||
const req: PayloadRequest = args.req
|
const req: PayloadRequest = args.req
|
||||||
|
|
||||||
if (!req.query || !Object.keys(req.query).length) {
|
if (req.searchParams.size === 0) {
|
||||||
return args
|
return args
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.keys(req.query).forEach((key) => {
|
req.searchParams.forEach((value, key) => {
|
||||||
if (key.startsWith('context_')) {
|
if (key.startsWith('context_')) {
|
||||||
// Strip 'context_' from key, add it to context object and remove it from query params
|
// Strip 'context_' from key, add it to context object and remove it from query params
|
||||||
const newKey = key.substring('context_'.length)
|
const newKey = key.substring('context_'.length)
|
||||||
context[newKey] = req.query[key]
|
context[newKey] = value
|
||||||
delete req.query[key]
|
req.searchParams.delete(key)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
|
import type { Payload } from '../../packages/payload/src'
|
||||||
import type { NestedAfterReadHook } from './payload-types'
|
import type { NestedAfterReadHook } from './payload-types'
|
||||||
|
|
||||||
import payload from '../../packages/payload/src'
|
import { getPayload } from '../../packages/payload/src'
|
||||||
import { AuthenticationError } from '../../packages/payload/src/errors'
|
import { AuthenticationError } from '../../packages/payload/src/errors'
|
||||||
import { devUser, regularUser } from '../credentials'
|
import { devUser, regularUser } from '../credentials'
|
||||||
import { initPayloadTest } from '../helpers/configHelpers'
|
import { NextRESTClient } from '../helpers/NextRESTClient'
|
||||||
|
import { startMemoryDB } from '../startMemoryDB'
|
||||||
import { afterOperationSlug } from './collections/AfterOperation'
|
import { afterOperationSlug } from './collections/AfterOperation'
|
||||||
import { chainingHooksSlug } from './collections/ChainingHooks'
|
import { chainingHooksSlug } from './collections/ChainingHooks'
|
||||||
import { contextHooksSlug } from './collections/ContextHooks'
|
import { contextHooksSlug } from './collections/ContextHooks'
|
||||||
@@ -16,15 +18,17 @@ import {
|
|||||||
import { relationsSlug } from './collections/Relations'
|
import { relationsSlug } from './collections/Relations'
|
||||||
import { transformSlug } from './collections/Transform'
|
import { transformSlug } from './collections/Transform'
|
||||||
import { hooksUsersSlug } from './collections/Users'
|
import { hooksUsersSlug } from './collections/Users'
|
||||||
import { HooksConfig } from './config'
|
import configPromise, { HooksConfig } from './config'
|
||||||
import { dataHooksGlobalSlug } from './globals/Data'
|
import { dataHooksGlobalSlug } from './globals/Data'
|
||||||
|
|
||||||
let apiUrl
|
let restClient: NextRESTClient
|
||||||
|
let payload: Payload
|
||||||
|
|
||||||
describe('Hooks', () => {
|
describe('Hooks', () => {
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
const { serverURL } = await initPayloadTest({ __dirname, init: { local: false } })
|
const config = await startMemoryDB(configPromise)
|
||||||
apiUrl = `${serverURL}/api`
|
payload = await getPayload({ config })
|
||||||
|
restClient = new NextRESTClient(payload.config)
|
||||||
})
|
})
|
||||||
|
|
||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
@@ -268,18 +272,17 @@ describe('Hooks', () => {
|
|||||||
context_secretValue: 'data from rest API',
|
context_secretValue: 'data from rest API',
|
||||||
})
|
})
|
||||||
// send context as query params. It will be parsed by the beforeOperation hook
|
// send context as query params. It will be parsed by the beforeOperation hook
|
||||||
const response = await fetch(`${apiUrl}/${contextHooksSlug}?${params.toString()}`, {
|
const { doc } = await restClient
|
||||||
body: JSON.stringify({
|
.POST(`/${contextHooksSlug}?${params.toString()}`, {
|
||||||
value: 'wrongvalue',
|
body: JSON.stringify({
|
||||||
}),
|
value: 'wrongvalue',
|
||||||
method: 'post',
|
}),
|
||||||
})
|
})
|
||||||
|
.then((res) => res.json())
|
||||||
const document = (await response.json()).doc
|
|
||||||
|
|
||||||
const retrievedDoc = await payload.findByID({
|
const retrievedDoc = await payload.findByID({
|
||||||
collection: contextHooksSlug,
|
collection: contextHooksSlug,
|
||||||
id: document.id,
|
id: doc.id,
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(retrievedDoc.value).toEqual('data from rest API')
|
expect(retrievedDoc.value).toEqual('data from rest API')
|
||||||
|
|||||||
Reference in New Issue
Block a user