Jelajahi Sumber

stackdriver: refactoring - extract out filtersegments component

Daniel Lee 7 tahun lalu
induk
melakukan
636d8421d0

+ 116 - 0
public/app/plugins/datasource/stackdriver/filter_segments.ts

@@ -0,0 +1,116 @@
+export const DefaultRemoveFilterValue = '-- remove filter --';
+
+export class FilterSegments {
+  filterSegments: any[];
+  removeSegment: any;
+  defaultFilterValue = 'select value';
+
+  constructor(private uiSegmentSrv, private target, private getFilterKeysFunc, private getFilterValuesFunc) {}
+
+  buildSegmentModel() {
+    this.removeSegment = this.uiSegmentSrv.newSegment({ fake: true, value: DefaultRemoveFilterValue });
+
+    this.filterSegments = [];
+    this.target.filters.forEach((f, index) => {
+      switch (index % 4) {
+        case 0:
+          this.filterSegments.push(this.uiSegmentSrv.newKey(f));
+          break;
+        case 1:
+          this.filterSegments.push(this.uiSegmentSrv.newOperator(f));
+          break;
+        case 2:
+          this.filterSegments.push(this.uiSegmentSrv.newKeyValue(f));
+          break;
+        case 3:
+          this.filterSegments.push(this.uiSegmentSrv.newCondition(f));
+          break;
+      }
+    });
+    this.ensurePlusButton(this.filterSegments);
+  }
+
+  async getFilters(segment, index, hasNoFilterKeys) {
+    if (segment.type === 'condition') {
+      return [this.uiSegmentSrv.newSegment('AND')];
+    }
+
+    if (segment.type === 'operator') {
+      return this.uiSegmentSrv.newOperators(['=', '!=', '=~', '!=~']);
+    }
+
+    if (segment.type === 'key' || segment.type === 'plus-button') {
+      if (hasNoFilterKeys && segment.value && segment.value !== DefaultRemoveFilterValue) {
+        this.removeSegment.value = DefaultRemoveFilterValue;
+        return Promise.resolve([this.removeSegment]);
+      } else {
+        return this.getFilterKeysFunc();
+      }
+    }
+
+    if (segment.type === 'value') {
+      const filterValues = this.getFilterValuesFunc(index);
+
+      if (filterValues.length > 0) {
+        return this.getValuesForFilterKey(filterValues);
+      }
+    }
+
+    return [];
+  }
+
+  getValuesForFilterKey(labels: any[]) {
+    const filterValues = labels.map(l => {
+      return this.uiSegmentSrv.newSegment({
+        value: `${l}`,
+        expandable: false,
+      });
+    });
+
+    return filterValues;
+  }
+
+  addNewFilterSegments(segment, index) {
+    if (index > 2) {
+      this.filterSegments.splice(index, 0, this.uiSegmentSrv.newCondition('AND'));
+    }
+    segment.type = 'key';
+    this.filterSegments.push(this.uiSegmentSrv.newOperator('='));
+    this.filterSegments.push(this.uiSegmentSrv.newFake(this.defaultFilterValue, 'value', 'query-segment-value'));
+  }
+
+  removeFilterSegment(index) {
+    this.filterSegments.splice(index, 3);
+    // remove trailing condition
+    if (index > 2 && this.filterSegments[index - 1].type === 'condition') {
+      this.filterSegments.splice(index - 1, 1);
+    }
+
+    // remove condition if it is first segment
+    if (index === 0 && this.filterSegments[0].type === 'condition') {
+      this.filterSegments.splice(0, 1);
+    }
+  }
+
+  ensurePlusButton(segments) {
+    const count = segments.length;
+    const lastSegment = segments[Math.max(count - 1, 0)];
+
+    if (!lastSegment || lastSegment.type !== 'plus-button') {
+      segments.push(this.uiSegmentSrv.newPlusButton());
+    }
+  }
+
+  filterSegmentUpdated(segment, index) {
+    if (segment.type === 'plus-button') {
+      this.addNewFilterSegments(segment, index);
+    } else if (segment.type === 'key' && segment.value === DefaultRemoveFilterValue) {
+      this.removeFilterSegment(index);
+      this.ensurePlusButton(this.filterSegments);
+    } else if (segment.type === 'value' && segment.value !== this.defaultFilterValue) {
+      this.ensurePlusButton(this.filterSegments);
+    }
+
+    return this.filterSegments.filter(s => s.type !== 'plus-button').map(seg => seg.value);
+  }
+}

