<commit_before>/**
 * @license
 * Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
 * This code may only be used under the BSD style license found at
 * http://polymer.github.io/LICENSE.txt
 * The complete set of authors may be found at
 * http://polymer.github.io/AUTHORS.txt
 * The complete set of contributors may be found at
 * http://polymer.github.io/CONTRIBUTORS.txt
 * Code distributed by Google as part of the polymer project is also
 * subject to an additional IP rights grant found at
 * http://polymer.github.io/PATENTS.txt
 */

import {assert} from 'chai';
import * as clone from 'clone';
import {readFileSync} from 'fs';
import * as path from 'path';
import {CompletionItem, CompletionItemKind, CompletionList, InsertTextFormat, MarkupContent} from 'vscode-languageserver/lib/main';

import {standardJavaScriptSnippets} from '../standard-snippets';

import {createTestEnvironment, defaultClientCapabilities} from './util';

const fixtureDir = path.join(__dirname, '..', '..', 'src', 'test', 'static');

const elementCompletions: CompletionItem[] = [
  {
    documentation: {
      kind: 'markdown',
      value: 'An element to test out behavior inheritance.'
    },
    insertText: '<behavior-test-elem $1></behavior-test-elem>$0',
    insertTextFormat: InsertTextFormat.Snippet,
    kind: CompletionItemKind.Class,
    label: '<behavior-test-elem>',
    filterText: 'behaviortestelem',
  },
  {
    documentation: {kind: 'markdown', value: ''},
    insertText: '<class-declaration></class-declaration>$0',
    insertTextFormat: InsertTextFormat.Snippet,
    kind: CompletionItemKind.Class,
    label: '<class-declaration>',
    filterText: 'classdeclaration',
  },
  {
    documentation: {kind: 'markdown', value: ''},
    insertText: '<anonymous-class></anonymous-class>$0',
    insertTextFormat: InsertTextFormat.Snippet,
    kind: CompletionItemKind.Class,
    label: '<anonymous-class>',
    filterText: 'anonymousclass',
  },
  {
    documentation: {kind: 'markdown', value: ''},
    insertText: '<class-expression></class-expression>$0',
    insertTextFormat: InsertTextFormat.Snippet,
    kind: CompletionItemKind.Class,
    label: '<class-expression>',
    filterText: 'classexpression',
  },
  {
    documentation: {kind: 'markdown', value: ''},
    insertText: '<register-before-declaration></register-before-declaration>$0',
    insertTextFormat: InsertTextFormat.Snippet,
    kind: CompletionItemKind.Class,
    label: '<register-before-declaration>',
    filterText: 'registerbeforedeclaration',
  },
  {
    documentation: {kind: 'markdown', value: ''},
    insertText: '<register-before-expression></register-before-expression>$0',
    insertTextFormat: InsertTextFormat.Snippet,
    kind: CompletionItemKind.Class,
    label: '<register-before-expression>',
    filterText: 'registerbeforeexpression',
  },
  {
    documentation: {
      kind: 'markdown',
      value: 'This is a description of WithObservedAttributes.'
    },
    insertText: '<vanilla-with-observed-attributes $1>' +
        '</vanilla-with-observed-attributes>$0',
    insertTextFormat: InsertTextFormat.Snippet,
    kind: CompletionItemKind.Class,
    label: '<vanilla-with-observed-attributes>',
    filterText: 'vanillawithobservedattributes',
  },
];

// Like elementCompletions, but without leading `<` characters.
const elementTagnameCompletions = elementCompletions.map((ec) => {
  return {...ec, insertText: ec.insertText!.slice(1)};
});

const elementCompletionsWithPlainDescriptions = elementCompletions.map((ec) => {
  return {...ec, documentation: (ec.documentation as MarkupContent).value};
});

