<commit_before>import uuid from 'uuid';
import { UrlUtils } from 'api/utils/url';
import cloneDeep from 'lodash/cloneDeep';
import Groups from 'api/groups';
import { request } from 'ui/utils/request';

const DEFAULT_RESPONSE = {
  status: 200,
  delay: 500,
  headers: {
    'content-type': 'application/json'
  },
  body: ''
};

// Convert the string to regex (replace ? to \?, / to \/ etc.)
// and replace all '*' with .*
const toRegExp = (value) => {
  const expression = UrlUtils._escapeRegExp(value)
    .replace(/\s/g, '')
    .replace(/\*/g, '.*');

  return new RegExp(`^${expression}$`);
};

export class Mock {

  constructor({ id = uuid.v4(), active = true, method, url, headers, params, response, name, origin, groupId }) {
    Object.assign(this, {
      id,
      active,
      method,
      url,
      headers,
      params,
      response: response || DEFAULT_RESPONSE,
      name,
      origin,
      groupId
    });
  }

  get fullUrl() {
    const isFullUrl      = this.url.indexOf('http://') !== -1 || this.url.indexOf('https://') !== -1;
    const hasOrigin      = !!this.origin;
    const includesOrigin = this.url.indexOf(this.origin) !== -1;

    if (isFullUrl || !hasOrigin || !includesOrigin) {
      return this.url;
    }

    return `${this.origin}/${this.url}`;
  }

  get isActive() {
    if (!this.groupId) {
      return this.active;
    }

    const group = Groups.find({ id: this.groupId }) || {};

    return group.active ? this.active : group.active;
  }

  get requestHash() {
    return [this.method, this.url, this.params].join('|');
  }

  getResponse() {
    return { headers: this.headers, ...this.response };
  }

  update(request) {
    this.response.status  = request.response.status;
    this.response.delay   = request.response.delay;
    this.response.body    = request.response.body;
    this.response.headers = { ...request.response.headers };
    this.active           = request.active;
    this.name             = request.name;
    this.params           = request.params;
    this.url              = request.url;
    this.method           = request.method;
    this.headers          = { ...request.headers };
    this.groupId          = request.groupId;
  }

  updateResponse(response) {
    this.response.status = response.status || this.response.status;
    this.response.delay  = response.delay || this.response.delay;
    this.response.body   = response.body || this.response.body;
  }

  recapture(done) {
    this.disable();

    request({
      method: this.method,
      url: this.url,
      headers: this.headers,
      params: this.params
    }, (response) => {
      this.updateResponse(response);
      this.enable();
      done(this.id);
    });
  }

  rename(newName) {
    this.name = newName;
  }

  toggle() {
    this.active = !this.active;
  }

  enable() {
    this.active = true;
  }

  disable() {
    this.active = false;
  }

  matches(request) {
    const preparedRegex = toRegExp(this.url);

    return request.method === this.method &&
      this.matchParams(request.params) &&
      preparedRegex.test(request.url);
  }

  matchParams(params) {
    if (this.params === params) {
      return true;
    }

    const emptyMockParams    = this.params === undefined || this.params === null || this.params === '';
    const emptyRequestParams = params === undefined || params === null || this.params === '';

    if (emptyMockParams && emptyRequestParams) {
      return true;
    }

    return toRegExp(this.params).test(params);
  }

  export() {
    const mock = cloneDeep(this);

    try {
      mock.params = JSON.parse(mock.params);
    } catch (ex) {
      // failed to parse params, reverting to string
    }

    try {
      mock.response.body = JSON.parse(mock.response.body);
    } catch (ex) {
      // failed to parse body, reverting to string
    }

    return mock;
  }

}
<commit_msg>Fix a bug where some requests appear with "null" string and lowercase method<commit_after>import uuid from 'uuid';
import { UrlUtils } from 'api/utils/url';
import cloneDeep from 'lodash/cloneDeep';
import Groups from 'api/groups';
import { request } from 'ui/utils/request';