+ 2 - 2
public/app/plugins/datasource/stackdriver/partials/query.editor.html

@@ -1,4 +1,4 @@
-<query-editor-row query-ctrl="ctrl" has-text-edit-mode="true">
+<query-editor-row query-ctrl="ctrl" has-text-edit-mode="false">
   <div class="gf-form-inline">
   <div class="gf-form-inline">
     <div class="gf-form">
     <div class="gf-form">
       <span class="gf-form-label width-9">Metric Type</span>
       <span class="gf-form-label width-9">Metric Type</span>
@@ -12,7 +12,7 @@
   <div class="gf-form-inline">
   <div class="gf-form-inline">
     <div class="gf-form">
     <div class="gf-form">
       <span class="gf-form-label query-keyword width-9">Filter</span>
       <span class="gf-form-label query-keyword width-9">Filter</span>
-      <div class="gf-form" ng-repeat="segment in ctrl.filterSegments">
+      <div class="gf-form" ng-repeat="segment in ctrl.filterSegments.filterSegments">
         <metric-segment segment="segment" get-options="ctrl.getFilters(segment, $index)" on-change="ctrl.filterSegmentUpdated(segment, $index)"></metric-segment>
         <metric-segment segment="segment" get-options="ctrl.getFilters(segment, $index)" on-change="ctrl.filterSegmentUpdated(segment, $index)"></metric-segment>
       </div>
       </div>
     </div>
     </div>

+ 23 - 95
public/app/plugins/datasource/stackdriver/query_ctrl.ts

@@ -2,7 +2,7 @@ import _ from 'lodash';
 import { QueryCtrl } from 'app/plugins/sdk';
 import { QueryCtrl } from 'app/plugins/sdk';
 import appEvents from 'app/core/app_events';
 import appEvents from 'app/core/app_events';
 import * as options from './constants';
 import * as options from './constants';
