All files conditions.ts

98.63% Statements 72/73
96.1% Branches 74/77
100% Functions 3/3
98.61% Lines 71/72

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111      6x   6x 929x 917x     24x     6x         745x 745x   745x 657x 88x 2x 86x   8x     8x 8x   8x     78x           8x   8x 4x 4x 4x   70x   40x   40x 3x 37x 3x 34x   34x 3x 31x 2x 29x 2x 27x 2x 25x 3x 22x 2x 20x 2x 18x 10x 10x 8x 8x 8x   30x   12x   12x 2x 10x 4x 6x 2x 4x 4x   18x 6x 12x 6x 6x   4x   4x 2x 2x 2x       2x    
import type { Context, PlainCondition, AttributeValue } from "@featurevisor/types";
 
import { GetRegex } from "./datafileReader";
import { compareVersions } from "./compareVersions";
 
export function getValueFromContext(obj, path): AttributeValue {
  if (path.indexOf(".") === -1) {
    return obj[path];
  }
 
  return path.split(".").reduce((o, i) => (o ? o[i] : undefined), obj);
}
 
export function conditionIsMatched(
  condition: PlainCondition,
  context: Context,
  getRegex: GetRegex,
): boolean {
  const { attribute, operator, value, regexFlags } = condition;
  const contextValueFromPath = getValueFromContext(context, attribute) as AttributeValue;
 
  if (operator === "equals") {
    return contextValueFromPath === value;
  } else if (operator === "notEquals") {
    return contextValueFromPath !== value;
  } else if (operator === "before" || operator === "after") {
    // date comparisons
    const valueInContext = contextValueFromPath as string | Date;
 
    const dateInContext =
      valueInContext instanceof Date ? valueInContext : new Date(valueInContext);
    const dateInCondition = value instanceof Date ? value : new Date(value as string);
 
    return operator === "before"
      ? dateInContext < dateInCondition
      : dateInContext > dateInCondition;
  } else if (
    Array.isArray(value) &&
    (["string", "number"].indexOf(typeof contextValueFromPath) !== -1 ||
      contextValueFromPath === null)
  ) {
    // in / notIn (where condition value is an array)
    const valueInContext = contextValueFromPath as string;
 
    if (operator === "in") {
      return value.indexOf(valueInContext) !== -1;
    } else if (operator === "notIn") {
      return value.indexOf(valueInContext) === -1;
    }
  } else if (typeof contextValueFromPath === "string" && typeof value === "string") {
    // string
    const valueInContext = contextValueFromPath as string;
 
    if (operator === "contains") {
      return valueInContext.indexOf(value) !== -1;
    } else if (operator === "notContains") {
      return valueInContext.indexOf(value) === -1;
    } else Iif (operator === "startsWith") {
      return valueInContext.startsWith(value);
    } else if (operator === "endsWith") {
      return valueInContext.endsWith(value);
    } else if (operator === "semverEquals") {
      return compareVersions(valueInContext, value) === 0;
    } else if (operator === "semverNotEquals") {
      return compareVersions(valueInContext, value) !== 0;
    } else if (operator === "semverGreaterThan") {
      return compareVersions(valueInContext, value) === 1;
    } else if (operator === "semverGreaterThanOrEquals") {
      return compareVersions(valueInContext, value) >= 0;
    } else if (operator === "semverLessThan") {
      return compareVersions(valueInContext, value) === -1;
    } else if (operator === "semverLessThanOrEquals") {
      return compareVersions(valueInContext, value) <= 0;
    } else if (operator === "matches") {
      const regex = getRegex(value, regexFlags || "");
      return regex.test(valueInContext);
    } else if (operator === "notMatches") {
      const regex = getRegex(value, regexFlags || "");
      return !regex.test(valueInContext);
    }
  } else if (typeof contextValueFromPath === "number" && typeof value === "number") {
    // numeric
    const valueInContext = contextValueFromPath as number;
 
    if (operator === "greaterThan") {
      return valueInContext > value;
    } else if (operator === "greaterThanOrEquals") {
      return valueInContext >= value;
    } else if (operator === "lessThan") {
      return valueInContext < value;
    } else if (operator === "lessThanOrEquals") {
      return valueInContext <= value;
    }
  } else if (operator === "exists") {
    return typeof contextValueFromPath !== "undefined";
  } else if (operator === "notExists") {
    return typeof contextValueFromPath === "undefined";
  } else if (Array.isArray(contextValueFromPath) && typeof value === "string") {
    // includes / notIncludes (where context value is an array)
    const valueInContext = contextValueFromPath as string[];
 
    if (operator === "includes") {
      return valueInContext.indexOf(value) > -1;
    } else if (operator === "notIncludes") {
      return valueInContext.indexOf(value) === -1;
    }
  }
 
  return false;
}