const attributeCompletions: CompletionItem[] = [
  {
    label: 'local-property',
    documentation: {
      kind: 'markdown',
      value: 'A property defined directly on behavior-test-elem.',
    },
    kind: CompletionItemKind.Field,
    detail: '{boolean | null | undefined}',
    sortText: 'aaa-local-property',
  },
  {
    label: 'non-notifying-property',
    documentation: {kind: 'markdown', value: ''},
    kind: CompletionItemKind.Field,
    detail: '{string | null | undefined}',
    sortText: 'aaa-non-notifying-property',
  },
  {
    label: 'notifying-property',
    documentation: {kind: 'markdown', value: ''},
    kind: CompletionItemKind.Field,
    detail: '{string | null | undefined}',
    sortText: 'aaa-notifying-property',

  },
  {
    label: 'deeply-inherited-property',
    documentation: {
      kind: 'markdown',
      value: 'This is a deeply inherited property.',
    },
    kind: CompletionItemKind.Field,
    detail: '{Array | null | undefined} ⊃ MyNamespace.SubBehavior',
    sortText: 'ddd-deeply-inherited-property',
  },
  {
    label: 'inherit-please',
    documentation: {
      kind: 'markdown',
      value: 'A property provided by SimpleBehavior.',
    },
    kind: CompletionItemKind.Field,
    detail: '{number | null | undefined} ⊃ MyNamespace.SimpleBehavior',
    sortText: 'ddd-inherit-please',
  },
  {
    label: 'on-local-property-changed',
    documentation: {
      kind: 'markdown',
      value: 'Fired when the `localProperty` property changes.'
    },
    kind: CompletionItemKind.Field,
    detail: '{CustomEvent}',
    sortText: 'eee-aaa-on-local-property-changed',
  },
  {
    label: 'on-notifying-property-changed',
    documentation: {
      kind: 'markdown',
      value: 'Fired when the `notifyingProperty` property changes.'
    },
    kind: CompletionItemKind.Field,
    detail: '{CustomEvent}',
    sortText: 'eee-aaa-on-notifying-property-changed',
  },
  {
    label: 'on-deeply-inherited-property-changed',
    documentation: {
      kind: 'markdown',
      value: 'Fired when the `deeplyInheritedProperty` property changes.'
    },
    kind: CompletionItemKind.Field,
    detail: '{CustomEvent} ⊃ MyNamespace.SubBehavior',
    sortText: 'eee-ddd-on-deeply-inherited-property-changed',
  },
  {
    label: 'on-inherit-please-changed',
    documentation: {
      kind: 'markdown',
      value: 'Fired when the `inheritPlease` property changes.'
    },
    kind: CompletionItemKind.Field,
    detail: '{CustomEvent} ⊃ MyNamespace.SimpleBehavior',
    sortText: 'eee-ddd-on-inherit-please-changed',
  },
];