-// mport BaseComponent, * as extras from './A';
+import { FilterSegments, DefaultRemoveFilterValue } from './filter_segments';
 
 
 export interface QueryMeta {
 export interface QueryMeta {
   rawQuery: string;
   rawQuery: string;
@@ -54,7 +54,6 @@ export class StackdriverQueryCtrl extends QueryCtrl {
   };
   };
 
 
   groupBySegments: any[];
   groupBySegments: any[];
-  filterSegments: any[];
   removeSegment: any;
   removeSegment: any;
   showHelp: boolean;
   showHelp: boolean;
   showLastQuery: boolean;
   showLastQuery: boolean;
@@ -62,6 +61,7 @@ export class StackdriverQueryCtrl extends QueryCtrl {
   lastQueryError?: string;
   lastQueryError?: string;
   metricLabels: { [key: string]: string[] };
   metricLabels: { [key: string]: string[] };
   resourceLabels: { [key: string]: string[] };
   resourceLabels: { [key: string]: string[] };
+  filterSegments: any;
 
 
   /** @ngInject */
   /** @ngInject */
   constructor($scope, $injector, private uiSegmentSrv, private timeSrv, private templateSrv) {
   constructor($scope, $injector, private uiSegmentSrv, private timeSrv, private templateSrv) {
@@ -86,24 +86,13 @@ export class StackdriverQueryCtrl extends QueryCtrl {
     this.removeSegment = this.uiSegmentSrv.newSegment({ fake: true, value: '-- remove group by --' });
     this.removeSegment = this.uiSegmentSrv.newSegment({ fake: true, value: '-- remove group by --' });
     this.ensurePlusButton(this.groupBySegments);
     this.ensurePlusButton(this.groupBySegments);
 
 
-    this.filterSegments = [];
-    this.target.filters.forEach((f, index) => {
-      switch (index % 4) {
-        case 0:
-          this.filterSegments.push(this.uiSegmentSrv.newKey(f));
-          break;
-        case 1:
-          this.filterSegments.push(this.uiSegmentSrv.newOperator(f));
-          break;
-        case 2:
-          this.filterSegments.push(this.uiSegmentSrv.newKeyValue(f));
-          break;
-        case 3:
-          this.filterSegments.push(this.uiSegmentSrv.newCondition(f));
-          break;
-      }
-    });
-    this.ensurePlusButton(this.filterSegments);
+    this.filterSegments = new FilterSegments(
+      this.uiSegmentSrv,
+      this.target,
+      this.getGroupBys.bind(this, null, null, DefaultRemoveFilterValue, false),
+      this.getFilterValues.bind(this)
+    );
+    this.filterSegments.buildSegmentModel();
   }
   }
 
 
   async getCurrentProject() {
   async getCurrentProject() {
@@ -238,95 +227,34 @@ export class StackdriverQueryCtrl extends QueryCtrl {
   }
   }
 
 
   async getFilters(segment, index) {
   async getFilters(segment, index) {
-    if (segment.type === 'condition') {
-      return [this.uiSegmentSrv.newSegment('AND')];
-    }
-
-    if (segment.type === 'operator') {
-      return this.uiSegmentSrv.newOperators(['=', '!=', '=~', '!=~']);
-    }
+    const hasNoFilterKeys = this.metricLabels && Object.keys(this.metricLabels).length === 0;
+    return this.filterSegments.getFilters(segment, index, hasNoFilterKeys);
+  }
 
 
-    if (segment.type === 'key' || segment.type === 'plus-button') {
-      if (
-        this.metricLabels &&
-        Object.keys(this.metricLabels).length === 0 &&
-        segment.value &&
-        segment.value !== this.defaultRemoveFilterValue
-      ) {
-        this.removeSegment.value = this.defaultRemoveFilterValue;
-        return Promise.resolve([this.removeSegment]);
-      } else {
-        return this.getGroupBys(null, null, this.defaultRemoveFilterValue, false);
-      }
+  getFilterValues(index) {
+    const filterKey = this.templateSrv.replace(this.filterSegments.filterSegments[index - 2].value);
+    if (!filterKey || !this.metricLabels || Object.keys(this.metricLabels).length === 0) {
+      return [];
     }
     }
 
 
-    if (segment.type === 'value') {
-      const filterKey = this.templateSrv.replace(this.filterSegments[index - 2].value);
-      if (!filterKey || !this.metricLabels || Object.keys(this.metricLabels).length === 0) {
-        return [];
-      }
-
-      const shortKey = filterKey.substring(filterKey.indexOf('.label.') + 7);
+    const shortKey = filterKey.substring(filterKey.indexOf('.label.') + 7);
 
 
-      if (filterKey.startsWith('metric.label.') && this.metricLabels.hasOwnProperty(shortKey)) {
-        return this.getValuesForFilterKey(this.metricLabels[shortKey]);
-      }
+    if (filterKey.startsWith('metric.label.') && this.metricLabels.hasOwnProperty(shortKey)) {
+      return this.metricLabels[shortKey];
+    }
 
 
-      if (filterKey.startsWith('resource.label.') && this.resourceLabels.hasOwnProperty(shortKey)) {
-        return this.getValuesForFilterKey(this.resourceLabels[shortKey]);
-      }
+    if (filterKey.startsWith('resource.label.') && this.resourceLabels.hasOwnProperty(shortKey)) {
+      return this.resourceLabels[shortKey];
     }
     }
 
 
     return [];
     return [];
   }
   }
 
 
-  getValuesForFilterKey(labels: any[]) {
-    const filterValues = labels.map(l => {
-      return this.uiSegmentSrv.newSegment({
-        value: `${l}`,
-        expandable: false,
-      });
-    });
-
-    return filterValues;
-  }
-
   filterSegmentUpdated(segment, index) {
   filterSegmentUpdated(segment, index) {
-    if (segment.type === 'plus-button') {
-      this.addNewFilterSegments(segment, index);
-    } else if (segment.type === 'key' && segment.value === this.defaultRemoveFilterValue) {
-      this.removeFilterSegment(index);
-      this.ensurePlusButton(this.filterSegments);
-    } else if (segment.type === 'value' && segment.value !== this.defaultFilterValue) {
-      this.ensurePlusButton(this.filterSegments);
-    }
-
-    this.target.filters = this.filterSegments.filter(s => s.type !== 'plus-button').map(seg => seg.value);
+    this.target.filters = this.filterSegments.filterSegmentUpdated(segment, index);
     this.refresh();
     this.refresh();
   }
   }
 
 
-  addNewFilterSegments(segment, index) {
-    if (index > 2) {
-      this.filterSegments.splice(index, 0, this.uiSegmentSrv.newCondition('AND'));
-    }
-    segment.type = 'key';
-    this.filterSegments.push(this.uiSegmentSrv.newOperator('='));
-    this.filterSegments.push(this.uiSegmentSrv.newFake(this.defaultFilterValue, 'value', 'query-segment-value'));
-  }
-
-  removeFilterSegment(index) {
-    this.filterSegments.splice(index, 3);
-    // remove trailing condition
-    if (index > 2 && this.filterSegments[index - 1].type === 'condition') {
-      this.filterSegments.splice(index - 1, 1);
-    }
-
-    // remove condition if it is first segment
-    if (index === 0 && this.filterSegments[0].type === 'condition') {
-      this.filterSegments.splice(0, 1);
-    }
-  }
-
   ensurePlusButton(segments) {
   ensurePlusButton(segments) {
     const count = segments.length;
     const count = segments.length;
     const lastSegment = segments[Math.max(count - 1, 0)];
     const lastSegment = segments[Math.max(count - 1, 0)];

+ 76 - 58
public/app/plugins/datasource/stackdriver/specs/query_ctrl.test.ts

@@ -12,15 +12,15 @@ describe('StackdriverQueryCtrl', () => {
     });
     });
 
 
     it('should initialize filter segments using the target filter values', () => {
     it('should initialize filter segments using the target filter values', () => {
-      expect(ctrl.filterSegments.length).toBe(8);
-      expect(ctrl.filterSegments[0].type).toBe('key');
-      expect(ctrl.filterSegments[1].type).toBe('operator');
-      expect(ctrl.filterSegments[2].type).toBe('value');
-      expect(ctrl.filterSegments[3].type).toBe('condition');
-      expect(ctrl.filterSegments[4].type).toBe('key');
-      expect(ctrl.filterSegments[5].type).toBe('operator');
-      expect(ctrl.filterSegments[6].type).toBe('value');
-      expect(ctrl.filterSegments[7].type).toBe('plus-button');
+      expect(ctrl.filterSegments.filterSegments.length).toBe(8);
+      expect(ctrl.filterSegments.filterSegments[0].type).toBe('key');
+      expect(ctrl.filterSegments.filterSegments[1].type).toBe('operator');
+      expect(ctrl.filterSegments.filterSegments[2].type).toBe('value');
+      expect(ctrl.filterSegments.filterSegments[3].type).toBe('condition');
+      expect(ctrl.filterSegments.filterSegments[4].type).toBe('key');
+      expect(ctrl.filterSegments.filterSegments[5].type).toBe('operator');
+      expect(ctrl.filterSegments.filterSegments[6].type).toBe('value');
+      expect(ctrl.filterSegments.filterSegments[7].type).toBe('plus-button');
     });
     });
   });
   });
 
 
