Browse Source

feat(search): Share tests between frontend + backend (take 2) (#26753)

This was reverted in GH-26706 due to a invalid regex (in safari) in some
parsing code (which this PR tested).

This is the take 2 along with GH-26723
Evan Purkhiser 3 years ago
parent
commit
c0903e00f5

+ 56 - 0
static/app/components/searchSyntax/utils.tsx

@@ -0,0 +1,56 @@
+import {Token, TokenResult} from './parser';
+
+/**
+ * Utility function to visit every Token node within an AST tree and apply
+ * a transform to those nodes.
+ */
+export function treeTransformer(
+  tree: TokenResult<Token>[],
+  transform: (token: TokenResult<Token>) => any
+) {
+  const nodeVisitor = (token: TokenResult<Token>) => {
+    switch (token.type) {
+      case Token.Filter:
+        return transform({
+          ...token,
+          key: nodeVisitor(token.key),
+          value: nodeVisitor(token.value),
+        });
+      case Token.KeyExplicitTag:
+        return transform({
+          ...token,
+          key: nodeVisitor(token.key),
+        });
+      case Token.KeyAggregate:
+        return transform({
+          ...token,
+          name: nodeVisitor(token.name),
+          args: token.args ? nodeVisitor(token.args) : token.args,
+          argsSpaceBefore: nodeVisitor(token.argsSpaceBefore),
+          argsSpaceAfter: nodeVisitor(token.argsSpaceAfter),
+        });
+      case Token.LogicGroup:
+        return transform({
+          ...token,
+          inner: token.inner.map(nodeVisitor),
+        });
+      case Token.KeyAggregateArgs:
+        return transform({
+          ...token,
+          args: token.args.map(v => ({...v, value: nodeVisitor(v.value)})),
+        });
+      case Token.ValueNumberList:
+      case Token.ValueTextList:
+        return transform({
+          ...token,
+          // TODO(ts): Not sure why `v` cannot be inferred here
+          items: token.items.map((v: any) => ({...v, value: nodeVisitor(v.value)})),
+        });
+
+      default:
+        return transform(token);
+    }
+  };
+
+  return tree.map(nodeVisitor);
+}

+ 34 - 0
tests/fixtures/search-syntax/aggregate_duration_filter.json

@@ -0,0 +1,34 @@
+[
+  {
+    "query": "avg(transaction.duration):>500s",
+    "result": [
+      {
+        "type": "filter",
+        "filter": "aggregateDuration",
+        "negated": false,
+        "key": {
+          "type": "keyAggregate",
+          "name": {"type": "keySimple", "value": "avg", "quoted": false},
+          "args": {
+            "type": "keyAggregateArgs",
+            "args": [
+              {
+                "separator": "",
+                "value": {
+                  "type": "keySimple",
+                  "value": "transaction.duration",
+                  "quoted": false
+                }
+              }
+            ]
+          },
+          "argsSpaceBefore": {"type": "spaces", "value": ""},
+          "argsSpaceAfter": {"type": "spaces", "value": ""}
+        },
+        "operator": ">",
+        "value": {"type": "valueDuration", "value": 500, "unit": "s"}
+      },
+      {"type": "spaces", "value": ""}
+    ]
+  }
+]

+ 35 - 0
tests/fixtures/search-syntax/aggregate_duration_filter_overrides_numeric_shorthand.json

@@ -0,0 +1,35 @@
+[
+  {
+    "desc": "2m should mean 2 minutes for duration filters (as opposed to 2 million)",
+    "query": "avg(transaction.duration):>2m",
+    "result": [
+      {
+        "type": "filter",
+        "filter": "aggregateDuration",
+        "negated": false,
+        "key": {
+          "type": "keyAggregate",
+          "name": {"type": "keySimple", "value": "avg", "quoted": false},
+          "args": {
+            "type": "keyAggregateArgs",
+            "args": [
+              {
+                "separator": "",
+                "value": {
+                  "type": "keySimple",
+                  "value": "transaction.duration",
+                  "quoted": false
+                }
+              }
+            ]
+          },
+          "argsSpaceBefore": {"type": "spaces", "value": ""},
+          "argsSpaceAfter": {"type": "spaces", "value": ""}
+        },
+        "operator": ">",
+        "value": {"type": "valueDuration", "value": 2, "unit": "m"}
+      },
+      {"type": "spaces", "value": ""}
+    ]
+  }
+]

+ 56 - 0
tests/fixtures/search-syntax/aggregate_rel_time_filter.json

@@ -0,0 +1,56 @@
+[
+  {
+    "query": "last_seen():+7d",
+    "result": [
+      {
+        "type": "filter",
+        "filter": "aggregateRelativeDate",
+        "negated": false,
+        "key": {
+          "type": "keyAggregate",
+          "name": {"type": "keySimple", "value": "last_seen", "quoted": false},
+          "args": null,
+          "argsSpaceBefore": {"type": "spaces", "value": ""},
+          "argsSpaceAfter": {"type": "spaces", "value": ""}
+        },
+        "operator": "",
+        "value": {"type": "valueRelativeDate", "value": 7, "sign": "+", "unit": "d"}
+      },
+      {"type": "spaces", "value": ""}
+    ]
+  },
+  {
+    "query": "last_seen():-2w",
+    "result": [
+      {
+        "type": "filter",
+        "filter": "aggregateRelativeDate",
+        "negated": false,
+        "key": {
+          "type": "keyAggregate",
+          "name": {"type": "keySimple", "value": "last_seen", "quoted": false},
+          "args": null,
+          "argsSpaceBefore": {"type": "spaces", "value": ""},
+          "argsSpaceAfter": {"type": "spaces", "value": ""}
+        },
+        "operator": "",
+        "value": {"type": "valueRelativeDate", "value": 2, "sign": "-", "unit": "w"}
+      },
+      {"type": "spaces", "value": ""}
+    ]
+  },
+  {
+    "query": "random:-2w",
+    "result": [
+      {
+        "type": "filter",
+        "filter": "text",
+        "negated": false,
+        "key": {"type": "keySimple", "value": "random", "quoted": false},
+        "operator": "",
+        "value": {"type": "valueText", "value": "-2w", "quoted": false}
+      },
+      {"type": "spaces", "value": ""}
+    ]
+  }
+]

+ 100 - 0
tests/fixtures/search-syntax/basic_fallthrough.json

@@ -0,0 +1,100 @@
+[
+  {
+    "query": "random:<hello",
+    "result": [
+      {
+        "type": "filter",
+        "filter": "text",
+        "negated": false,
+        "key": {"type": "keySimple", "value": "random", "quoted": false},
+        "operator": "",
+        "value": {"type": "valueText", "value": "<hello", "quoted": false}
+      },
+      {"type": "spaces", "value": ""}
+    ]
+  },
+  {
+    "query": "random:<512.1.0",
+    "result": [
+      {
+        "type": "filter",
+        "filter": "text",
+        "negated": false,
+        "key": {"type": "keySimple", "value": "random", "quoted": false},
+        "operator": "",
+        "value": {"type": "valueText", "value": "<512.1.0", "quoted": false}
+      },
+      {"type": "spaces", "value": ""}
+    ]
+  },
+  {
+    "query": "random:2018-01-01",
+    "result": [
+      {
+        "type": "filter",
+        "filter": "text",
+        "negated": false,
+        "key": {"type": "keySimple", "value": "random", "quoted": false},
+        "operator": "",
+        "value": {"type": "valueText", "value": "2018-01-01", "quoted": false}
+      },
+      {"type": "spaces", "value": ""}
+    ]
+  },
+  {
+    "query": "random:+7d",
+    "result": [
+      {
+        "type": "filter",
+        "filter": "text",
+        "negated": false,
+        "key": {"type": "keySimple", "value": "random", "quoted": false},
+        "operator": "",
+        "value": {"type": "valueText", "value": "+7d", "quoted": false}
+      },
+      {"type": "spaces", "value": ""}
+    ]
+  },
+  {
+    "query": "random:>2018-01-01",
+    "result": [
+      {
+        "type": "filter",
+        "filter": "text",
+        "negated": false,
+        "key": {"type": "keySimple", "value": "random", "quoted": false},
+        "operator": "",
+        "value": {"type": "valueText", "value": ">2018-01-01", "quoted": false}
+      },
+      {"type": "spaces", "value": ""}
+    ]
+  },
+  {
+    "query": "random:hello",
+    "result": [
+      {
+        "type": "filter",
+        "filter": "text",
+        "negated": false,
+        "key": {"type": "keySimple", "value": "random", "quoted": false},
+        "operator": "",
+        "value": {"type": "valueText", "value": "hello", "quoted": false}
+      },
+      {"type": "spaces", "value": ""}
+    ]
+  },
+  {
+    "query": "random:123",
+    "result": [
+      {
+        "type": "filter",
+        "filter": "text",
+        "negated": false,
+        "key": {"type": "keySimple", "value": "random", "quoted": false},
+        "operator": "",
+        "value": {"type": "valueText", "value": "123", "quoted": false}
+      },
+      {"type": "spaces", "value": ""}
+    ]
+  }
+]

+ 100 - 0
tests/fixtures/search-syntax/boolean_filter.json

@@ -0,0 +1,100 @@
+[
+  {
+    "query": "stack.in_app:true",
+    "result": [
+      {
+        "type": "filter",
+        "filter": "boolean",
+        "negated": false,
+        "key": {"type": "keySimple", "value": "stack.in_app", "quoted": false},
+        "operator": "",
+        "value": {"type": "valueBoolean", "value": true}
+      },
+      {"type": "spaces", "value": ""}
+    ]
+  },
+  {
+    "query": "stack.in_app:TRUE",
+    "result": [
+      {
+        "type": "filter",
+        "filter": "boolean",
+        "negated": false,
+        "key": {"type": "keySimple", "value": "stack.in_app", "quoted": false},
+        "operator": "",
+        "value": {"type": "valueBoolean", "value": true}
+      },
+      {"type": "spaces", "value": ""}
+    ]
+  },
+  {
+    "query": "stack.in_app:1",
+    "result": [
+      {
+        "type": "filter",
+        "filter": "boolean",
+        "negated": false,
+        "key": {"type": "keySimple", "value": "stack.in_app", "quoted": false},
+        "operator": "",
+        "value": {"type": "valueBoolean", "value": true}
+      },
+      {"type": "spaces", "value": ""}
+    ]
+  },
+  {
+    "query": "stack.in_app:false",
+    "result": [
+      {
+        "type": "filter",
+        "filter": "boolean",
+        "negated": false,
+        "key": {"type": "keySimple", "value": "stack.in_app", "quoted": false},
+        "operator": "",
+        "value": {"type": "valueBoolean", "value": false}
+      },
+      {"type": "spaces", "value": ""}
+    ]
+  },
+  {
+    "query": "stack.in_app:FALSE",
+    "result": [
+      {
+        "type": "filter",
+        "filter": "boolean",
+        "negated": false,
+        "key": {"type": "keySimple", "value": "stack.in_app", "quoted": false},
+        "operator": "",
+        "value": {"type": "valueBoolean", "value": false}
+      },
+      {"type": "spaces", "value": ""}
+    ]
+  },
+  {
+    "query": "stack.in_app:0",
+    "result": [
+      {
+        "type": "filter",
+        "filter": "boolean",
+        "negated": false,
+        "key": {"type": "keySimple", "value": "stack.in_app", "quoted": false},
+        "operator": "",
+        "value": {"type": "valueBoolean", "value": false}
+      },
+      {"type": "spaces", "value": ""}
+    ]
+  },
+  {
+    "query": "!stack.in_app:false",
+    "result": [
+      {
+        "type": "filter",
+        "filter": "boolean",
+        "negated": true,
+        "key": {"type": "keySimple", "value": "stack.in_app", "quoted": false},
+        "operator": "",
+        "value": {"type": "valueBoolean", "value": false}
+      },
+      {"type": "spaces", "value": ""}
+    ]
+  }
+]

+ 16 - 0
tests/fixtures/search-syntax/boolean_filter_passthrough.json

@@ -0,0 +1,16 @@
+[
+  {
+    "query": "project_id:1",
+    "result": [
+      {
+        "type": "filter",
+        "filter": "numeric",
+        "negated": false,
+        "key": {"type": "keySimple", "value": "project_id", "quoted": false},
+        "operator": "",
+        "value": {"type": "valueNumber", "value": "1", "rawValue": 1, "unit": null}
+      },
+      {"type": "spaces", "value": ""}
+    ]
+  }
+]

+ 42 - 0
tests/fixtures/search-syntax/custom_explicit_tag.json

@@ -0,0 +1,42 @@
+[
+  {
+    "query": "tags[fruit]:apple release:1.2.1 tags[project_id]:123",
+    "result": [
+      {
+        "type": "filter",
+        "filter": "text",
+        "negated": false,
+        "key": {
+          "type": "keyExplicitTag",
+          "prefix": "tags",
+          "key": {"type": "keySimple", "value": "fruit", "quoted": false}
+        },
+        "operator": "",
+        "value": {"type": "valueText", "value": "apple", "quoted": false}
+      },
+      {"type": "spaces", "value": " "},
+      {
+        "type": "filter",
+        "filter": "text",
+        "negated": false,
+        "key": {"type": "keySimple", "value": "release", "quoted": false},
+        "operator": "",
+        "value": {"type": "valueText", "value": "1.2.1", "quoted": false}
+      },
+      {"type": "spaces", "value": " "},
+      {
+        "type": "filter",
+        "filter": "text",
+        "negated": false,
+        "key": {
+          "type": "keyExplicitTag",
+          "prefix": "tags",
+          "key": {"type": "keySimple", "value": "project_id", "quoted": false}
+        },
+        "operator": "",
+        "value": {"type": "valueText", "value": "123", "quoted": false}
+      },
+      {"type": "spaces", "value": ""}
+    ]
+  }
+]

+ 25 - 0
tests/fixtures/search-syntax/custom_tag.json

@@ -0,0 +1,25 @@
+[
+  {
+    "query": "fruit:apple release:1.2.1",
+    "result": [
+      {
+        "type": "filter",
+        "filter": "text",
+        "negated": false,
+        "key": {"type": "keySimple", "value": "fruit", "quoted": false},
+        "operator": "",
+        "value": {"type": "valueText", "value": "apple", "quoted": false}
+      },
+      {"type": "spaces", "value": " "},
+      {
+        "type": "filter",
+        "filter": "text",
+        "negated": false,
+        "key": {"type": "keySimple", "value": "release", "quoted": false},
+        "operator": "",
+        "value": {"type": "valueText", "value": "1.2.1", "quoted": false}
+      },
+      {"type": "spaces", "value": ""}
+    ]
+  }
+]

+ 110 - 0
tests/fixtures/search-syntax/duration_aggregate_measurements_filter.json

@@ -0,0 +1,110 @@
+[
+  {
+    "query": "percentile(measurements.fp, 0.5):3.3s",
+    "result": [
+      {
+        "type": "filter",
+        "filter": "aggregateDuration",
+        "negated": false,
+        "key": {
+          "type": "keyAggregate",
+          "name": {"type": "keySimple", "value": "percentile", "quoted": false},
+          "args": {
+            "type": "keyAggregateArgs",
+            "args": [
+              {
+                "separator": "",
+                "value": {
+                  "type": "keySimple",
+                  "value": "measurements.fp",
+                  "quoted": false
+                }
+              },
+              {
+                "separator": ", ",
+                "value": {"type": "keySimple", "value": "0.5", "quoted": false}
+              }
+            ]
+          },
+          "argsSpaceBefore": {"type": "spaces", "value": ""},
+          "argsSpaceAfter": {"type": "spaces", "value": ""}
+        },
+        "operator": "",
+        "value": {"type": "valueDuration", "value": 3.3, "unit": "s"}
+      },
+      {"type": "spaces", "value": ""}
+    ]
+  },
+  {
+    "query": "percentile(measurements.fp, 0.5):>3.3s",
+    "result": [
+      {
+        "type": "filter",
+        "filter": "aggregateDuration",
+        "negated": false,
+        "key": {
+          "type": "keyAggregate",
+          "name": {"type": "keySimple", "value": "percentile", "quoted": false},
+          "args": {
+            "type": "keyAggregateArgs",
+            "args": [
+              {
+                "separator": "",
+                "value": {
+                  "type": "keySimple",
+                  "value": "measurements.fp",
+                  "quoted": false
+                }
+              },
+              {
+                "separator": ", ",
+                "value": {"type": "keySimple", "value": "0.5", "quoted": false}
+              }
+            ]
+          },
+          "argsSpaceBefore": {"type": "spaces", "value": ""},
+          "argsSpaceAfter": {"type": "spaces", "value": ""}
+        },
+        "operator": ">",
+        "value": {"type": "valueDuration", "value": 3.3, "unit": "s"}
+      },
+      {"type": "spaces", "value": ""}
+    ]
+  },
+  {
+    "query": "percentile(measurements.fp, 0.5):<3.3s",
+    "result": [
+      {
+        "type": "filter",
+        "filter": "aggregateDuration",
+        "negated": false,
+        "key": {
+          "type": "keyAggregate",
+          "name": {"type": "keySimple", "value": "percentile", "quoted": false},
+          "args": {
+            "type": "keyAggregateArgs",
+            "args": [
+              {
+                "separator": "",
+                "value": {
+                  "type": "keySimple",
+                  "value": "measurements.fp",
+                  "quoted": false
+                }
+              },
+              {
+                "separator": ", ",
+                "value": {"type": "keySimple", "value": "0.5", "quoted": false}
+              }
+            ]
+          },
+          "argsSpaceBefore": {"type": "spaces", "value": ""},
+          "argsSpaceAfter": {"type": "spaces", "value": ""}
+        },
+        "operator": "<",
+        "value": {"type": "valueDuration", "value": 3.3, "unit": "s"}
+      },
+      {"type": "spaces", "value": ""}
+    ]
+  }
+]

Some files were not shown because too many files changed in this diff