jameswlane/jest-express

View on GitHub
src/request.ts

Summary

Maintainability
D
3 days
Test Coverage
A
100%
import { parse } from 'url';
import { Express } from './express';

interface IRequestOptions {
  method?:
  | 'GET'
  | 'POST'
  | 'DELETE'
  | 'PATCH'
  | 'PUT'
  | 'HEAD'
  | 'OPTIONS'
  | 'CONNECT';
  headers?: any;
  app?: Express;
}

declare const jest: any;
// https://expressjs.com/en/4x/api.html#req
export class Request {
  // Properties
  public baseUrl: string;

  public body: any;

  public cookies: any;

  public fresh: boolean;

  public headers: any;

  public hostname: string;

  public ip: string;

  public ips: string[];

  public method: string;

  public originalUrl: string;

  public params: any;

  public path: string;

  public protocol: string;

  public query: any;

  public route: any;

  public secure: boolean;

  public signedCookies: any;

  public stale: boolean;

  public subdomains: string[];

  public xhr: boolean;

  // Methods
  public accepts: any;

  public acceptsCharsets: any;

  public acceptsEncodings: any;

  public acceptsLanguages: any;

  public get: any;

  public header: any;

  public is: any;

  public range: any;

  // Application
  public app: Express;

  private defaultUrl: string | undefined;

  private defaultOptions: IRequestOptions | undefined;

  constructor(url?: string | null, options?: IRequestOptions) {
    // Properties
    this.baseUrl = '';
    this.body = '';
    this.cookies = {};
    this.fresh = false;
    this.headers = {};
    this.hostname = '';
    this.ip = '::1';
    this.ips = [];
    this.method = 'GET';
    this.originalUrl = '';
    this.params = {};
    this.path = '';
    this.protocol = 'http';
    this.query = {};
    this.route = {};
    this.secure = false;
    this.signedCookies = {};
    this.stale = false;
    this.subdomains = [];
    this.xhr = false;
    // Methods
    this.accepts = jest.fn();
    this.acceptsCharsets = jest.fn();
    this.acceptsEncodings = jest.fn();
    this.acceptsLanguages = jest.fn();
    this.get = this.header = jest
      .fn()
      .mockImplementation((header: string) => this.headers[header.toLowerCase()]);
    this.is = jest.fn();
    this.range = jest.fn();
    // Application
    this.app = options && options.app ? options.app : new Express();

    if (typeof url === 'string') {
      this.defaultUrl = url;
      this.defaultOptions = options;
      this.setUrl(this.defaultUrl, this.defaultOptions);
    }

    return this;
  }

  public setUrl(url: string, options?: IRequestOptions) {
    const parsedUrl = parse(url, true);

    this.path = parsedUrl.pathname || '/';
    this.hostname = parsedUrl.hostname || '';
    this.originalUrl = this.path + (parsedUrl.search || '');
    this.query = parsedUrl.query;
    this.protocol = parsedUrl.protocol
      ? parsedUrl.protocol.slice(0, parsedUrl.protocol.length - 1)
      : 'http';
    this.secure = parsedUrl.protocol === 'https:';

    const hostnameParts = this.hostname.split('.');
    if (hostnameParts.length > 2) {
      this.subdomains = hostnameParts.slice(0, hostnameParts.length - 2);
    }

    if (options) {
      if (options.headers) {
        const headers: any = {};
        for (const k of Object.keys(options.headers)) {
          const key = k.toLowerCase();
          headers[key] = options.headers[k];
        }

        this.headers = { ...headers };
      }
      if (options.method) {
        this.method = options.method;
      }
    }
  }

  public resetMocked() {
    // Properties
    this.baseUrl = '';
    this.body = '';
    this.cookies = {};
    this.fresh = false;
    this.headers = {};
    this.hostname = '';
    this.ip = '::1';
    this.ips = [];
    this.method = 'GET';
    this.originalUrl = '';
    this.params = {};
    this.path = '';
    this.protocol = 'http';
    this.query = {};
    this.route = {};
    this.secure = false;
    this.signedCookies = {};
    this.stale = false;
    this.subdomains = [];
    this.xhr = false;

    if (typeof this.defaultUrl === 'string') {
      this.setUrl(this.defaultUrl, this.defaultOptions);
    }

    // Methods
    this.accepts.mockReset();
    this.acceptsCharsets.mockReset();
    this.acceptsEncodings.mockReset();
    this.acceptsLanguages.mockReset();
    this.get.mockReset();
    this.is.mockReset();
    this.range.mockReset();
  }

  public setBaseUrl(value: string) {
    this.baseUrl = value;
  }

  public setBody(value: any) {
    this.body = value;
  }

  public setCookies(key: string | { [key: string]: string }, value?: string) {
    if (typeof key === 'string') {
      this.cookies[key] = value;
    } else {
      for (const k of Object.keys(key)) {
        this.cookies[k] = key[k];
      }
    }
  }

  public setFresh(value: boolean) {
    this.fresh = value;
  }

  public setHeaders(key: string | { [key: string]: string }, value?: string) {
    if (typeof key === 'string') {
      this.headers[key.toLowerCase()] = value;
    } else {
      for (const k of Object.keys(key)) {
        this.headers[k.toLowerCase()] = key[k];
      }
    }
  }

  public setHostname(value: string) {
    this.hostname = value;
  }

  public setIp(value: string) {
    this.ip = value;
  }

  public setIps(value: string) {
    this.ips.push(value);
  }

  public setMethod(value: string) {
    this.method = value;
  }

  public setOriginalUrl(value: string) {
    this.originalUrl = value;
  }

  public setParams(key: string | { [key: string]: string }, value?: string) {
    if (typeof key === 'string') {
      this.params[key] = value;
    } else {
      for (const k of Object.keys(key)) {
        this.params[k] = key[k];
      }
    }
  }

  public setPath(value: string) {
    this.path = value;
  }

  public setProtocol(value: string) {
    this.protocol = value;
  }

  public setQuery(key: string | { [key: string]: string }, value?: string) {
    if (typeof key === 'string') {
      this.query[key] = value;
    } else {
      for (const k of Object.keys(key)) {
        this.query[k] = key[k];
      }
    }
  }

  public setRoute(key: string | { [key: string]: string }, value?: string) {
    if (typeof key === 'string') {
      this.route[key] = value;
    } else {
      for (const k of Object.keys(key)) {
        this.route[k] = key[k];
      }
    }
  }

  public setSecure(value: boolean) {
    this.secure = value;
  }

  public setSignedCookies(
    key: string | { [key: string]: string },
    value?: string,
  ) {
    if (typeof key === 'string') {
      this.signedCookies[key] = value;
    } else {
      for (const k of Object.keys(key)) {
        this.signedCookies[k] = key[k];
      }
    }
  }

  public setStale(value: boolean) {
    this.stale = value;
  }

  public setSubdomains(value: string) {
    this.subdomains.push(value);
  }

  public setXhr(value: boolean) {
    this.xhr = value;
  }
}