@@ -106,7 +106,7 @@ describe('StackdriverQueryCtrl', () => {
         result = await ctrl.getFilters(segment, 0);
         result = await ctrl.getFilters(segment, 0);
       });
       });
 
 
-      it('should populate group bys segments', () => {
+      it('should populate condition segments', () => {
         expect(result.length).toBe(1);
         expect(result.length).toBe(1);
         expect(result[0].value).toBe('AND');
         expect(result[0].value).toBe('AND');
       });
       });
@@ -142,7 +142,7 @@ describe('StackdriverQueryCtrl', () => {
         result = await ctrl.getFilters(segment, 0);
         result = await ctrl.getFilters(segment, 0);
       });
       });
 
 
-      it('should populate group bys segments', () => {
+      it('should populate filter key segments', () => {
         expect(result.length).toBe(5);
         expect(result.length).toBe(5);
         expect(result[0].value).toBe('metric.label.metric-key-1');
         expect(result[0].value).toBe('metric.label.metric-key-1');
         expect(result[1].value).toBe('metric.label.metric-key-2');
         expect(result[1].value).toBe('metric.label.metric-key-2');
@@ -163,13 +163,16 @@ describe('StackdriverQueryCtrl', () => {
           'resource-key-2': ['resource-value-2'],
           'resource-key-2': ['resource-value-2'],
         };
         };
 
 
-        ctrl.filterSegments = [{ type: 'key', value: 'metric.label.metric-key-1' }, { type: 'operator', value: '=' }];
+        ctrl.filterSegments.filterSegments = [
+          { type: 'key', value: 'metric.label.metric-key-1' },
+          { type: 'operator', value: '=' },
+        ];
 
 
         const segment = { type: 'value' };
         const segment = { type: 'value' };
         result = await ctrl.getFilters(segment, 2);
         result = await ctrl.getFilters(segment, 2);
       });
       });
 
 
