From 5f9cd33b5e9ad21bd2efaa69d04ddfbe9578296e Mon Sep 17 00:00:00 2001 From: DevSide Date: Fri, 15 Nov 2024 00:16:09 +0100 Subject: [PATCH] feat: migrate to zod --- packages/core/package.json | 4 +- packages/core/src/configuration.ts | 35 ++-- packages/core/src/fixtures.ts | 191 +++--------------- packages/core/src/index.ts | 4 + packages/core/src/schema.ts | 141 +++++++++++++ packages/core/src/service.ts | 50 +++-- packages/dynamock/package.json | 1 - packages/dynamock/src/createServer.ts | 1 + packages/dynamock/test/integrations.spec.ts | 2 +- packages/puppeteer/src/index.ts | 2 +- .../config/manipulate/delete-all.yml | 36 ++-- .../test-files/config/manipulate/put-all.yml | 54 +++-- .../config/manipulate/put-cookies.yml | 21 +- .../config/manipulate/put-query.yml | 17 +- ...-type.yml => no-matching-cookies-type.yml} | 44 +--- ...-type.yml => no-matching-headers-type.yml} | 44 +--- .../validation/invalid-request-headers.yml | 11 - yarn.lock | 63 +----- 18 files changed, 323 insertions(+), 398 deletions(-) create mode 100644 packages/core/src/schema.ts rename packages/test-cases/test-files/fixtures/matching/cookies/{matching-cookies-type.yml => no-matching-cookies-type.yml} (54%) rename packages/test-cases/test-files/fixtures/matching/headers/{matching-headers-type.yml => no-matching-headers-type.yml} (54%) diff --git a/packages/core/package.json b/packages/core/package.json index 8cb9e59..a51c49d 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -21,13 +21,14 @@ "test": "yarn test:ts", "test:common": "NODE_OPTIONS='--enable-source-maps --experimental-vm-modules' jest", "test:ts": "yarn test:common -config=./test/config/jest.config.js --coverage --passWithNoTests", + "ts": "tsc --noEmit --watch", "coverage:permissions": "chmod -R 777 ./coverage" }, "engines": { "node": ">=20" }, "dependencies": { - "@hapi/joi": "17.1.1" + "zod": "3.23.8" }, "devDependencies": { "@jest/globals": "^29.7.0", @@ -36,7 +37,6 @@ "@semantic-release/github": "^11.0.0", "@semantic-release/npm": "^12.0.1", "@semantic-release/release-notes-generator": "^14.0.1", - "@types/hapi__joi": "^17.1.14", "jest": "^29.7.0", "semantic-release": "^24.1.2", "ts-jest": "^29.2.5", diff --git a/packages/core/src/configuration.ts b/packages/core/src/configuration.ts index fd48dd4..c4e963b 100644 --- a/packages/core/src/configuration.ts +++ b/packages/core/src/configuration.ts @@ -1,27 +1,24 @@ -import Joi from '@hapi/joi' +import { z } from 'zod' -export type ConfigurationObjectType = { - [key: string]: { - [key: string]: string - } -} +const ConfigurationObjectSchema = z.record(z.record(z.string())) -export type ConfigurationType = { - cors: null | '*' - headers: ConfigurationObjectType - query: ConfigurationObjectType - cookies: ConfigurationObjectType -} +const ConfigurationSchema = z + .object({ + cors: z.union([z.literal('*'), z.literal(null)]), + headers: z.record(z.record(z.string())), + query: z.record(z.record(z.string())), + cookies: z.record(z.record(z.string())), + }) + .strict() + +const ConfigurationPartialSchema = ConfigurationSchema.partial() -const schema = Joi.object({ - cors: Joi.alternatives([Joi.string().valid('*'), Joi.object().valid(null)]), - headers: Joi.object(), - query: Joi.object(), - cookies: Joi.object(), -}).required() +export type ConfigurationObjectType = z.infer +export type ConfigurationPartialType = z.infer +export type ConfigurationType = z.infer export function validateConfiguration(unsafeConfiguration: unknown) { - return schema.validate(unsafeConfiguration).error + return ConfigurationPartialSchema.safeParse(unsafeConfiguration) } export function createConfiguration(): ConfigurationType { diff --git a/packages/core/src/fixtures.ts b/packages/core/src/fixtures.ts index a16b061..8b011d2 100644 --- a/packages/core/src/fixtures.ts +++ b/packages/core/src/fixtures.ts @@ -1,76 +1,22 @@ import { URLSearchParams } from 'node:url' import { hash, isObjectEmpty, type NonEmptyArray, sortObjectKeysRecurs } from './utils.js' -// TODO: remove Joi with a lightweight composable validation library -import Joi from '@hapi/joi' import type { ConfigurationType } from './configuration.js' +import type { z } from 'zod' +import { + type FixtureRequestOptionsSchema, + type FixtureRequestSchema, + type FixtureResponseSchema, + FixtureSchema, +} from './schema.js' export type FixtureStorageType = { storage: Map } -export type FixtureRequestOptionsType = null | { - // TODO: test and document this - origin?: { - allowRegex?: boolean - } - path?: { - allowRegex?: boolean - disableEncodeURI?: boolean - } - method?: { - allowRegex?: boolean - } - headers?: { - strict?: boolean - allowRegex?: boolean - } - cookies?: { - strict?: boolean - allowRegex?: boolean - } - query?: { - strict?: boolean - allowRegex?: boolean - } - body?: { - strict?: boolean - allowRegex?: boolean - } -} - -export type FixtureRequestType = { - origin: string - path: string - method: string - headers?: null | { [key: string]: string } | ({ [key: string]: string } | string)[] - cookies?: null | { [key: string]: string } | ({ [key: string]: string } | string)[] - query?: null | { [key: string]: string } | ({ [key: string]: string } | string)[] - body?: null | { [key: string]: unknown } - options?: FixtureRequestOptionsType -} - -export type FixtureResponseType = { - status?: number - headers?: null | { [key: string]: string } | ({ [key: string]: string } | string)[] - cookies?: null | { [key: string]: string } | ({ [key: string]: string } | string)[] - query?: null | { [key: string]: string } | ({ [key: string]: string } | string)[] - body?: null | { [key: string]: unknown } - filepath?: string - options?: null | { - delay?: number - lifetime?: number - } -} - -export type FixtureType = - | { - request: FixtureRequestType - response: FixtureResponseType - } - | { - request: FixtureRequestType - responses: NonEmptyArray - } +export type FixtureRequestOptionsType = null | z.infer +export type FixtureRequestType = z.infer +export type FixtureResponseType = z.infer +export type FixtureType = z.infer export type NormalizedFixtureRequestType = { origin: string @@ -107,101 +53,30 @@ export function createFixtureStorage() { } } -export function validateFixture( - unsafeFixture: unknown, - configuration: ConfigurationType, -): [null, string] | [FixtureType, string] { - const schemaProperty = Joi.alternatives([ - Joi.array().items( - Joi.custom((value, helpers) => { - const path = helpers.state.path - const property = path?.[path.length - 2] - - if (property === 'headers' || property === 'query' || property === 'cookies') { - if (!configuration[property]?.[value]) { - throw new Error(`${value} not found in configuration`) - } - } - - return value - }), - Joi.object(), - ), - Joi.object(), - ]) - - const optionsStrictOrAllowRegex = Joi.object({ - strict: Joi.bool(), - allowRegex: Joi.bool(), - }).invalid({ strict: true, allowRegex: true }) - - const requestSchema = Joi.object({ - body: Joi.any(), - origin: Joi.string().required(), - path: Joi.string().required(), - method: Joi.alternatives([ - Joi.string().regex(/^(head|delete|put|post|get|options|patch|\*)$/i), - Joi.custom((value, helpers) => { - const options = helpers.state.ancestors[0].options || {} - const allowMethodRegex = options.method?.allowRegex - - if (!allowMethodRegex) { - throw new Error(`Method ${value} is not a valid method`) - } +export function validateFixture(unsafeFixture: unknown, configuration: ConfigurationType) { + const refineArrayWithConfiguration = ( + property: 'headers' | 'query' | 'cookies', + ): [(data: FixtureType) => boolean | true, { message: string }] => [ + (data: FixtureType) => { + const propertyValue = data.request[property] - if (typeof value !== 'string') { - return helpers.error('string.invalid') - } + if (Array.isArray(propertyValue)) { + return propertyValue.every((value) => + typeof value === 'string' ? configuration[property][value] !== undefined : true, + ) + } - return value - }), - ]).required(), - headers: schemaProperty, - cookies: schemaProperty, - query: schemaProperty, - options: Joi.object({ - path: Joi.object({ - allowRegex: Joi.bool(), - disableEncodeURI: Joi.bool(), - }).invalid({ allowRegex: true, disableEncodeURI: true }), - method: Joi.object({ - allowRegex: Joi.bool(), - }), - headers: optionsStrictOrAllowRegex, - cookies: optionsStrictOrAllowRegex, - query: optionsStrictOrAllowRegex, - body: optionsStrictOrAllowRegex, - }), - }) - - const responseSchema = Joi.object({ - status: Joi.number().integer().min(200).max(600), - body: Joi.any(), - filepath: Joi.string(), - headers: schemaProperty, - cookies: schemaProperty, - options: Joi.object({ - delay: Joi.number().integer().min(0), - lifetime: Joi.number().integer().min(0), - }), - }).oxor('body', 'filepath') - - const schema = Joi.object({ - request: requestSchema.required(), - response: responseSchema, - responses: Joi.array().items(responseSchema), - }) - .or('response', 'responses') - .required() - - const error = schema.validate(unsafeFixture).error - - if (error) { - return [null, error.message] - } + return true + }, + { + message: `request.${property} contains a value not in the configuration`, + }, + ] - // Use "as" temporarily until new validation lib like Zod - return [unsafeFixture as FixtureType, ''] + return FixtureSchema.refine(...refineArrayWithConfiguration('headers')) + .refine(...refineArrayWithConfiguration('query')) + .refine(...refineArrayWithConfiguration('cookies')) + .safeParse(unsafeFixture) } function normalizeArrayMatcher( @@ -329,7 +204,7 @@ function normalizeFixture(fixture: FixtureType, configuration: ConfigurationType } } -function createFixtureId(fixture: FixtureType) { +function createFixtureId(fixture: NormalizedFixtureType) { return hash(JSON.stringify(fixture.request)) } diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index fd7d0e3..40ba74f 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -3,3 +3,7 @@ export * from './response.js' export * from './service.js' export * from './fixtures.js' export * from './configuration.js' +export { FixtureResponseSchema } from './schema.js' +export { FixtureRequestSchema } from './schema.js' +export { RecordOrArrayWithConfigurationSchema } from './schema.js' +export { FixtureRequestOptionsSchema } from './schema.js' diff --git a/packages/core/src/schema.ts b/packages/core/src/schema.ts new file mode 100644 index 0000000..7427ef1 --- /dev/null +++ b/packages/core/src/schema.ts @@ -0,0 +1,141 @@ +import { z } from 'zod' + +export const FixtureRequestOptionsSchema = z + .object({ + origin: z + .object({ + allowRegex: z.boolean(), + }) + .strict() + .partial(), + path: z + .object({ + allowRegex: z.boolean(), + disableEncodeURI: z.boolean(), + }) + .strict() + .partial() + .refine((value) => !(value.allowRegex === true && value.disableEncodeURI === true), { + message: 'Cannot use options.path.allowRegex and options.path.disableEncodeURI together', + }), + method: z + .object({ + allowRegex: z.boolean(), + }) + .strict() + .partial(), + headers: z + .object({ + strict: z.boolean(), + allowRegex: z.boolean(), + }) + .strict() + .partial() + .refine((value) => !(value.strict === true && value.allowRegex === true), { + message: 'Cannot use options.headers.strict and options.headers.allowRegex together', + }), + cookies: z + .object({ + strict: z.boolean(), + allowRegex: z.boolean(), + }) + .strict() + .partial() + .refine((value) => !(value.strict === true && value.allowRegex === true), { + message: 'Cannot use options.cookies.strict and options.cookies.allowRegex together', + }), + query: z + .object({ + strict: z.boolean(), + allowRegex: z.boolean(), + }) + .strict() + .partial() + .refine((value) => !(value.strict === true && value.allowRegex === true), { + message: 'Cannot use options.query.strict and options.query.allowRegex together', + }), + body: z + .object({ + strict: z.boolean(), + allowRegex: z.boolean(), + }) + .strict() + .partial() + .refine((value) => !(value.strict === true && value.allowRegex === true), { + message: 'Cannot use options.body.strict and options.body.allowRegex together', + }), + }) + .partial() + +export const RecordOrArrayWithConfigurationSchema = z.union([ + z.record(z.string()), + z.array(z.union([z.string(), z.record(z.string())])), +]) + +export const FixtureRequestSchema = z + .object({ + origin: z.string(), + path: z.union([z.literal('*'), z.string().startsWith('/')]), + method: z.string(), + headers: RecordOrArrayWithConfigurationSchema.nullish(), + cookies: RecordOrArrayWithConfigurationSchema.nullish(), + query: RecordOrArrayWithConfigurationSchema.nullish(), + body: z.unknown(), + options: FixtureRequestOptionsSchema.nullish(), + }) + .strict() + .partial({ + headers: true, + cookies: true, + query: true, + body: true, + options: true, + }) + .refine( + (data) => data.options?.method?.allowRegex || /^(head|delete|put|post|get|options|patch|\*)$/i.test(data.method), + { + message: 'Method not allowed, expecting /^(head|delete|put|post|get|options|patch|\\*)$/i', + }, + ) + +export const FixtureResponseSchema = z + .object({ + status: z.number().min(200).max(600), + headers: RecordOrArrayWithConfigurationSchema.nullish(), + cookies: RecordOrArrayWithConfigurationSchema.nullish(), + query: RecordOrArrayWithConfigurationSchema.nullish(), + body: z.unknown(), + filepath: z.string(), + options: z + .object({ + delay: z.number().nonnegative(), + lifetime: z.number().nonnegative(), + }) + .strict() + .partial() + .nullish(), + }) + .strict() + .partial({ + status: true, + headers: true, + cookies: true, + query: true, + body: true, + filepath: true, + options: true, + }) + .refine((data) => !(data.body && data.filepath), { + message: 'Cannot use both response.body and response.filepath', + }) + +export const FixtureSchema = z.union([ + z.object({ + request: FixtureRequestSchema, + response: FixtureResponseSchema, + }), + z.object({ + request: FixtureRequestSchema, + responses: z.array(FixtureResponseSchema).nonempty(), + }), +]) diff --git a/packages/core/src/service.ts b/packages/core/src/service.ts index 3094043..5a56e5a 100644 --- a/packages/core/src/service.ts +++ b/packages/core/src/service.ts @@ -8,6 +8,7 @@ import { validateFixture, } from './fixtures.js' import { + ConfigurationPartialType, type ConfigurationType, createConfiguration, updateConfiguration, @@ -16,9 +17,20 @@ import { import { REQUEST_PROPERTIES, requestPropertyMatch } from './properties.js' import type { CoreRequest } from './request.js' import type { CoreResponse } from './response.js' - -export function createServiceError(status: number, message: string): [number, { message: string }] { - return [status, { message: `[FIXTURE SERVER ERROR ${status}]: ${message}` }] +import type { ZodError } from 'zod' + +export function createServiceError( + status: number, + message: string, + error: null | ZodError = null, +): [number, { message: string; error: null | ZodError }] { + return [ + status, + { + message: `[FIXTURE SERVER ERROR ${status}]: ${message}`, + error, + }, + ] } export type ServiceType = { @@ -44,15 +56,15 @@ export function getServiceConfiguration({ configuration }: ServiceType): [number export function updateServiceConfiguration( { configuration }: ServiceType, - data: Partial, + data: unknown, ): [number, ConfigurationType | { message: string }] { - const error = validateConfiguration(data) + const validation = validateConfiguration(data) - if (error) { - return createServiceError(400, error.message) + if (!validation.success) { + return createServiceError(400, 'Configuration validation failed', validation.error) } - const { cors, headers, query, cookies } = data + const { cors, headers, query, cookies } = validation.data updateConfiguration(configuration, cors, headers, query, cookies) return [200, configuration] @@ -68,13 +80,13 @@ export function createServiceFixture( { configuration, fixtureStorage }: ServiceType, unsafeFixture: unknown, ): [number, object] { - const [fixture, validationError] = validateFixture(unsafeFixture, configuration) + const validation = validateFixture(unsafeFixture, configuration) - if (!fixture) { - return createServiceError(400, validationError) + if (!validation.success) { + return createServiceError(400, 'Fixture validation failed', validation.error) } - const { conflictError, fixtureId } = registerFixture(fixtureStorage, fixture, configuration) + const { conflictError, fixtureId } = registerFixture(fixtureStorage, validation.data, configuration) if (conflictError) { return createServiceError(409, conflictError) @@ -95,15 +107,15 @@ export function createServiceFixtures( } for (const unsafeFixture of unsafeFixtures) { - const [fixture, validationError] = validateFixture(unsafeFixture, configuration) + const validation = validateFixture(unsafeFixture, configuration) - if (!fixture) { + if (!validation.success) { cleanUpOnError() - return createServiceError(400, validationError) + return createServiceError(400, 'Fixture validation failed', validation.error) } - const { conflictError, fixtureId } = registerFixture(fixtureStorage, fixture, configuration) + const { conflictError, fixtureId } = registerFixture(fixtureStorage, validation.data, configuration) if (conflictError) { cleanUpOnError() @@ -178,7 +190,7 @@ export function matchServiceRequestAgainstFixtures( const options = response.options || {} const send = () => { - const corResponse = { + const coreResponse = { status: response.status || 200, // TODO not here headers: response.headers ?? {}, cookies: response.cookies ?? {}, @@ -188,10 +200,10 @@ export function matchServiceRequestAgainstFixtures( } if (service.configuration.cors === '*') { - Object.assign(corResponse.headers, corsAllowAllHeaders) + Object.assign(coreResponse.headers, corsAllowAllHeaders) } - end(corResponse) + end(coreResponse) } // The fixture has been or will be consumed diff --git a/packages/dynamock/package.json b/packages/dynamock/package.json index 6135746..46e321c 100644 --- a/packages/dynamock/package.json +++ b/packages/dynamock/package.json @@ -42,7 +42,6 @@ "@semantic-release/release-notes-generator": "^14.0.1", "@types/cookie-parser": "^1.4.7", "@types/express": "^5.0.0", - "@types/hapi__joi": "^17.1.14", "@types/node": "^22.7.7", "@types/supertest": "^6.0.2", "jest": "^29.7.0", diff --git a/packages/dynamock/src/createServer.ts b/packages/dynamock/src/createServer.ts index d92502d..d24546c 100644 --- a/packages/dynamock/src/createServer.ts +++ b/packages/dynamock/src/createServer.ts @@ -33,6 +33,7 @@ export function createServer() { req.body.request.origin = `${req.protocol}://${req.get('host')}` } const [status, data] = createServiceFixture(service, req.body) + console.log(JSON.stringify(data, null, 2)) res.status(status).send(data) }) diff --git a/packages/dynamock/test/integrations.spec.ts b/packages/dynamock/test/integrations.spec.ts index 615132f..ae6ba23 100644 --- a/packages/dynamock/test/integrations.spec.ts +++ b/packages/dynamock/test/integrations.spec.ts @@ -132,7 +132,7 @@ describe('integrations.js', () => { }) describe('matching path', () => { - test.each([ + test.only.each([ ['/ a', null, '/ a', true], ['/ a', null, '/%20a', true], ['/%20a', null, '/ a', false], diff --git a/packages/puppeteer/src/index.ts b/packages/puppeteer/src/index.ts index a3f8318..b9429b2 100644 --- a/packages/puppeteer/src/index.ts +++ b/packages/puppeteer/src/index.ts @@ -16,7 +16,7 @@ import { updateServiceConfiguration, } from '@dynamock/core' import { URLSearchParams } from 'node:url' -import type { ConfigurationType } from '@dynamock/core/dist/configuration.js' +import type { ConfigurationType } from '@dynamock/core' import { URL } from 'node:url' function mapToCoreRequest(request: HTTPRequest): CoreRequest { diff --git a/packages/test-cases/test-files/config/manipulate/delete-all.yml b/packages/test-cases/test-files/config/manipulate/delete-all.yml index 61a8553..c49cd1b 100644 --- a/packages/test-cases/test-files/config/manipulate/delete-all.yml +++ b/packages/test-cases/test-files/config/manipulate/delete-all.yml @@ -3,27 +3,39 @@ data: cors: "*" headers: - hfoo: "hfoo" - hbar: "hbar" + hfoo: + hfoo: "hfoo" + hbar: + hbar: "hbar" query: - qfoo: "qfoo" - qbar: "qbar" + qfoo: + qfoo: "qfoo" + qbar: + qbar: "qbar" cookies: - cfoo: "cfoo" - cbar: "cbar" + cfoo: + cfoo: "cfoo" + cbar: + cbar: "cbar" expectation: status: 200 bodyJSON: cors: "*" headers: - hfoo: "hfoo" - hbar: "hbar" + hfoo: + hfoo: "hfoo" + hbar: + hbar: "hbar" query: - qfoo: "qfoo" - qbar: "qbar" + qfoo: + qfoo: "qfoo" + qbar: + qbar: "qbar" cookies: - cfoo: "cfoo" - cbar: "cbar" + cfoo: + cfoo: "cfoo" + cbar: + cbar: "cbar" - action: name: delete_config expectation: diff --git a/packages/test-cases/test-files/config/manipulate/put-all.yml b/packages/test-cases/test-files/config/manipulate/put-all.yml index efb197d..6ee98a2 100644 --- a/packages/test-cases/test-files/config/manipulate/put-all.yml +++ b/packages/test-cases/test-files/config/manipulate/put-all.yml @@ -3,27 +3,39 @@ data: cors: "*" headers: - hfoo: "hfoo" - hbar: "hbar" + hfoo: + hfoo: "hfoo" + hbar: + hbar: "hbar" query: - qfoo: "qfoo" - qbar: "qbar" + qfoo: + qfoo: "qfoo" + qbar: + qbar: "qbar" cookies: - cfoo: "cfoo" - cbar: "cbar" + cfoo: + cfoo: "cfoo" + cbar: + cbar: "cbar" expectation: status: 200 bodyJSON: cors: "*" headers: - hfoo: "hfoo" - hbar: "hbar" + hfoo: + hfoo: "hfoo" + hbar: + hbar: "hbar" query: - qfoo: "qfoo" - qbar: "qbar" + qfoo: + qfoo: "qfoo" + qbar: + qbar: "qbar" cookies: - cfoo: "cfoo" - cbar: "cbar" + cfoo: + cfoo: "cfoo" + cbar: + cbar: "cbar" - action: name: get_config expectation: @@ -31,11 +43,17 @@ bodyJSON: cors: "*" headers: - hfoo: "hfoo" - hbar: "hbar" + hfoo: + hfoo: "hfoo" + hbar: + hbar: "hbar" query: - qfoo: "qfoo" - qbar: "qbar" + qfoo: + qfoo: "qfoo" + qbar: + qbar: "qbar" cookies: - cfoo: "cfoo" - cbar: "cbar" + cfoo: + cfoo: "cfoo" + cbar: + cbar: "cbar" diff --git a/packages/test-cases/test-files/config/manipulate/put-cookies.yml b/packages/test-cases/test-files/config/manipulate/put-cookies.yml index 3aa601d..d3095c6 100644 --- a/packages/test-cases/test-files/config/manipulate/put-cookies.yml +++ b/packages/test-cases/test-files/config/manipulate/put-cookies.yml @@ -2,7 +2,8 @@ name: put_config data: cookies: - jwt: "jwt" + jwt: + jwt: "jwt" expectation: status: 200 bodyJSON: @@ -10,13 +11,16 @@ headers: {} query: {} cookies: - jwt: "jwt" + jwt: + jwt: "jwt" - action: name: put_config data: cookies: - jwt2: "jwt2" - jwt3: "jwt3" + jwt2: + jwt2: "jwt2" + jwt3: + jwt3: "jwt3" expectation: status: 200 bodyJSON: @@ -24,6 +28,9 @@ headers: {} query: {} cookies: - jwt: "jwt" - jwt2: "jwt2" - jwt3: "jwt3" + jwt: + jwt: "jwt" + jwt2: + jwt2: "jwt2" + jwt3: + jwt3: "jwt3" diff --git a/packages/test-cases/test-files/config/manipulate/put-query.yml b/packages/test-cases/test-files/config/manipulate/put-query.yml index 5ee37d0..6f4f212 100644 --- a/packages/test-cases/test-files/config/manipulate/put-query.yml +++ b/packages/test-cases/test-files/config/manipulate/put-query.yml @@ -3,29 +3,32 @@ data: cors: null query: - foo: "foo" + foo: + foo: "foo" expectation: status: 200 bodyJSON: cors: null headers: { } query: - foo: "foo" + foo: + foo: "foo" cookies: { } - action: name: put_config data: cors: null query: - bar: "bar" - bar2: "bar2" + bar: + bar: "bar" expectation: status: 200 bodyJSON: cors: null headers: { } query: - foo: "foo" - bar: "bar" - bar2: "bar2" + foo: + foo: "foo" + bar: + bar: "bar" cookies: { } diff --git a/packages/test-cases/test-files/fixtures/matching/cookies/matching-cookies-type.yml b/packages/test-cases/test-files/fixtures/matching/cookies/no-matching-cookies-type.yml similarity index 54% rename from packages/test-cases/test-files/fixtures/matching/cookies/matching-cookies-type.yml rename to packages/test-cases/test-files/fixtures/matching/cookies/no-matching-cookies-type.yml index acf422e..5747b76 100644 --- a/packages/test-cases/test-files/fixtures/matching/cookies/matching-cookies-type.yml +++ b/packages/test-cases/test-files/fixtures/matching/cookies/no-matching-cookies-type.yml @@ -9,16 +9,7 @@ response: status: 200 expectation: - status: 201 -- action: - name: test_fixture - data: - path: / - method: GET - cookies: - a: "1" - expectation: - status: 200 + status: 400 - action: name: post_fixture data: @@ -30,16 +21,7 @@ response: status: 200 expectation: - status: 201 -- action: - name: test_fixture - data: - path: / - method: GET - cookies: - a: "[]" - expectation: - status: 200 + status: 400 - action: name: post_fixture data: @@ -52,16 +34,7 @@ response: status: 200 expectation: - status: 201 -- action: - name: test_fixture - data: - path: / - method: GET - cookies: - a: '{"b":"b"}' - expectation: - status: 200 + status: 400 - action: name: post_fixture data: @@ -73,13 +46,4 @@ response: status: 200 expectation: - status: 201 -- action: - name: test_fixture - data: - path: / - method: GET - cookies: - a: 'null' - expectation: - status: 200 \ No newline at end of file + status: 400 diff --git a/packages/test-cases/test-files/fixtures/matching/headers/matching-headers-type.yml b/packages/test-cases/test-files/fixtures/matching/headers/no-matching-headers-type.yml similarity index 54% rename from packages/test-cases/test-files/fixtures/matching/headers/matching-headers-type.yml rename to packages/test-cases/test-files/fixtures/matching/headers/no-matching-headers-type.yml index 59125e3..1935fad 100644 --- a/packages/test-cases/test-files/fixtures/matching/headers/matching-headers-type.yml +++ b/packages/test-cases/test-files/fixtures/matching/headers/no-matching-headers-type.yml @@ -9,16 +9,7 @@ response: status: 200 expectation: - status: 201 -- action: - name: test_fixture - data: - path: / - method: GET - headers: - a: "1" - expectation: - status: 200 + status: 400 - action: name: post_fixture data: @@ -30,16 +21,7 @@ response: status: 200 expectation: - status: 201 -- action: - name: test_fixture - data: - path: / - method: GET - headers: - a: "[]" - expectation: - status: 200 + status: 400 - action: name: post_fixture data: @@ -52,16 +34,7 @@ response: status: 200 expectation: - status: 201 -- action: - name: test_fixture - data: - path: / - method: GET - headers: - a: '{"b":"b"}' - expectation: - status: 200 + status: 400 - action: name: post_fixture data: @@ -73,13 +46,4 @@ response: status: 200 expectation: - status: 201 -- action: - name: test_fixture - data: - path: / - method: GET - headers: - a: 'null' - expectation: - status: 200 \ No newline at end of file + status: 400 diff --git a/packages/test-cases/test-files/fixtures/validation/invalid-request-headers.yml b/packages/test-cases/test-files/fixtures/validation/invalid-request-headers.yml index 504baef..ea3a6aa 100644 --- a/packages/test-cases/test-files/fixtures/validation/invalid-request-headers.yml +++ b/packages/test-cases/test-files/fixtures/validation/invalid-request-headers.yml @@ -1,14 +1,3 @@ -- action: - name: post_fixture - data: - request: - path: / - method: post - headers: null - response: - status: 200 - expectation: - status: 400 - action: name: post_fixture data: diff --git a/yarn.lock b/yarn.lock index a3d3d73..1ac497b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -821,18 +821,17 @@ __metadata: version: 0.0.0-use.local resolution: "@dynamock/core@workspace:packages/core" dependencies: - "@hapi/joi": "npm:17.1.1" "@jest/globals": "npm:^29.7.0" "@semantic-release/commit-analyzer": "npm:^13.0.0" "@semantic-release/git": "npm:^10.0.1" "@semantic-release/github": "npm:^11.0.0" "@semantic-release/npm": "npm:^12.0.1" "@semantic-release/release-notes-generator": "npm:^14.0.1" - "@types/hapi__joi": "npm:^17.1.14" jest: "npm:^29.7.0" semantic-release: "npm:^24.1.2" ts-jest: "npm:^29.2.5" typescript: "npm:^5.6.3" + zod: "npm:3.23.8" languageName: unknown linkType: soft @@ -880,58 +879,6 @@ __metadata: languageName: unknown linkType: soft -"@hapi/address@npm:^4.0.1": - version: 4.1.0 - resolution: "@hapi/address@npm:4.1.0" - dependencies: - "@hapi/hoek": "npm:^9.0.0" - checksum: 10c0/6f111f57d9ff72bab8f0a356cdc95f3a5561a347fedc5c2d398906a3754273db4f83e6f92f5d20759c95077f52d01837175a9128b705aef98101f2d34cabe3ac - languageName: node - linkType: hard - -"@hapi/formula@npm:^2.0.0": - version: 2.0.0 - resolution: "@hapi/formula@npm:2.0.0" - checksum: 10c0/93fd1768da51043e49e008a1556c68e9bbf19f6be4823a7c04ed982afaea8f7079f1d4a5452620fe6124976ea0867a6f42e69579fc74f9b9f3dac6bdcc1fc969 - languageName: node - linkType: hard - -"@hapi/hoek@npm:^9.0.0": - version: 9.2.0 - resolution: "@hapi/hoek@npm:9.2.0" - checksum: 10c0/5185e683938a564cd4a7f47222c98e7f8aaa7fa2a6291735f688c1ab6f6aff4186bfc2bb673bdccdd8dfba412bfdaad6567b22c877f6aae1069030a45377799c - languageName: node - linkType: hard - -"@hapi/joi@npm:17.1.1": - version: 17.1.1 - resolution: "@hapi/joi@npm:17.1.1" - dependencies: - "@hapi/address": "npm:^4.0.1" - "@hapi/formula": "npm:^2.0.0" - "@hapi/hoek": "npm:^9.0.0" - "@hapi/pinpoint": "npm:^2.0.0" - "@hapi/topo": "npm:^5.0.0" - checksum: 10c0/0c9fc1e8d26909b0bd1458728d10071170c5112980d455b865fca17964f65befe8b4c30a3d362d423ec60be77afd2d811d2e40a028d3b099adaba80b960db297 - languageName: node - linkType: hard - -"@hapi/pinpoint@npm:^2.0.0": - version: 2.0.0 - resolution: "@hapi/pinpoint@npm:2.0.0" - checksum: 10c0/7abd089408304b06b42ac476684d6240265ef4d31a24ad215f86af67a1a71033a3c540b85fcde7d18c994ceef4d15ca20fb9271cd7d19ab826d2a3defe705bb8 - languageName: node - linkType: hard - -"@hapi/topo@npm:^5.0.0": - version: 5.1.0 - resolution: "@hapi/topo@npm:5.1.0" - dependencies: - "@hapi/hoek": "npm:^9.0.0" - checksum: 10c0/b16b06d9357947149e032bdf10151eb71aea8057c79c4046bf32393cb89d0d0f7ca501c40c0f7534a5ceca078de0700d2257ac855c15e59fe4e00bba2f25c86f - languageName: node - linkType: hard - "@isaacs/cliui@npm:^8.0.2": version: 8.0.2 resolution: "@isaacs/cliui@npm:8.0.2" @@ -2128,13 +2075,6 @@ __metadata: languageName: node linkType: hard -"@types/hapi__joi@npm:^17.1.14": - version: 17.1.14 - resolution: "@types/hapi__joi@npm:17.1.14" - checksum: 10c0/f9324de0c9ac37097b5bddc997402e299b7a9ab098a27c22f808d363c8218f94180023117b0b99fe187bffa1f6e473744b7417054a3737b3360035c20274d792 - languageName: node - linkType: hard - "@types/http-errors@npm:*": version: 2.0.4 resolution: "@types/http-errors@npm:2.0.4" @@ -3621,7 +3561,6 @@ __metadata: "@semantic-release/release-notes-generator": "npm:^14.0.1" "@types/cookie-parser": "npm:^1.4.7" "@types/express": "npm:^5.0.0" - "@types/hapi__joi": "npm:^17.1.14" "@types/node": "npm:^22.7.7" "@types/supertest": "npm:^6.0.2" cookie-parser: "npm:1.4.7"