Request

A RequestRule allows you to write rules about the request bodies in your OpenAPI specification.

new RequestRule({
  name: "prevent request removal",
  rule: (requestAssertions) => {
    requestAssertions.body.removed("not remove request", () => {
      throw new RuleError({
        message: "cannot remove an request",
      });
    });
  },
});

new RequestRule(options)

The following table describes the options object.

propertydescriptionrequiredtype
namethe name of the ruleyesstring
matchesA function used to determine when this Rule should be applied. Return true to indicate this Rule should run.no(request: RequestBody, ruleContext: RuleContext) => boolean
docsLinkA link to the documentation for this ruleset. This will be used to show the user on a rule error. If there is a more specific docsLink (e.g. on a nested Rule), the more specific docsLink will be shown)nostring
ruleA function to define assertions for a specification.yes(requestAssertions: RequestAssertions, ruleContext: RuleContext) => void

matches

matches is invoked with a RequestBody and RuleContext objects. The RequestBodycorresponds to the RequestBody that this rule would run on. The RuleContext object contains details about the location. Return a boolean to indicate whether this rule should be run on the RequestBody provided.

Example:

new RequestRule({
  ...,
  // only matches requests with content type 'application/json' in post operations
  matches: (request, ruleContext) => ruleContext.operation.method === 'post' && request.contentType === 'application/json',
  ...
});

requestAssertions.body

new RequestRule({
  ...,
  rule: (requestAssertions) => {
    // lifecycle rules that are available are added, changed, addedOrChanged, requirement and removed
    requestAssertions.body.added('contain description', (request) => {
      if (!request.value.description) {
        throw new RuleError({
          message: 'requests must contain a description',
        });
      }
    });
  },
});

requestAssertions.body also includes a number of common helper functions. These are invoked by defining a lifecycle trigger, and then the helper function. e.g. requestAssertions.body[lifecycle].helperFunction().

The helper functions that are included are:

  • matches
  • matchesOneOf

All of these helper functions can be inverted by prefixing with .not.

i.e. requestAssertions.body.added.not.matches({ schema: { type: 'array' } })

matches

requestAssertions.body[lifecycle].matches(shape)

Expects the operation to match a shape. The default behavior is to do a partial match.

import { Matchers } from '@useoptic/rulesets-base';
 
new RequestRule({
  ...,
  rule: (requestAssertions) => {
    requestAssertions.body.added.matches({
      description: Matchers.string
    });
  },
});

matchesOneOf

requestAssertions.body[lifecycle].matches(shape)

Expects the operation to match one of an array of shapes. The default behavior is to do a partial match.

import { Matchers } from '@useoptic/rulesets-base';
 
new RequestRule({
  ...,
  rule: (requestAssertions) => {
    requestAssertions.body.added.matches([
      { description: Matchers.string },
      { summary: Matchers.string },
    ]);
  },
});

requestAssertions.property

requestAssertions.property is used to define request body property rules.

requestAssertions.property[lifecycle](assertion)

new RequestRule({
  ...,
  rule: (requestAssertions) => {
    // lifecycle rules that are available are added, changed, addedOrChanged, requirement and removed
    requestAssertions.property.added('contains a type', (property) => {
      if (!property.value.type) {
        throw new RuleError({
          message: 'properties must contain a type',
        });
      }
    });
  },
});

requestAssertions.schema

requestAssertions.schema is used to define rules on any schema in a response body. Schemas can exist on the root request body, as an object field, array item and on polymorphic types (oneOf, anyOf, allOf).

requestAssertions.schema[lifecycle](assertion)

new RequestRule({
  ...,
  rule: (requestAssertions) => {
    // lifecycle rules that are available are added, changed, addedOrChanged, requirement and removed
    requestAssertions.schema.added('contains a type', (schema) => {
      if (!schema.value.flatSchema.type) {
        throw new RuleError({
          message: 'schemas must contain a type',
        });
      }
 
      // schemas also contain the location of where the schema is located
      // Other examples include type === 'oneOf', 'array', etc
      if (schema.location.context.type === 'field' && schema.location.context.required) {
        // On field types, the context also includes required and key
        throw new RuleError({
          message: 'cannot add required fields',
        });
      }
    });
  },
});