-      it('should populate group bys segments', () => {
+      it('should populate filter value segments', () => {
         expect(result.length).toBe(1);
         expect(result.length).toBe(1);
         expect(result[0].value).toBe('metric-value-1');
         expect(result[0].value).toBe('metric-value-1');
       });
       });
@@ -179,18 +182,18 @@ describe('StackdriverQueryCtrl', () => {
       describe('and there are no other filters', () => {
       describe('and there are no other filters', () => {
         beforeEach(() => {
         beforeEach(() => {
           const segment = { value: 'filterkey1', type: 'plus-button' };
           const segment = { value: 'filterkey1', type: 'plus-button' };
-          ctrl.filterSegments = [segment];
+          ctrl.filterSegments.filterSegments = [segment];
           ctrl.filterSegmentUpdated(segment, 0);
           ctrl.filterSegmentUpdated(segment, 0);
         });
         });
 
 
         it('should transform the plus button segment to a key segment', () => {
         it('should transform the plus button segment to a key segment', () => {
-          expect(ctrl.filterSegments[0].type).toBe('key');
+          expect(ctrl.filterSegments.filterSegments[0].type).toBe('key');
         });
         });
 
 
         it('should add an operator, value segment and plus button segment', () => {
         it('should add an operator, value segment and plus button segment', () => {
-          expect(ctrl.filterSegments.length).toBe(3);
-          expect(ctrl.filterSegments[1].type).toBe('operator');
-          expect(ctrl.filterSegments[2].type).toBe('value');
+          expect(ctrl.filterSegments.filterSegments.length).toBe(3);
+          expect(ctrl.filterSegments.filterSegments[1].type).toBe('operator');
+          expect(ctrl.filterSegments.filterSegments[2].type).toBe('value');
         });
         });
       });
       });
     });
     });