suite('AutoCompleter', () => {
  const indexFile = path.join('editor-service', 'index.html');
  const indexContents = readFileSync(path.join(fixtureDir, indexFile), 'utf-8');
  const tagPosition = {line: 7, column: 9};
  const tagPositionEnd = {line: 7, column: 21};
  const localAttributePosition = {line: 7, column: 31};

  test('Get element completions for an empty text region', async() => {
    const {client} = await createTestEnvironment({fixtureDir});
    await client.openFile(indexFile);
    const completions =
        await client.getCompletions(indexFile, {line: 0, column: 0});
    assert.deepEqual(
        completions, {isIncomplete: false, items: elementCompletions});
    await client.cleanup();
  });

  let testName = `Doesn't send down markdown if the client doesn't support it`;
  test(testName, async() => {
    const capabilities = clone(defaultClientCapabilities);
    capabilities.textDocument!.completion!.completionItem! = {
      ...(capabilities.textDocument!.completion!.completionItem!),
      documentationFormat: undefined
    };

    const {client} = await createTestEnvironment({fixtureDir, capabilities});
    await client.openFile(indexFile);<commit_msg>Skip the AutoCompleter suite for the moment due to flaky tests.<commit_after>/**
 * @license
 * Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
 * This code may only be used under the BSD style license found at
 * http://polymer.github.io/LICENSE.txt
 * The complete set of authors may be found at
 * http://polymer.github.io/AUTHORS.txt
 * The complete set of contributors may be found at
 * http://polymer.github.io/CONTRIBUTORS.txt
 * Code distributed by Google as part of the polymer project is also
 * subject to an additional IP rights grant found at
 * http://polymer.github.io/PATENTS.txt
 */

import {assert} from 'chai';
import * as clone from 'clone';
import {readFileSync} from 'fs';
import * as path from 'path';
import {CompletionItem, CompletionItemKind, CompletionList, InsertTextFormat, MarkupContent} from 'vscode-languageserver/lib/main';

import {standardJavaScriptSnippets} from '../standard-snippets';

import {createTestEnvironment, defaultClientCapabilities} from './util';

const fixtureDir = path.join(__dirname, '..', '..', 'src', 'test', 'static');

const elementCompletions: CompletionItem[] = [
  {
    documentation: {
      kind: 'markdown',
      value: 'An element to test out behavior inheritance.'
    },
    insertText: '<behavior-test-elem $1></behavior-test-elem>$0',
    insertTextFormat: InsertTextFormat.Snippet,
    kind: CompletionItemKind.Class,
    label: '<behavior-test-elem>',
    filterText: 'behaviortestelem',
  },
  {
    documentation: {kind: 'markdown', value: ''},
    insertText: '<class-declaration></class-declaration>$0',
    insertTextFormat: InsertTextFormat.Snippet,
    kind: CompletionItemKind.Class,
    label: '<class-declaration>',
    filterText: 'classdeclaration',
  },
  {
    documentation: {kind: 'markdown', value: ''},
    insertText: '<anonymous-class></anonymous-class>$0',
    insertTextFormat: InsertTextFormat.Snippet,
    kind: CompletionItemKind.Class,
    label: '<anonymous-class>',
    filterText: 'anonymousclass',
  },
  {
    documentation: {kind: 'markdown', value: ''},
    insertText: '<class-expression></class-expression>$0',
    insertTextFormat: InsertTextFormat.Snippet,
    kind: CompletionItemKind.Class,
    label: '<class-expression>',
    filterText: 'classexpression',
  },
  {
    documentation: {kind: 'markdown', value: ''},
    insertText: '<register-before-declaration></register-before-declaration>$0',
    insertTextFormat: InsertTextFormat.Snippet,
    kind: CompletionItemKind.Class,
    label: '<register-before-declaration>',
    filterText: 'registerbeforedeclaration',
  },
  {
    documentation: {kind: 'markdown', value: ''},
    insertText: '<register-before-expression></register-before-expression>$0',
    insertTextFormat: InsertTextFormat.Snippet,
    kind: CompletionItemKind.Class,
    label: '<register-before-expression>',
    filterText: 'registerbeforeexpression',
  },
  {
    documentation: {
      kind: 'markdown',
      value: 'This is a description of WithObservedAttributes.'
    },
    insertText: '<vanilla-with-observed-attributes $1>' +
        '</vanilla-with-observed-attributes>$0',
    insertTextFormat: InsertTextFormat.Snippet,
    kind: CompletionItemKind.Class,
    label: '<vanilla-with-observed-attributes>',
    filterText: 'vanillawithobservedattributes',
  },
];

// Like elementCompletions, but without leading `<` characters.
const elementTagnameCompletions = elementCompletions.map((ec) => {
  return {...ec, insertText: ec.insertText!.slice(1)};
});

const elementCompletionsWithPlainDescriptions = elementCompletions.map((ec) => {
  return {...ec, documentation: (ec.documentation as MarkupContent).value};
});

const attributeCompletions: CompletionItem[] = [
  {
    label: 'local-property',
    documentation: {
      kind: 'markdown',
      value: 'A property defined directly on behavior-test-elem.',
    },
    kind: CompletionItemKind.Field,
    detail: '{boolean | null | undefined}',
    sortText: 'aaa-local-property',
  },
  {
    label: 'non-notifying-property',
    documentation: {kind: 'markdown', value: ''},
    kind: CompletionItemKind.Field,
    detail: '{string | null | undefined}',
    sortText: 'aaa-non-notifying-property',
  },
  {
    label: 'notifying-property',
    documentation: {kind: 'markdown', value: ''},
    kind: CompletionItemKind.Field,
    detail: '{string | null | undefined}',
    sortText: 'aaa-notifying-property',

  },
  {
    label: 'deeply-inherited-property',
    documentation: {
      kind: 'markdown',
      value: 'This is a deeply inherited property.',
    },
    kind: CompletionItemKind.Field,
    detail: '{Array | null | undefined} ⊃ MyNamespace.SubBehavior',
    sortText: 'ddd-deeply-inherited-property',
  },
  {
    label: 'inherit-please',
    documentation: {
      kind: 'markdown',
      value: 'A property provided by SimpleBehavior.',
    },
    kind: CompletionItemKind.Field,
    detail: '{number | null | undefined} ⊃ MyNamespace.SimpleBehavior',
    sortText: 'ddd-inherit-please',
  },
  {
    label: 'on-local-property-changed',
    documentation: {
      kind: 'markdown',
      value: 'Fired when the `localProperty` property changes.'
    },
    kind: CompletionItemKind.Field,
    detail: '{CustomEvent}',
    sortText: 'eee-aaa-on-local-property-changed',
  },
  {
    label: 'on-notifying-property-changed',
    documentation: {
      kind: 'markdown',
      value: 'Fired when the `notifyingProperty` property changes.'
    },
    kind: CompletionItemKind.Field,
    detail: '{CustomEvent}',
    sortText: 'eee-aaa-on-notifying-property-changed',
  },
  {
    label: 'on-deeply-inherited-property-changed',
    documentation: {
      kind: 'markdown',
      value: 'Fired when the `deeplyInheritedProperty` property changes.'
    },
    kind: CompletionItemKind.Field,
    detail: '{CustomEvent} ⊃ MyNamespace.SubBehavior',
    sortText: 'eee-ddd-on-deeply-inherited-property-changed',
  },
  {
    label: 'on-inherit-please-changed',
    documentation: {
      kind: 'markdown',
      value: 'Fired when the `inheritPlease` property changes.'
    },
    kind: CompletionItemKind.Field,
    detail: '{CustomEvent} ⊃ MyNamespace.SimpleBehavior',
    sortText: 'eee-ddd-on-inherit-please-changed',
  },
];

// TODO(https://github.com/Polymer/tools/issues/170): these tests are slightly
//     flaky, skip for now.
suite.skip('AutoCompleter', () => {
  const indexFile = path.join('editor-service', 'index.html');
  const indexContents = readFileSync(path.join(fixtureDir, indexFile), 'utf-8');
  const tagPosition = {line: 7, column: 9};
  const tagPositionEnd = {line: 7, column: 21};
  const localAttributePosition = {line: 7, column: 31};

  test('Get element completions for an empty text region', async() => {
    const {client} = await createTestEnvironment({fixtureDir});
    await client.openFile(indexFile);
    const completions =
        await client.getCompletions(indexFile, {line: 0, column: 0});
    assert.deepEqual(
        completions, {isIncomplete: false, items: elementCompletions});
    await client.cleanup();
  });

  let testName = `Doesn't send down markdown if the client doesn't support it`;
  test(testName, async() => {
    const capabilities = clone(defaultClientCapabilities);
    capabilities.textDocument!.completion!.completionItem! = {
      ...(capabilities.textDocument!.completion!.completionItem!),
      documentationFormat: undefined
    };

    const {client} = await createTestEnvironment({fixtureDir, capabilities});
    await client.openFile(indexFile);
{'fraction_non_alphanumeric': 0.14038255751738898, 'fraction_numerical': 0.003544676297485286, 'mean_word_length': 3.870684039087948, 'pattern_counts': {'":': 0, '<': 47, '<?xml version=': 0, '>': 55, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '133161', 'n_tokens_mistral': 4570, 'n_tokens_neox': 4429, 'n_words': 1028}