text:
import chai from 'chai';
import { analyzeCompletion, computeStartCompletePosition, ContextKind } from './hybrid';
import { createEditorState, mockedMetricsTerms, mockPrometheusServer } from '../test/utils.test';
import { Completion, CompletionContext } from '@codemirror/autocomplete';
import {
  aggregateOpModifierTerms,
  aggregateOpTerms,
  atModifierTerms,
  binOpModifierTerms,
  binOpTerms,
  durationTerms,
  functionIdentifierTerms,
  matchOpTerms,
  numberTerms,
  snippets,
} from './promql.terms';
import { EqlSingle, Neq } from '../grammar/parser.terms';
import { syntaxTree } from '@codemirror/language';
import { newCompleteStrategy } from './index';

describe('analyzeCompletion test', () => {
  const testCases = [
    {
      title: 'empty expr',
      expr: '',
      pos: 0,
      expectedContext: [
        {
          kind: ContextKind.MetricName,
          metricName: '',
        },
        { kind: ContextKind.Function },
        { kind: ContextKind.Aggregation },
        { kind: ContextKind.Number },
      ],
    },
    {
      title: 'simple metric & number autocompletion',
      expr: 'go_',
      pos: 3, // cursor is at the end of the expr
      expectedContext: [
        {
          kind: ContextKind.MetricName,
          metricName: 'go_',
        },
        { kind: ContextKind.Function },
        { kind: ContextKind.Aggregation },
        { kind: ContextKind.Number },
      ],
    },
    {
      title: 'metric/function/aggregation autocompletion',
      expr: 'sum()',
      pos: 4,
      expectedContext: [
        {
          kind: ContextKind.MetricName,
          metricName: '',
        },
        { kind: ContextKind.Function },
        { kind: ContextKind.Aggregation },
      ],
    },
    {
      title: 'metric/function/aggregation autocompletion 2',
      expr: 'sum(rat)',
      pos: 7,
      expectedContext: [
        {
          kind: ContextKind.MetricName,
          metricName: 'rat',
        },
        { kind: ContextKind.Function },
        { kind: ContextKind.Aggregation },
      ],
    },
    {
      title: 'metric/function/aggregation autocompletion 3',
      expr: 'sum(rate())',
      pos: 9,
      expectedContext: [
        {
          kind: ContextKind.MetricName,
          metricName: '',
        },
        { kind: ContextKind.Function },
        { kind: ContextKind.Aggregation },
      ],
    },
    {
      title: 'metric/function/aggregation autocompletion 4',
      expr: 'sum(rate(my_))',
      pos: 12,
      expectedContext: [
        {
          kind: ContextKind.MetricName,
          metricName: 'my_',
        },
        { kind: ContextKind.Function },
        { kind: ContextKind.Aggregation },
      ],
    },
    {
      title: 'autocomplete binOp modifier or metric or number',
      expr: 'metric_name / ignor',
      pos: 19,
      expectedContext: [
        { kind: ContextKind.MetricName, metricName: 'ignor' },
        { kind: ContextKind.Function },
        { kind: ContextKind.Aggregation },
        { kind: ContextKind.BinOpModifier },
        { kind: ContextKind.Number },
      ],
    },
    {
      title: 'autocomplete binOp modifier or metric or number 2',
      expr: 'sum(http_requests_total{method="GET"} / o)',
      pos: 41,
      expectedContext: [
        { kind: ContextKind.MetricName, metricName: 'o' },
        { kind: ContextKind.Function },
        { kind: ContextKind.Aggregation },
        { kind: ContextKind.BinOpModifier },
        { kind: ContextKind.Number },
      ],
    },
    {
      title: 'autocomplete bool/binOp modifier/metric/number 1',
      expr: '1 > b)',
      pos: 5,
      expectedContext: [
        { kind: ContextKind.MetricName, metricName: 'b' },
        { kind: ContextKind.Function },
        { kind: ContextKind.Aggregation },
        { kind: ContextKind.BinOpModifier },
        { kind: ContextKind.Number },
        { kind: ContextKind.Bool },
      ],
    },
    {
      title: 'autocomplete bool/binOp modifier/metric/number 2',
      expr: '1 == b)',
      pos: 6,
      expectedContext: [
        { kind: ContextKind.MetricName, metricName: 'b' },
        { kind: ContextKind.Function },
        { kind: ContextKind.Aggregation },
        { kind: ContextKind.BinOpModifier },
        { kind: ContextKind.Number },
        { kind: ContextKind.Bool },
      ],
    },
    {
      title: 'autocomplete bool/binOp modifier/metric/number 3',
      expr: '1 != b)',
      pos: 6,
      expectedContext: [
        { kind: ContextKind.MetricName, metricName: 'b' },
        { kind: ContextKind.Function },
        { kind: ContextKind.Aggregation },
        { kind: ContextKind.BinOpModifier },
        { kind: ContextKind.Number },
        { kind: ContextKind.Bool },
      ],
    },
    {
      title: 'autocomplete bool/binOp modifier/metric/number 4',
      expr: '1 > b)',
      pos: 5,
      expectedContext: [
        { kind: ContextKind.MetricName, metricName: 'b' },
        { kind: ContextKind.Function },
        { kind: ContextKind.Aggregation },
        { kind: ContextKind.BinOpModifier },
        { kind: ContextKind.Number },
        { kind: ContextKind.Bool },
      ],
    },
    {
      title: 'autocomplete bool/binOp modifier/metric/number 5',
      expr: '1 >= b)',
      pos: 6,
      expectedContext: [
        { kind: ContextKind.MetricName, metricName: 'b' },
        { kind: ContextKind.Function },
        { kind: ContextKind.Aggregation },
        { kind: ContextKind.BinOpModifier },
        { kind: ContextKind.Number },
        { kind: ContextKind.Bool },
      ],
    },
    {
      title: 'autocomplete bool/binOp modifier/metric/number 6',
      expr: '1 <= b)',
      pos: 6,
      expectedContext: [
        { kind: ContextKind.MetricName, metricName: 'b' },
        { kind: ContextKind.Function },
        { kind: ContextKind.Aggregation },
        { kind: ContextKind.BinOpModifier },
        { kind: ContextKind.Number },
        { kind: ContextKind.Bool },
      ],
    },
    {
      title: 'autocomplete bool/binOp modifier/metric/number 7',
      expr: '1 < b)',
      pos: 5,
      expectedContext: [
        { kind: ContextKind.MetricName, metricName: 'b' },
        { kind: ContextKind.Function },
        { kind: ContextKind.Aggregation },
        { kind: ContextKind.BinOpModifier },
        { kind: ContextKind.Number },
        { kind: ContextKind.Bool },
      ],
    },
    {
      title: 'starting to autocomplete labelName in aggregate modifier',
      expr: 'sum by ()',
      pos: 8, // cursor is between the bracket
      expectedContext: [{ kind: ContextKind.LabelName }],
    },
    {
      title: 'continue to autocomplete labelName in aggregate modifier',
      expr: 'sum by (myL)',
      pos: 11, // cursor is between the bracket after the string myL
      expectedContext: [{ kind: ContextKind.LabelName }],
    },
    {
      title: 'autocomplete labelName in a list',
      expr: 'sum by (myLabel1,)',
      pos: 17, // cursor is between the bracket after the string myLab
      expectedContext: [{ kind: ContextKind.LabelName }],
    },
    {
      title: 'autocomplete labelName in a list 2',
      expr: 'sum by (myLabel1, myLab)',
      pos: 23, // cursor is between the bracket after the string myLab
      expectedContext: [{ kind: ContextKind.LabelName }],
    },
    {
      title: 'autocomplete labelName associated to a metric',
      expr: 'metric_name{}',
      pos: 12, // cursor is between the bracket
      expectedContext: [{ kind: ContextKind.LabelName, metricName: 'metric_name' }],
    },
    {
      title: 'autocomplete labelName that defined a metric',
      expr: '{}',
      pos: 1, // cursor is between the bracket
      expectedContext: [{ kind: ContextKind.LabelName, metricName: '' }],
    },
    {
      title: 'continue to autocomplete labelName associated to a metric',
      expr: 'metric_name{myL}',
      pos: 15, // cursor is between the bracket after the string myL
      expectedContext: [{ kind: ContextKind.LabelName, metricName: 'metric_name' }],
    },
    {
      title: 'continue to autocomplete labelName associated to a metric 2',
      expr: 'metric_name{myLabel="labelValue",}',
      pos: 33, // cursor is between the bracket after the comma
      expectedContext: [{ kind: ContextKind.LabelName, metricName: 'metric_name' }],
    },
    {
      title: 'continue autocomplete labelName that defined a metric',
      expr: '{myL}',
      pos: 4, // cursor is between the bracket after the string myL
      expectedContext: [{ kind: ContextKind.LabelName, metricName: '' }],
    },
    {
      title: 'continue autocomplete labelName that defined a metric 2',
      expr: '{myLabel="labelValue",}',
      pos: 22, // cursor is between the bracket after the comma
      expectedContext: [{ kind: ContextKind.LabelName, metricName: '' }],
    },
    {
      title: 'autocomplete the labelValue with metricName + labelName',
      expr: 'metric_name{labelName=""}',
      pos: 23, // cursor is between the quotes
      expectedContext: [
        {
          kind: ContextKind.LabelValue,
          metricName: 'metric_name',
          labelName: 'labelName',
          matchers: [
            {
              name: 'labelName',
              type: EqlSingle,
              value: '',
            },
          ],
        },
      ],
    },
    {
      title: 'autocomplete the labelValue with metricName + labelName 2',
      expr: 'metric_name{labelName="labelValue", labelName!=""}',
      pos: 48, // cursor is between the quotes
      expectedContext: [
        {
          kind: ContextKind.LabelValue,
          metricName: 'metric_name',
          labelName: 'labelName',
          matchers: [
            {
              name: 'labelName',
              type: EqlSingle,
              value: 'labelValue',
            },
            {
              name: 'labelName',
              type: Neq,
              value: '',
            },
          ],
        },
      ],
    },
    {
      title: 'autocomplete the labelValue associated to a labelName',
      expr: '{labelName=""}',
      pos: 12, // cursor is between the quotes
      expectedContext: [
        {
          kind: ContextKind.LabelValue,
          metricName: '',
          labelName: 'labelName',
          matchers: [
            {
              name: 'labelName',
              type: EqlSingle,
              value: '',
            },
          ],
        },
      ],
    },
    {
      title: 'autocomplete the labelValue associated to a labelName 2',
      expr: '{labelName="labelValue", labelName!=""}',
      pos: 37, // cursor is between the quotes
      expectedContext: [
        {
          kind: ContextKind.LabelValue,
          metricName: '',
          labelName: 'labelName',
          matchers: [
            {
              name: 'labelName',
              type: EqlSingle,
              value: 'labelValue',
            },
            {
              name: 'labelName',
              type: Neq,
              value: '',
            },
          ],
        },
      ],
    },
    {
      title: 'autocomplete AggregateOpModifier or BinOp',
      expr: 'sum() b',
      pos: 7, // cursor is after the 'b'
      expectedContext: [{ kind: ContextKind.AggregateOpModifier }, { kind: ContextKind.BinOp }],
    },
    {
      title: 'autocomplete AggregateOpModifier or BinOp 2',
      expr: 'sum(rate(foo[5m])) an',
      pos: 21,
      expectedContext: [{ kind: ContextKind.AggregateOpModifier }, { kind: ContextKind.BinOp }],
    },
    {
      title: 'autocomplete AggregateOpModifier or BinOp or Offset',
      expr: 'sum b',
      pos: 5, // cursor is after 'b'
      expectedContext: [{ kind: ContextKind.AggregateOpModifier }, { kind: ContextKind.BinOp }, { kind: ContextKind.Offset }],
    },
    {
      title: 'autocomplete binOp',
      expr: 'metric_name !',
      pos: 13,
      expectedContext: [{ kind: ContextKind.BinOp }],
    },
    {
      title: 'autocomplete binOp 2',
      expr: 'metric_name =',
      pos: 13,
      expectedContext: [{ kind: ContextKind.BinOp }],
    },
    {
      title: 'autocomplete matchOp',
      expr: 'go{instance=""}',
      pos: 12, // cursor is after the 'equal'
      expectedContext: [{ kind: ContextKind.MatchOp }],
    },
    {
      title: 'autocomplete matchOp 2',
      expr: 'metric_name{labelName!}',
      pos: 22, // cursor is after '!'
      expectedContext: [{ kind: ContextKind.MatchOp }],
    },
    {
      title: 'autocomplete duration with offset',
      expr: 'http_requests_total offset 5',
      pos: 28,
      expectedContext: [{ kind: ContextKind.Duration }],
    },
    {
      title: 'autocomplete duration with offset',
      expr: 'sum(http_requests_total{method="GET"} offset 4)',
      pos: 46,
      expectedContext: [{ kind: ContextKind.Duration }],
    },
    {
      title: 'autocomplete offset or binOp',
      expr: 'http_requests_total off',
      pos: 23,
      expectedContext: [{ kind: ContextKind.BinOp }, { kind: ContextKind.Offset }],
    },
    {
      title: 'autocomplete offset or binOp 2',
      expr: 'metric_name unle',
      pos: 16,
      expectedContext: [{ kind: ContextKind.BinOp }, { kind: ContextKind.Offset }],
    },
    {
      title: 'autocomplete offset or binOp 3',
      expr: 'http_requests_total{method="GET"} off',
      pos: 37,
      expectedContext: [{ kind: ContextKind.BinOp }, { kind: ContextKind.Offset }],
    },
    {
      title: 'autocomplete offset or binOp 4',
      expr: 'rate(foo[5m]) un',
      pos: 16,
      expectedContext: [{ kind: ContextKind.BinOp }, { kind: ContextKind.Offset }],
    },
    {
      title: 'autocomplete offset or binop 5',
      expr: 'sum(http_requests_total{method="GET"} off)',
      pos: 41,
      expectedContext: [{ kind: ContextKind.BinOp }, { kind: ContextKind.Offset }],
    },
    {
      title: 'not autocompleting duration for a matrixSelector',
      expr: 'go[]',
      pos: 3,
      expectedContext: [],
    },
    {
      title: 'not autocompleting duration for a matrixSelector 2',
      expr: 'go{l1="l2"}[]',
      pos: 12,
      expectedContext: [],
    },
    {
      title: 'autocomplete duration for a matrixSelector',
      expr: 'go[5]',
      pos: 4,
      expectedContext: [{ kind: ContextKind.Duration }],
    },
    {
      title: 'autocomplete duration for a matrixSelector 2',
      expr: 'go[5d1]',
      pos: 6,
      expectedContext: [{ kind: ContextKind.Duration }],
    },
    {
      title: 'autocomplete duration for a matrixSelector 3',
      expr: 'rate(my_metric{l1="l2"}[25])',
      pos: 26,
      expectedContext: [{ kind: ContextKind.Duration }],
    },
    {
      title: 'autocomplete duration for a matrixSelector 4',
      expr: 'rate(my_metric{l1="l2"}[25d5])',
      pos: 28,
      expectedContext: [{ kind: ContextKind.Duration }],
    },
    {
      title: 'autocomplete duration for a subQuery',
      expr: 'go[5d:5]',
      pos: 7,
      expectedContext: [{ kind: ContextKind.Duration }],
    },
    {
      title: 'autocomplete duration for a subQuery 2',
      expr: 'go[5d:5d4]',
      pos: 9,
      expectedContext: [{ kind: ContextKind.Duration }],
    },
    {
      title: 'autocomplete duration for a subQuery 3',
      expr: 'rate(my_metric{l1="l2"}[25d:6])',
      pos: 29,
      expectedContext: [{ kind: ContextKind.Duration }],
    },
    {
      title: 'autocomplete duration for a subQuery 4',
      expr: 'rate(my_metric{l1="l2"}[25d:6d5])',
      pos: 31,
      expectedContext: [{ kind: ContextKind.Duration }],
    },
    {
      title: 'autocomplete at modifiers',
      expr: '1 @ s',
      pos: 5,
      expectedContext: [{ kind: ContextKind.AtModifiers }],
    },
  ];
  testCases.forEach((value) => {
    it(value.title, () => {
      const state = createEditorState(value.expr);
      const node = syntaxTree(state).resolve(value.pos, -1);
      const result = analyzeCompletion(state, node);
      chai.expect(value.expectedContext).to.deep.equal(result);
    });
  });
});