@@ -201,15 +204,20 @@ describe('StackdriverQueryCtrl', () => {
           const existingOperatorSegment = { value: '=', type: 'operator' };
           const existingOperatorSegment = { value: '=', type: 'operator' };
           const existingValueSegment = { value: 'filtervalue', type: 'value' };
           const existingValueSegment = { value: 'filtervalue', type: 'value' };
           const plusSegment = { value: '', type: 'plus-button' };
           const plusSegment = { value: '', type: 'plus-button' };
-          ctrl.filterSegments = [existingKeySegment, existingOperatorSegment, existingValueSegment, plusSegment];
+          ctrl.filterSegments.filterSegments = [
+            existingKeySegment,
+            existingOperatorSegment,
+            existingValueSegment,
+            plusSegment,
+          ];
           ctrl.filterSegmentUpdated(existingKeySegment, 0);
           ctrl.filterSegmentUpdated(existingKeySegment, 0);
         });
         });
 
 
         it('should not add any new segments', () => {
         it('should not add any new segments', () => {
-          expect(ctrl.filterSegments.length).toBe(4);
-          expect(ctrl.filterSegments[0].type).toBe('key');
-          expect(ctrl.filterSegments[1].type).toBe('operator');
-          expect(ctrl.filterSegments[2].type).toBe('value');
+          expect(ctrl.filterSegments.filterSegments.length).toBe(4);
+          expect(ctrl.filterSegments.filterSegments[0].type).toBe('key');
+          expect(ctrl.filterSegments.filterSegments[1].type).toBe('operator');
+          expect(ctrl.filterSegments.filterSegments[2].type).toBe('value');
         });
         });
       });
       });
       describe('and user clicks on value segment and value not equal to fake value', () => {
       describe('and user clicks on value segment and value not equal to fake value', () => {
@@ -217,16 +225,16 @@ describe('StackdriverQueryCtrl', () => {
           const existingKeySegment = { value: 'filterkey1', type: 'key' };
           const existingKeySegment = { value: 'filterkey1', type: 'key' };
           const existingOperatorSegment = { value: '=', type: 'operator' };
           const existingOperatorSegment = { value: '=', type: 'operator' };
           const existingValueSegment = { value: 'filtervalue', type: 'value' };
           const existingValueSegment = { value: 'filtervalue', type: 'value' };
-          ctrl.filterSegments = [existingKeySegment, existingOperatorSegment, existingValueSegment];
+          ctrl.filterSegments.filterSegments = [existingKeySegment, existingOperatorSegment, existingValueSegment];
           ctrl.filterSegmentUpdated(existingValueSegment, 2);
           ctrl.filterSegmentUpdated(existingValueSegment, 2);
         });
         });
 
 
         it('should ensure that plus segment exists', () => {
         it('should ensure that plus segment exists', () => {
-          expect(ctrl.filterSegments.length).toBe(4);
-          expect(ctrl.filterSegments[0].type).toBe('key');
-          expect(ctrl.filterSegments[1].type).toBe('operator');
-          expect(ctrl.filterSegments[2].type).toBe('value');
-          expect(ctrl.filterSegments[3].type).toBe('plus-button');
+          expect(ctrl.filterSegments.filterSegments.length).toBe(4);
+          expect(ctrl.filterSegments.filterSegments[0].type).toBe('key');
+          expect(ctrl.filterSegments.filterSegments[1].type).toBe('operator');
+          expect(ctrl.filterSegments.filterSegments[2].type).toBe('value');
+          expect(ctrl.filterSegments.filterSegments[3].type).toBe('plus-button');
         });
         });
       });
       });
 
 