const DEFAULT_RESPONSE = {
  status: 200,
  delay: 500,
  headers: {
    'content-type': 'application/json'
  },
  body: ''
};

// Convert the string to regex (replace ? to \?, / to \/ etc.)
// and replace all '*' with .*
const toRegExp = (value) => {
  const expression = UrlUtils._escapeRegExp(value)
    .replace(/\s/g, '')
    .replace(/\*/g, '.*');

  return new RegExp(`^${expression}$`);
};

export class Mock {

  constructor({ id = uuid.v4(), active = true, method, url, headers, params, response, name, origin, groupId }) {
    Object.assign(this, {
      id,
      active,
      method,
      url,
      headers,
      params,
      response: response || DEFAULT_RESPONSE,
      name,
      origin,
      groupId
    });
  }

  get fullUrl() {
    const isFullUrl      = this.url.indexOf('http://') !== -1 || this.url.indexOf('https://') !== -1;
    const hasOrigin      = !!this.origin;
    const includesOrigin = this.url.indexOf(this.origin) !== -1;

    if (isFullUrl || !hasOrigin || !includesOrigin) {
      return this.url;
    }

    return `${this.origin}/${this.url}`;
  }

  get isActive() {
    if (!this.groupId) {
      return this.active;
    }

    const group = Groups.find({ id: this.groupId }) || {};

    return group.active ? this.active : group.active;
  }

  get requestHash() {
    return [this.method, this.url, this.params].join('|');
  }

  getResponse() {
    return { headers: this.headers, ...this.response };
  }

  update(request) {
    this.response.status  = request.response.status;
    this.response.delay   = request.response.delay;
    this.response.body    = request.response.body;
    this.response.headers = { ...request.response.headers };
    this.active           = request.active;
    this.name             = request.name;
    this.params           = request.params;
    this.url              = request.url;
    this.method           = request.method;
    this.headers          = { ...request.headers };
    this.groupId          = request.groupId;
  }

  updateResponse(response) {
    this.response.status = response.status || this.response.status;
    this.response.delay  = response.delay || this.response.delay;
    this.response.body   = response.body || this.response.body;
  }

  recapture(done) {
    this.disable();

    request({
      method: this.method,
      url: this.url,
      headers: this.headers,
      params: this.params
    }, (response) => {
      this.updateResponse(response);
      this.enable();
      done(this.id);
    });
  }

  rename(newName) {
    this.name = newName;
  }

  toggle() {
    this.active = !this.active;
  }

  enable() {
    this.active = true;
  }

  disable() {
    this.active = false;
  }

  matches(request) {
    const preparedRegex = toRegExp(this.url);

    const methodMatches = request.method.toLowerCase() === this.method.toLowerCase();

    return methodMatches &&
      this.matchParams(request.params) &&
      preparedRegex.test(request.url);
  }

  matchParams(params) {
    if (this.params === params) {
      return true;
    }

    const emptyMockParams    = this.params === undefined || this.params === null || this.params === '' || this.params === 'null';
    const emptyRequestParams = params === undefined || params === null || params === '' || params === 'null';

    if (emptyMockParams && emptyRequestParams) {
      return true;
    }

    return toRegExp(this.params).test(params);
  }

  export() {
    const mock = cloneDeep(this);

    try {
      mock.params = JSON.parse(mock.params);
    } catch (ex) {
      // failed to parse params, reverting to string
    }

    try {
      mock.response.body = JSON.parse(mock.response.body);
    } catch (ex) {
      // failed to parse body, reverting to string
    }

    return mock;
  }

}

{'fraction_non_alphanumeric': 0.1533997729279677, 'fraction_numerical': 0.0025230225810521003, 'mean_word_length': 2.399656946826758, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 7, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7112473', 'n_tokens_mistral': 2525, 'n_tokens_neox': 2453, 'n_words': 535}