describe('computeStartCompletePosition test', () => {
  const testCases = [
    {
      title: 'empty bracket',
      expr: '{}',
      pos: 1, // cursor is between the bracket
      expectedStart: 1,
    },
    {
      title: 'empty bracket 2',
      expr: 'metricName{}',
      pos: 11, // cursor is between the bracket
      expectedStart: 11,
    },
    {
      title: 'empty bracket 3',
      expr: 'sum by()',
      pos: 7, // cursor is between the bracket
      expectedStart: 7,
    },
    {
      title: 'empty bracket 4',
      expr: 'sum by(test) ()',
      pos: 14, // cursor is between the bracket
      expectedStart: 14,
    },
    {
      title: 'empty bracket 5',
      expr: 'sum()',
      pos: 4, // cursor is between the bracket
      expectedStart: 4,
    },
    {
      title: 'empty bracket 6',
      expr: 'sum(rate())',
      pos: 9, // cursor is between the bracket
      expectedStart: 9,
    },
    {
      title: 'bracket containing a substring',
      expr: '{myL}',
      pos: 4, // cursor is between the bracket
      expectedStart: 1,
    },
    {
      title: 'bracket containing a substring 2',
      expr: '{myLabel="LabelValue",}',
      pos: 22, // cursor is after the comma
      expectedStart: 22,
    },
    {
      title: 'bracket containing a substring 2',
      expr: 'metricName{myL}',
      pos: 14, // cursor is between the bracket
      expectedStart: 11,
    },
    {
      title: 'bracket containing a substring 3',
      expr: 'metricName{myLabel="LabelValue",}',
      pos: 32, // cursor is after the comma
      expectedStart: 32,
    },
    {
      title: 'bracket containing a substring 4',
      expr: 'sum by(myL)',
      pos: 10, // cursor is between the bracket
      expectedStart: 7,
    },
    {
      title: 'bracket containing a substring 5',
      expr: 'sum by(myLabel,)',
      pos: 15, // cursor is after the comma
      expectedStart: 15,
    },
    {
      title: 'bracket containing a substring 6',
      expr: 'sum(ra)',
      pos: 6, // cursor is between the bracket
      expectedStart: 4,
    },
    {
      title: 'bracket containing a substring 7',
      expr: 'sum(rate(my))',
      pos: 11, // cursor is between the bracket
      expectedStart: 9,
    },
    {
      title: 'start should not be at the beginning of the substring',
      expr: 'metric_name{labelName!}',
      pos: 22,
      expectedStart: 21,
    },
    {
      title: 'start should not be at the beginning of the substring 2',
      expr: 'metric_name{labelName!="labelValue"}',
      pos: 22,
      expectedStart: 21,
    },
    {
      title: 'start should be equal to the pos for the duration of an offset',
      expr: 'http_requests_total offset 5',
      pos: 28,
      expectedStart: 28,
    },
    {
      title: 'start should be equal to the pos for the duration of an offset 2',
      expr: 'http_requests_total offset 587',
      pos: 30,
      expectedStart: 30,
    },
    {
      title: 'start should be equal to the pos for the duration of an offset 3',
      expr: 'http_requests_total offset 587',
      pos: 29,
      expectedStart: 29,
    },
    {
      title: 'start should be equal to the pos for the duration of an offset 4',
      expr: 'sum(http_requests_total{method="GET"} offset 4)',
      pos: 46,
      expectedStart: 46,
    },
    {
      title: 'start should not be equal to the pos for the duration in a matrix selector',
      expr: 'go[]',
      pos: 3,
      expectedStart: 0,
    },
    {
      title: 'start should be equal to the pos for the duration in a matrix selector',
      expr: 'go[5]',
      pos: 4,
      expectedStart: 4,
    },
    {
      title: 'start should be equal to the pos for the duration in a matrix selector 2',
      expr: 'go[5d5]',
      pos: 6,
      expectedStart: 6,
    },
    {
      title: 'start should be equal to the pos for the duration in a matrix selector 3',
      expr: 'rate(my_metric{l1="l2"}[25])',
      pos: 26,
      expectedStart: 26,
    },
    {
      title: 'start should be equal to the pos for the duration in a matrix selector 4',
      expr: 'rate(my_metric{l1="l2"}[25d5])',
      pos: 28,
      expectedStart: 28,
    },
    {
      title: 'start should be equal to the pos for the duration in a subquery selector',
      expr: 'go[5d:5]',
      pos: 7,
      expectedStart: 7,
    },
    {
      title: 'start should be equal to the pos for the duration in a subquery selector 2',
      expr: 'go[5d:5d5]',
      pos: 9,
      expectedStart: 9,
    },
    {
      title: 'start should be equal to the pos for the duration in a subquery selector 3',
      expr: 'rate(my_metric{l1="l2"}[25d:6])',
      pos: 29,
      expectedStart: 29,
    },
    {
      title: 'start should be equal to the pos for the duration in a subquery selector 3',
      expr: 'rate(my_metric{l1="l2"}[25d:6d5])',
      pos: 31,
      expectedStart: 31,
    },
  ];
  testCases.forEach((value) => {
    it(value.title, () => {
      const state = createEditorState(value.expr);
      const node = syntaxTree(state).resolve(value.pos, -1);
      const result = computeStartCompletePosition(node, value.pos);
      chai.expect(value.expectedStart).to.equal(result);
    });
  });
});