@@ -235,15 +243,15 @@ describe('StackdriverQueryCtrl', () => {
           const existingKeySegment = { value: 'filterkey1', type: 'key' };
           const existingKeySegment = { value: 'filterkey1', type: 'key' };
           const existingOperatorSegment = { value: '=', type: 'operator' };
           const existingOperatorSegment = { value: '=', type: 'operator' };
           const existingValueSegment = { value: ctrl.defaultFilterValue, type: 'value' };
           const existingValueSegment = { value: ctrl.defaultFilterValue, type: 'value' };
-          ctrl.filterSegments = [existingKeySegment, existingOperatorSegment, existingValueSegment];
+          ctrl.filterSegments.filterSegments = [existingKeySegment, existingOperatorSegment, existingValueSegment];
           ctrl.filterSegmentUpdated(existingValueSegment, 2);
           ctrl.filterSegmentUpdated(existingValueSegment, 2);
         });
         });
 
 
         it('should not add plus segment', () => {
         it('should not add plus segment', () => {
-          expect(ctrl.filterSegments.length).toBe(3);
-          expect(ctrl.filterSegments[0].type).toBe('key');
-          expect(ctrl.filterSegments[1].type).toBe('operator');
-          expect(ctrl.filterSegments[2].type).toBe('value');
+          expect(ctrl.filterSegments.filterSegments.length).toBe(3);
+          expect(ctrl.filterSegments.filterSegments[0].type).toBe('key');
+          expect(ctrl.filterSegments.filterSegments[1].type).toBe('operator');
+          expect(ctrl.filterSegments.filterSegments[2].type).toBe('value');
         });
         });
       });
       });
       describe('and user removes key segment', () => {
       describe('and user removes key segment', () => {
@@ -252,13 +260,18 @@ describe('StackdriverQueryCtrl', () => {
           const existingOperatorSegment = { value: '=', type: 'operator' };
           const existingOperatorSegment = { value: '=', type: 'operator' };
           const existingValueSegment = { value: 'filtervalue', type: 'value' };
           const existingValueSegment = { value: 'filtervalue', type: 'value' };
           const plusSegment = { value: '', type: 'plus-button' };
           const plusSegment = { value: '', type: 'plus-button' };
-          ctrl.filterSegments = [existingKeySegment, existingOperatorSegment, existingValueSegment, plusSegment];
+          ctrl.filterSegments.filterSegments = [
+            existingKeySegment,
+            existingOperatorSegment,
+            existingValueSegment,
+            plusSegment,
+          ];
           ctrl.filterSegmentUpdated(existingKeySegment, 0);
           ctrl.filterSegmentUpdated(existingKeySegment, 0);
         });
         });
 
 
         it('should remove filter segments', () => {
         it('should remove filter segments', () => {
-          expect(ctrl.filterSegments.length).toBe(1);
-          expect(ctrl.filterSegments[0].type).toBe('plus-button');
+          expect(ctrl.filterSegments.filterSegments.length).toBe(1);
+          expect(ctrl.filterSegments.filterSegments[0].type).toBe('plus-button');
         });
         });
       });
       });
 
 
@@ -270,7 +283,7 @@ describe('StackdriverQueryCtrl', () => {
           const existingValueSegment = { value: 'filtervalue', type: 'value' };
           const existingValueSegment = { value: 'filtervalue', type: 'value' };
           const conditionSegment = { value: 'AND', type: 'condition' };
           const conditionSegment = { value: 'AND', type: 'condition' };
           const plusSegment = { value: '', type: 'plus-button' };
           const plusSegment = { value: '', type: 'plus-button' };
-          ctrl.filterSegments = [
+          ctrl.filterSegments.filterSegments = [
             existingKeySegment1,
             existingKeySegment1,
             existingOperatorSegment,
             existingOperatorSegment,
             existingValueSegment,
             existingValueSegment,
@@ -284,11 +297,11 @@ describe('StackdriverQueryCtrl', () => {
         });
         });
 
 
         it('should remove filter segments and the condition segment', () => {
         it('should remove filter segments and the condition segment', () => {
-          expect(ctrl.filterSegments.length).toBe(4);
-          expect(ctrl.filterSegments[0].type).toBe('key');
-          expect(ctrl.filterSegments[1].type).toBe('operator');
-          expect(ctrl.filterSegments[2].type).toBe('value');
-          expect(ctrl.filterSegments[3].type).toBe('plus-button');
+          expect(ctrl.filterSegments.filterSegments.length).toBe(4);
+          expect(ctrl.filterSegments.filterSegments[0].type).toBe('key');
+          expect(ctrl.filterSegments.filterSegments[1].type).toBe('operator');
+          expect(ctrl.filterSegments.filterSegments[2].type).toBe('value');
+          expect(ctrl.filterSegments.filterSegments[3].type).toBe('plus-button');
         });
         });
       });
       });
 
 