describe('autocomplete promQL test', () => {
  beforeEach(() => {
    mockPrometheusServer();
  });
  const testCases = [
    {
      title: 'offline empty expr',
      expr: '',
      pos: 0,
      expectedResult: {
        options: ([] as Completion[]).concat(functionIdentifierTerms, aggregateOpTerms, numberTerms, snippets),
        from: 0,
        to: 0,
        span: /^[a-zA-Z0-9_:]+$/,
      },
    },
    {
      title: 'offline simple function/aggregation/number autocompletion',
      expr: 'go_',
      pos: 3,
      expectedResult: {
        options: ([] as Completion[]).concat(functionIdentifierTerms, aggregateOpTerms, numberTerms, snippets),
        from: 0,
        to: 3,
        span: /^[a-zA-Z0-9_:]+$/,
      },
    },
    {
      title: 'offline function/aggregation autocompletion in aggregation',
      expr: 'sum()',
      pos: 4,
      expectedResult: {
        options: ([] as Completion[]).concat(functionIdentifierTerms, aggregateOpTerms, snippets),
        from: 4,
        to: 4,
        span: /^[a-zA-Z0-9_:]+$/,
      },
    },
    {
      title: 'offline function/aggregation autocompletion in aggregation 2',
      expr: 'sum(ra)',
      pos: 6,
      expectedResult: {
        options: ([] as Completion[]).concat(functionIdentifierTerms, aggregateOpTerms, snippets),
        from: 4,
        to: 6,
        span: /^[a-zA-Z0-9_:]+$/,
      },
    },
    {
      title: 'offline function/aggregation autocompletion in aggregation 3',
      expr: 'sum(rate())',
      pos: 9,
      expectedResult: {
        options: ([] as Completion[]).concat(functionIdentifierTerms, aggregateOpTerms, snippets),
        from: 9,
        to: 9,
        span: /^[a-zA-Z0-9_:]+$/,
      },
    },
    {
      title: 'offline function/aggregation autocompletion in aggregation 4',
      expr: 'sum by (instance, job) ( sum_over(scrape_series_added[1h])) / sum by (instance, job) (sum_over_time(scrape_samples_scraped[1h])) > 0.1 and sum by(instance, job) (scrape_samples_scraped{) > 100',
      pos: 33,
      expectedResult: {
        options: ([] as Completion[]).concat(functionIdentifierTerms, aggregateOpTerms, snippets),
        from: 25,
        to: 33,
        span: /^[a-zA-Z0-9_:]+$/,
      },
    },
    {
      title: 'autocomplete binOp modifier/metric/number',
      expr: 'metric_name / ignor',
      pos: 19,
      expectedResult: {
        options: ([] as Completion[]).concat(functionIdentifierTerms, aggregateOpTerms, binOpModifierTerms, numberTerms, snippets),
        from: 14,
        to: 19,
        span: /^[a-zA-Z0-9_:]+$/,
      },
    },
    {
      title: 'autocomplete binOp modifier/metric/number 2',
      expr: 'sum(http_requests_total{method="GET"} / o)',
      pos: 41,
      expectedResult: {
        options: ([] as Completion[]).concat(functionIdentifierTerms, aggregateOpTerms, binOpModifierTerms, numberTerms, snippets),
        from: 40,
        to: 41,
        span: /^[a-zA-Z0-9_:]+$/,
      },
    },
    {
      title: 'offline autocomplete labelName return nothing',
      expr: 'sum by ()',
      pos: 8, // cursor is between the bracket
      expectedResult: {
        options: [],
        from: 8,
        to: 8,
        span: /^[a-zA-Z0-9_:]+$/,
      },
    },
    {
      title: 'offline autocomplete labelName return nothing 2',
      expr: 'sum by (myL)',
      pos: 11, // cursor is between the bracket after the string myL
      expectedResult: {
        options: [],
        from: 8,
        to: 11,
        span: /^[a-zA-Z0-9_:]+$/,
      },
    },
    {
      title: 'offline autocomplete labelName return nothing 3',
      expr: 'sum by (myLabel1, myLab)',
      pos: 23, // cursor is between the bracket after the string myLab
      expectedResult: {
        options: [],
        from: 18,
        to: 23,
        span: /^[a-zA-Z0-9_:]+$/,
      },
    },
    {
      title: 'offline autocomplete labelName return nothing 4',
      expr: 'metric_name{}',
      pos: 12, // cursor is between the bracket
      expectedResult: {
        options: [],
        from: 12,
        to: 12,
        span: /^[a-zA-Z0-9_:]+$/,
      },
    },
    {
      title: 'offline autocomplete labelName return nothing 5',
      expr: '{}',
      pos: 1, // cursor is between the bracket
      expectedResult: {
        options: [],
        from: 1,
        to: 1,
        span: /^[a-zA-Z0-9_:]+$/,
      },
    },
    {
      title: 'offline autocomplete labelName return nothing 6',
      expr: 'metric_name{myL}',
      pos: 15, // cursor is between the bracket after the string myL
      expectedResult: {
        options: [],
        from: 12,
        to: 15,
        span: /^[a-zA-Z0-9_:]+$/,
      },
    },
    {
      title: 'offline autocomplete labelName return nothing 7',
      expr: '{myL}',
      pos: 4, // cursor is between the bracket after the string myL
      expectedResult: {
        options: [],
        from: 1,
        to: 4,
        span: /^[a-zA-Z0-9_:]+$/,
      },
    },
    {
      title: 'offline autocomplete labelValue return nothing',
      expr: 'metric_name{labelName=""}',
      pos: 23, // cursor is between the quotes
      expectedResult: {
        options: [],
        from: 23,
        to: 23,
        span: /^[a-zA-Z0-9_:]+$/,
      },
    },
    {
      title: 'offline autocomplete labelValue return nothing 2',
      expr: '{labelName=""}',
      pos: 12, // cursor is between the quotes
      expectedResult: {
        options: [],
        from: 12,
        to: 12,
        span: /^[a-zA-Z0-9_:]+$/,
      },
    },
    {
      title: 'offline autocomplete aggregate operation modifier or binary operator',
      expr: 'sum() b',
      pos: 7, // cursor is after 'b'
      expectedResult: {
        options: ([] as Completion[]).concat(aggregateOpModifierTerms, binOpTerms),
        from: 6,
        to: 7,
        span: /^[a-zA-Z0-9_:]+$/,
      },
    },
    {
      title: 'offline autocomplete aggregate operation modifier or binary operator 2',
      expr: 'sum(rate(foo[5m])) an',
      pos: 21, // cursor is after the string 'an'
      expectedResult: {
        options: ([] as Completion[]).concat(aggregateOpModifierTerms, binOpTerms),
        from: 19,
        to: 21,
        span: /^[a-zA-Z0-9_:]+$/,
      },
    },
    {
      title: 'offline autocomplete aggregate operation modifier or binary operator or offset',
      expr: 'sum b',
      pos: 5, // cursor is after 'b'
      expectedResult: {
        options: ([] as Completion[]).concat(aggregateOpModifierTerms, binOpTerms, [{ label: 'offset' }]),
        from: 4,
        to: 5,
        span: /^[a-zA-Z0-9_:]+$/,
      },
    },
    {
      title: 'offline autocomplete binOp',
      expr: 'metric_name !',
      pos: 13,
      expectedResult: {
        options: binOpTerms,
        from: 12,
        to: 13,
        span: /^[a-zA-Z0-9_:]+$/,
      },
    },
    {
      title: 'offline autocomplete binOp 2',
      expr: 'metric_name =',
      pos: 13,
      expectedResult: {
        options: binOpTerms,
        from: 12,
        to: 13,
        span: /^[a-zA-Z0-9_:]+$/,
      },
    },
    {
      title: 'offline autocomplete matchOp',
      expr: 'go{instance=""}',
      pos: 12, // cursor is after the 'equal'
      expectedResult: {
        options: matchOpTerms,
        from: 11,
        to: 12,
        span: /^[a-zA-Z0-9_:]+$/,
      },
    },
    {
      title: 'offline autocomplete matchOp 2',
      expr: 'metric_name{labelName!}',
      pos: 22, // cursor is after '!'
      expectedResult: {
        options: matchOpTerms,
        from: 21,
        to: 22,
        span: /^[a-zA-Z0-9_:]+$/,
      },
    },
    {
      title: 'offline autocomplete duration with offset',
      expr: 'http_requests_total offset 5',
      pos: 28,
      expectedResult: {
        options: durationTerms,
        from: 28,
        to: 28,
        span: undefined,
      },
    },
    {
      title: 'offline autocomplete duration with offset 2',
      expr: 'sum(http_requests_total{method="GET"} offset 4)',
      pos: 46,
      expectedResult: {
        options: durationTerms,
        from: 46,
        to: 46,
        span: undefined,
      },
    },
    {
      title: 'offline autocomplete offset or binOp',
      expr: 'http_requests_total off',
      pos: 23,
      expectedResult: {
        options: ([] as Completion[]).concat(binOpTerms, [{ label: 'offset' }]),
        from: 20,
        to: 23,
        span: /^[a-zA-Z0-9_:]+$/,
      },
    },
    {
      title: 'offline autocomplete offset or binOp 2',
      expr: 'metric_name unle',
      pos: 16,
      expectedResult: {
        options: ([] as Completion[]).concat(binOpTerms, [{ label: 'offset' }]),
        from: 12,
        to: 16,
        span: /^[a-zA-Z0-9_:]+$/,
      },
    },
    {
      title: 'offline autocomplete offset or binOp 3',
      expr: 'http_requests_total{method="GET"} off',
      pos: 37,
      expectedResult: {
        options: ([] as Completion[]).concat(binOpTerms, [{ label: 'offset' }]),
        from: 34,
        to: 37,
        span: /^[a-zA-Z0-9_:]+$/,
      },
    },
    {
      title: 'offline autocomplete offset or binOp 4',
      expr: 'rate(foo[5m]) un',
      pos: 16,
      expectedResult: {
        options: ([] as Completion[]).concat(binOpTerms, [{ label: 'offset' }]),
        from: 14,
        to: 16,
        span: /^[a-zA-Z0-9_:]+$/,
      },
    },
    {
      title: 'autocomplete offset or binop 5',
      expr: 'sum(http_requests_total{method="GET"} off)',
      pos: 41,
      expectedResult: {
        options: ([] as Completion[]).concat(binOpTerms, [{ label: 'offset' }]),
        from: 38,
        to: 41,
        span: /^[a-zA-Z0-9_:]+$/,
      },
    },
    {
      title: 'offline not autocompleting duration for a matrixSelector',
      expr: 'go[]',
      pos: 3,
      expectedResult: {
        options: [],
        from: 0,
        to: 3,
        span: /^[a-zA-Z0-9_:]+$/,
      },
    },
    {
      title: 'offline not autocompleting duration for a matrixSelector 2',
      expr: 'go{l1="l2"}[]',
      pos: 12,
      expectedResult: {
        options: [],
        from: 0,
        to: 12,
        span: /^[a-zA-Z0-9_:]+$/,
      },
    },
    {
      title: 'offline autocomplete duration for a matrixSelector',
      expr: 'go[5]',
      pos: 4,
      expectedResult: {
        options: durationTerms,
        from: 4,
        to: 4,
        span: undefined,
      },
    },
    {
      title: 'offline autocomplete duration for a matrixSelector 2',
      expr: 'go[5d1]',
      pos: 6,
      expectedResult: {
        options: durationTerms,
        from: 6,
        to: 6,
        span: undefined,
      },
    },
    {
      title: 'offline autocomplete duration for a matrixSelector 3',
      expr: 'rate(my_metric{l1="l2"}[25])',
      pos: 26,
      expectedResult: {
        options: durationTerms,
        from: 26,
        to: 26,
        span: undefined,
      },
    },
    {
      title: 'offline autocomplete duration for a matrixSelector 4',
      expr: 'rate(my_metric{l1="l2"}[25d5])',
      pos: 28,
      expectedResult: {
        options: durationTerms,
        from: 28,
        to: 28,
        span: undefined,
      },
    },
    {
      title: 'offline autocomplete duration for a subQuery',
      expr: 'go[5d:5]',
      pos: 7,
      expectedResult: {
        options: durationTerms,
        from: 7,
        to: 7,
        span: undefined,
      },
    },
    {
      title: 'offline autocomplete duration for a subQuery 2',
      expr: 'go[5d:5d4]',
      pos: 9,
      expectedResult: {
        options: durationTerms,
        from: 9,
        to: 9,
        span: undefined,
      },
    },
    {
      title: 'offline autocomplete duration for a subQuery 3',
      expr: 'rate(my_metric{l1="l2"}[25d:6])',
      pos: 29,
      expectedResult: {
        options: durationTerms,
        from: 29,
        to: 29,
        span: undefined,
      },
    },
    {
      title: 'offline autocomplete duration for a subQuery 4',
      expr: 'rate(my_metric{l1="l2"}[25d:6d5])',
      pos: 31,
      expectedResult: {
        options: durationTerms,
        from: 31,
        to: 31,
        span: undefined,
      },
    },
    {
      title: 'offline autocomplete at modifiers',
      expr: '1 @ s',
      pos: 5,
      expectedResult: {
        options: atModifierTerms,
        from: 4,
        to: 5,
        span: /^[a-zA-Z0-9_:]+$/,
      },
    },
    {
      title: 'online autocomplete of metrics',
      expr: 'alert',
      pos: 5,
      conf: { remote: { url: 'http://localhost:8080' } },
      expectedResult: {
        options: ([] as Completion[]).concat(mockedMetricsTerms, functionIdentifierTerms, aggregateOpTerms, numberTerms, snippets),
        from: 0,
        to: 5,
        span: /^[a-zA-Z0-9_:]+$/,
      },
    },
    {
      title: 'online autocomplete of label name corresponding to a metric',
      expr: 'alertmanager_alerts{}',
      pos: 20,
      conf: { remote: { url: 'http://localhost:8080' } },
      expectedResult: {
        options: [
          {
            label: 'env',
            type: 'constant',
          },
          {
            label: 'instance',
            type: 'constant',
          },
          {
            label: 'job',
            type: 'constant',
          },
          {
            label: 'state',
            type: 'constant',
          },
        ],
        from: 20,
        to: 20,
        span: /^[a-zA-Z0-9_:]+$/,
      },
    },
    {
      title: 'online autocomplete of label value corresponding to a metric and a label name',
      expr: 'alertmanager_alerts{env=""}',
      pos: 25,
      conf: { remote: { url: 'http://localhost:8080' } },
      expectedResult: {
        options: [
          {
            label: 'demo',
            type: 'text',
          },
        ],
        from: 25,
        to: 25,
        span: /^[a-zA-Z0-9_:]+$/,
      },
    },
    {
      title: 'online autocomplete with initial metric list',
      expr: 'rat',
      pos: 3,
      conf: { remote: { cache: { initialMetricList: ['metric1', 'metric2', 'rat'] } } },
      expectedResult: {
        options: ([] as Completion[]).concat(
          [
            {
              label: 'metric1',
              type: 'constant',
            },
            {
              label: 'metric2',
              type: 'constant',
            },
            {
              label: 'rat',
              type: 'constant',
            },
          ],
          functionIdentifierTerms,
          aggregateOpTerms,
          numberTerms,
          snippets
        ),
        from: 0,
        to: 3,
        span: /^[a-zA-Z0-9_:]+$/,
      },
    },
  ];
  testCases.forEach((value) => {
    it(value.title, async () => {
      const state = createEditorState(value.expr);
      const context = new CompletionContext(state, value.pos, true);
      const completion = newCompleteStrategy(value.conf);
      const result = await completion.promQL(context);
      chai.expect(value.expectedResult).to.deep.equal(result);
    });
  });
});


text:
07966 189 084 hayley@hayleytwheeler.co.uk
The Coaching Programme
Helping Athletes Succeed – Workshop
Limitless Kids
GDPR Privacy Policy Additional Notice
Home » About » Praise
Some of the comments received by clients following coaching sessions and after completing coaching programmes
WORKSHOPS AND SPEAKING ENGAGEMENTS
Feedback from 'Helping Athletes Succeed' workshop -
'Really insightful - lots of really handy tips to push us in the right direction with supporting our athletes'
'Great knowledge, really hit home. Massive help personally'
'Excellent workshop. More understanding, develop exciting happenings. Great guest speakers'
'Really got a lot out of this. Learnt some great pointers which I can apply in the future'
'A hugely enjoyable course. Lots of points have hit home on a personal level. Great personal stories from the speakers. Very well delivered course. Mind is working overtime (in a good way) as to how we can start the conversation in club.'
'Very informative - great help'
'As a person who suffers with mental health, has a family history of mental health, think this was a massive step in approaching the subject and having listened to people who have come out of it the other side it gives me hope that its possible to live with it on a daily basis.'
'Enjoyable course. Very informative. Lots of personal experiences / stats. A lot to think about: pledge, code of conduct, feelings, discussions.'
"Hayley gave one of the best keynotes we have had at the Ignite Business Club to date. She made us all think especially about looking after ourselves. I high recommend Hayley T Wheeler visit her website to find out how she can help you and your business. "
"Looking back now I don't even recognise the person I was before meeting Hayley. I was broken with no hope of things getting better and began to accept that that was my life. After my first session I felt like I was in a safe place where I could talk through my emotions and finally open up with someone who would listen without judgement. I actively use her coaching method every day to help me take back control of my anxiety and she has helped me take the right steps to find out who I am. I can't thank Hayley enough for all the tools she has given me, listening to me, helping me click the restart button on my life and most importantly she has taught me to love myself again."
"When you tell me that you feel proud of my journey I wish I could show you my insides. I wish you could feel the happiness jumping around inside me. It's like little ping pongs balls bouncing around. I can look back now and let go a little. I can think about things but move forward. You listened when no one else has before and that listening and patience with me has changed the way I look at everything. I can't actually put into words how much I appreciate everything you have done for me and how grateful I will forever be for the time that you have given to me."
"I would just like to thank you for everything you and this programme has done for me. I never knew I could have come this far since last year and I am now the happiest I have been in as long as I can remember! This programme has given me the tools to be able to overcome problems and issues I didn't know how and made me able to view things in a different more positive perspective. My anxiety and depression has rapidly decreased since starting the programme and my self esteem has rocketed! So if just like to say again a massive thank you to you"
"When I first went on this course I didn't really think it would change much, if anything. As the weeks went on I found myself questioning different things in ways I never had. I was on the verge of cancelling my very first holiday, as the stress and anxiety had built up to such a level I really didn't think I could cope. But after each session I was starting to see differences, some small, some not so small. In the way I was dealing with things and life in general, I believe this course has given me new ways of dealing with stress and anxiety. It has also made me feel more confident in the decisions I do actually make. I also believe that if it were not for Hayley and this course I would never have known what a normal family holiday would have felt like, and I never would have had the most amazing time!!
I am now looking forward to and planning the next. This course hasn't given me the answers to everything but has taught me ways of dealing with situations in a more positive aspect, but mainly it has taught me how to start changing my negative attitude to all change. I wouldn't say I look forward to change now, I still find things difficult sometimes, but now, I am no longer scared. I would just like to say thank you Hayley for helping me achieve something i never ever thought possible, there is light at the end of the tunnel"
"Hayley and the recent work she has done with the Mothers living in the community of Morfa has been nothing short of inspiring. She engaged them fully in each session, tackling many difficult and emotive subjects week on week. Her manner and delivery pushes people to think on a deeper level without being judgemental, allowing them to re-assess and importantly re-focus on what is important.
The difference we have seen in the group that completed the course has also been highly complimentary of the work Hayley has done with them. We have seen noticeable differences in the ability of one of the mothers to cope with her current relationship breakdown, another has gone on to further education and all have feedback positive changes in regards to the relationships they have with their children.
We hope to work again with Hayley in the future but in the mean time wish her all the best in her work."
"I met Hayley a few years ago, but little did I know how instrumental she would be in shaping my future. I thought I had pretty much dealt with the things that were holding me back in my professional life and personal life & during one of our sessions we had touched on if fear was holding me back. I felt that no, it wasn't. A few months later I was in a very dark place on a personal level and booked in to see Hayley. After suffering with anxiety for four years I was feeling at my lowest after a sequence of personal issues.
We worked through Hayley's course & with her help we uncovered that I was living constantly in grief and that my coping mechanisms were covering over 70 major traumatic events in my life. I had no previous understanding that these were holding me back and shaping how I lived. The course gave me the final piece of the puzzle to help rebuild my life the way I wanted, to take control of my thoughts and move on emotionally. The course has armed me with strategies to future-proof my life and design it the way I want. I've learnt I'm allowed to be me and embrace that. So thank you Hayley for truly releasing me from a prison I didn't even know was there! Truly thank you so much, you've unlocked so much"
"Thank you so much for speaking at both our campaign days. The service users have made loads of wonderful comments about your talk and how much they could relate to your story. A lot of service users really enjoyed the aspect of using visual representation (jars) to express their emotions and commented that they found doing the jar activity a lot easier than to talk openly about how they were feeling.... once again thank you so much "
"Thank you for all your faith, support and encouragement you have put in me over the last few months. My house has a mammy my children deserve... I am so glad I opened up to you or my fog would never have been lifted. I've enjoyed seeing myself change week by week, and get stronger. I'm beginning to understand myself more which was hard at first. The difference in me is amazing.
Thank you, you've changed my life forever."
Developed, Hosted and Maintained by Pixel and Print Ltd.
By continuing to use the site, you agree to the use of cookies. Privacy Policy

redpajama_set_name: RedPajamaCommonCrawl