@@ -300,7 +313,7 @@ describe('StackdriverQueryCtrl', () => {
           const existingValueSegment = { value: 'filtervalue', type: 'value' };
           const existingValueSegment = { value: 'filtervalue', type: 'value' };
           const conditionSegment = { value: 'AND', type: 'condition' };
           const conditionSegment = { value: 'AND', type: 'condition' };
           const plusSegment = { value: '', type: 'plus-button' };
           const plusSegment = { value: '', type: 'plus-button' };
-          ctrl.filterSegments = [
+          ctrl.filterSegments.filterSegments = [
             existingKeySegment1,
             existingKeySegment1,
             existingOperatorSegment,
             existingOperatorSegment,
             existingValueSegment,
             existingValueSegment,
@@ -314,11 +327,11 @@ describe('StackdriverQueryCtrl', () => {
         });
         });
 
 
         it('should remove filter segments and the condition segment', () => {
         it('should remove filter segments and the condition segment', () => {
-          expect(ctrl.filterSegments.length).toBe(4);
-          expect(ctrl.filterSegments[0].type).toBe('key');
-          expect(ctrl.filterSegments[1].type).toBe('operator');
-          expect(ctrl.filterSegments[2].type).toBe('value');
-          expect(ctrl.filterSegments[3].type).toBe('plus-button');
+          expect(ctrl.filterSegments.filterSegments.length).toBe(4);
+          expect(ctrl.filterSegments.filterSegments[0].type).toBe('key');
+          expect(ctrl.filterSegments.filterSegments[1].type).toBe('operator');
+          expect(ctrl.filterSegments.filterSegments[2].type).toBe('value');
+          expect(ctrl.filterSegments.filterSegments[3].type).toBe('plus-button');
         });
         });
       });
       });
 
 
@@ -328,19 +341,24 @@ describe('StackdriverQueryCtrl', () => {
           const existingOperatorSegment = { value: '=', type: 'operator' };
           const existingOperatorSegment = { value: '=', type: 'operator' };
           const existingValueSegment = { value: 'filtervalue', type: 'value' };
           const existingValueSegment = { value: 'filtervalue', type: 'value' };
           const plusSegment = { value: 'filterkey2', type: 'plus-button' };
           const plusSegment = { value: 'filterkey2', type: 'plus-button' };
-          ctrl.filterSegments = [existingKeySegment, existingOperatorSegment, existingValueSegment, plusSegment];
+          ctrl.filterSegments.filterSegments = [
+            existingKeySegment,
+            existingOperatorSegment,
+            existingValueSegment,
+            plusSegment,
+          ];
           ctrl.filterSegmentUpdated(plusSegment, 3);
           ctrl.filterSegmentUpdated(plusSegment, 3);
         });
         });
 
 
         it('should condition segment and new filter segments', () => {
         it('should condition segment and new filter segments', () => {
-          expect(ctrl.filterSegments.length).toBe(7);
-          expect(ctrl.filterSegments[0].type).toBe('key');
-          expect(ctrl.filterSegments[1].type).toBe('operator');
-          expect(ctrl.filterSegments[2].type).toBe('value');
-          expect(ctrl.filterSegments[3].type).toBe('condition');
-          expect(ctrl.filterSegments[4].type).toBe('key');
-          expect(ctrl.filterSegments[5].type).toBe('operator');
-          expect(ctrl.filterSegments[6].type).toBe('value');
+          expect(ctrl.filterSegments.filterSegments.length).toBe(7);
+          expect(ctrl.filterSegments.filterSegments[0].type).toBe('key');
+          expect(ctrl.filterSegments.filterSegments[1].type).toBe('operator');
+          expect(ctrl.filterSegments.filterSegments[2].type).toBe('value');
+          expect(ctrl.filterSegments.filterSegments[3].type).toBe('condition');
+          expect(ctrl.filterSegments.filterSegments[4].type).toBe('key');
+          expect(ctrl.filterSegments.filterSegments[5].type).toBe('operator');
+          expect(ctrl.filterSegments.filterSegments[6].type).toBe('value');
         });
         });
       });
       });
     });
     });