]> git.madduck.net Git - etc/vim.git/blobdiff - .vim/bundle/ale/test/test_code_action.vader

madduck's git repository

Every one of the projects in this repository is available at the canonical URL git://git.madduck.net/madduck/pub/<projectpath> — see each project's metadata for the exact URL.

All patches and comments are welcome. Please squash your changes to logical commits before using git-format-patch and git-send-email to patches@git.madduck.net. If you'd read over the Git project's submission guidelines and adhered to them, I'd be especially grateful.

SSH access, as well as push access can be individually arranged.

If you use my repositories frequently, consider adding the following snippet to ~/.gitconfig and using the third clone URL listed for each project:

[url "git://git.madduck.net/madduck/"]
  insteadOf = madduck:

Merge commit '76265755a1add77121c8f9dabb3e9bb70fe9a972' as '.vim/bundle/ale'
[etc/vim.git] / .vim / bundle / ale / test / test_code_action.vader
diff --git a/.vim/bundle/ale/test/test_code_action.vader b/.vim/bundle/ale/test/test_code_action.vader
new file mode 100644 (file)
index 0000000..80e2b1d
--- /dev/null
@@ -0,0 +1,605 @@
+Before:
+  let g:notified_changes = []
+
+  runtime autoload/ale/lsp.vim
+
+  function! ale#lsp#NotifyForChanges(conn_id, buffer) abort
+    call add(g:notified_changes, {
+    \ 'conn_id': a:conn_id,
+    \ 'buffer': a:buffer
+    \})
+  endfunction
+
+  Save g:ale_enabled
+  let g:ale_enabled = 0
+
+  let g:file1 = tempname()
+  let g:file2 = tempname()
+  let g:test = {}
+
+  let g:test.create_change = {line, offset, end_line, end_offset, value ->
+  \{
+  \   'changes': [{
+  \      'fileName': g:file1,
+  \      'textChanges': [{
+  \        'start': {
+  \          'line': line,
+  \          'offset': offset,
+  \        },
+  \        'end': {
+  \          'line': end_line,
+  \          'offset': end_offset,
+  \        },
+  \        'newText': value,
+  \      }],
+  \   }]
+  \}}
+
+  function! WriteFileAndEdit() abort
+    let g:test.text = [
+    \ 'class Name {',
+    \ '  value: string',
+    \ '}',
+    \]
+    call writefile(g:test.text, g:file1, 'S')
+    execute 'edit ' . g:file1
+  endfunction!
+
+After:
+  " Close the extra buffers if we opened it.
+  if bufnr(g:file1) != -1 && buflisted(bufnr(g:file1))
+    execute ':bp! | :bd! ' . bufnr(g:file1)
+  endif
+  if bufnr(g:file2) != -1 && buflisted(bufnr(g:file2))
+    execute ':bp! | :bd! ' . bufnr(g:file2)
+  endif
+
+  if filereadable(g:file1)
+    call delete(g:file1)
+  endif
+  if filereadable(g:file2)
+    call delete(g:file2)
+  endif
+
+  unlet! g:notified_changes
+  " unlet! g:expected_notified_changes
+  unlet! g:file1
+  unlet! g:file2
+  unlet! g:test
+  unlet! g:changes
+  delfunction WriteFileAndEdit
+
+  runtime autoload/ale/lsp.vim
+
+  Restore
+
+
+Execute(It should modify and save multiple files):
+  call writefile([
+  \ 'class Name {',
+  \ '  value: string',
+  \ '}',
+  \ '',
+  \ 'class B {',
+  \ '  constructor(readonly a: Name) {}',
+  \ '}'
+  \], g:file1, 'S')
+  call writefile([
+  \ 'import A from "A"',
+  \ 'import {',
+  \ '  B,',
+  \ '  C,',
+  \ '} from "module"',
+  \ 'import D from "D"',
+  \], g:file2, 'S')
+
+  call ale#code_action#HandleCodeAction(
+  \ {
+  \   'changes': [{
+  \      'fileName': g:file1,
+  \      'textChanges': [{
+  \        'start': {
+  \          'line': 1,
+  \          'offset': 7,
+  \        },
+  \        'end': {
+  \          'line': 1,
+  \          'offset': 11,
+  \        },
+  \        'newText': 'Value',
+  \      }, {
+  \        'start': {
+  \          'line': 6,
+  \          'offset': 27,
+  \        },
+  \        'end': {
+  \          'line': 6,
+  \          'offset': 31,
+  \        },
+  \        'newText': 'Value',
+  \      }],
+  \   }, {
+  \     'fileName': g:file2,
+  \     'textChanges': [{
+  \       'start': {
+  \         'line': 2,
+  \         'offset': 1,
+  \       },
+  \       'end': {
+  \         'line': 6,
+  \         'offset': 1,
+  \       },
+  \       'newText': "import {A, B} from 'module'\n\n",
+  \     }]
+  \   }],
+  \ },
+  \ {'should_save': 1, 'conn_id': 'test_conn'},
+  \)
+
+  AssertEqual [
+  \ 'class Value {',
+  \ '  value: string',
+  \ '}',
+  \ '',
+  \ 'class B {',
+  \ '  constructor(readonly a: Value) {}',
+  \ '}',
+  \ '',
+  \], readfile(g:file1, 'b')
+
+  AssertEqual [
+  \ 'import A from "A"',
+  \ 'import {A, B} from ''module''',
+  \ '',
+  \ 'import D from "D"',
+  \ '',
+  \], readfile(g:file2, 'b')
+
+  AssertEqual [{
+  \ 'conn_id': 'test_conn',
+  \ 'buffer': bufnr(g:file1),
+  \}, {
+  \ 'conn_id': 'test_conn',
+  \ 'buffer': bufnr(g:file2),
+  \}], g:notified_changes
+
+Execute(Beginning of file can be modified):
+  let g:test.text = [
+  \ 'class Name {',
+  \ '  value: string',
+  \ '}',
+  \]
+  call writefile(g:test.text, g:file1, 'S')
+
+  call ale#code_action#HandleCodeAction(
+  \ {
+  \   'changes': [{
+  \      'fileName': g:file1,
+  \      'textChanges': [{
+  \        'start': {
+  \          'line': 1,
+  \          'offset': 1,
+  \        },
+  \        'end': {
+  \          'line': 1,
+  \          'offset': 1,
+  \        },
+  \        'newText': "type A: string\ntype B: number\n",
+  \      }],
+  \   }]
+  \ },
+  \ {'should_save': 1, 'conn_id': 'test_conn'},
+  \)
+
+  AssertEqual [
+  \  'type A: string',
+  \  'type B: number',
+  \] + g:test.text + [''], readfile(g:file1, 'b')
+
+  AssertEqual [{
+  \ 'conn_id': 'test_conn',
+  \ 'buffer': bufnr(g:file1),
+  \}], g:notified_changes
+
+
+Execute(End of file can be modified):
+  let g:test.text = [
+  \ 'class Name {',
+  \ '  value: string',
+  \ '}',
+  \]
+  call writefile(g:test.text, g:file1, 'S')
+
+  call ale#code_action#HandleCodeAction(
+  \ {
+  \   'changes': [{
+  \    'fileName': g:file1,
+  \    'textChanges': [{
+  \      'start': {
+  \        'line': 4,
+  \        'offset': 1,
+  \      },
+  \      'end': {
+  \        'line': 4,
+  \        'offset': 1,
+  \      },
+  \      'newText': "type A: string\ntype B: number\n",
+  \     }],
+  \   }]
+  \ },
+  \ {'should_save': 1, 'conn_id': 'test_conn'},
+  \)
+
+  AssertEqual g:test.text + [
+  \  'type A: string',
+  \  'type B: number',
+  \  '',
+  \], readfile(g:file1, 'b')
+
+  AssertEqual [{
+  \ 'conn_id': 'test_conn',
+  \ 'buffer': bufnr(g:file1),
+  \}], g:notified_changes
+
+
+Execute(Current buffer contents will be reloaded):
+  let g:test.text = [
+  \ 'class Name {',
+  \ '  value: string',
+  \ '}',
+  \]
+  call writefile(g:test.text, g:file1, 'S')
+
+  execute 'edit ' . g:file1
+  let g:test.buffer = bufnr(g:file1)
+
+  call ale#code_action#HandleCodeAction(
+  \ {
+  \   'changes': [{
+  \      'fileName': g:file1,
+  \      'textChanges': [{
+  \        'start': {
+  \          'line': 1,
+  \          'offset': 1,
+  \        },
+  \        'end': {
+  \          'line': 1,
+  \          'offset': 1,
+  \        },
+  \        'newText': "type A: string\ntype B: number\n",
+  \      }],
+  \   }]
+  \ },
+  \ {'should_save': 1, 'conn_id': 'test_conn'},
+  \)
+
+  AssertEqual [
+  \  'type A: string',
+  \  'type B: number',
+  \] + g:test.text + [''], readfile(g:file1, 'b')
+
+  AssertEqual [
+  \  'type A: string',
+  \  'type B: number',
+  \] + g:test.text, getbufline(g:test.buffer, 1, '$')
+
+  AssertEqual [{
+  \ 'conn_id': 'test_conn',
+  \ 'buffer': bufnr(g:file1),
+  \}], g:notified_changes
+
+
+Execute(Unlisted buffer contents will be modified correctly):
+  let g:test.text = [
+  \ 'class Name {',
+  \ '  value: string',
+  \ '}',
+  \]
+  call writefile(g:test.text, g:file1, 'S')
+
+  execute 'edit ' . g:file1
+  let g:test.buffer = bufnr(g:file1)
+
+  execute 'bd'
+  AssertEqual bufnr(g:file1), g:test.buffer
+
+  call ale#code_action#HandleCodeAction(
+  \ {
+  \   'changes': [{
+  \      'fileName': g:file1,
+  \      'textChanges': [{
+  \        'start': {
+  \          'line': 1,
+  \          'offset': 1,
+  \        },
+  \        'end': {
+  \          'line': 1,
+  \          'offset': 1,
+  \        },
+  \        'newText': "type A: string\ntype B: number\n",
+  \      }],
+  \   }]
+  \ },
+  \ {'should_save': 1, 'conn_id': 'test_conn'},
+  \)
+
+  AssertEqual [
+  \  'type A: string',
+  \  'type B: number',
+  \] + g:test.text + [''], readfile(g:file1, 'b')
+
+  AssertEqual [{
+  \ 'conn_id': 'test_conn',
+  \ 'buffer': bufnr(g:file1),
+  \}], g:notified_changes
+
+# Tests for cursor repositioning. In comments `=` designates change range, and
+# `C` cursor position
+
+#     C ===
+Execute(Cursor will not move when it is before text change):
+  call WriteFileAndEdit()
+  let g:test.changes = g:test.create_change(2, 3, 2, 8, 'value2')
+
+  call setpos('.', [0, 1, 1, 0])
+  call ale#code_action#HandleCodeAction(g:test.changes, {
+  \ 'should_save': 1,
+  \ 'conn_id': 'test_conn',
+  \})
+  AssertEqual [1, 1], getpos('.')[1:2]
+
+  AssertEqual [{
+  \ 'conn_id': 'test_conn',
+  \ 'buffer': bufnr(''),
+  \}], g:notified_changes
+
+  call setpos('.', [0, 2, 2, 0])
+  call ale#code_action#HandleCodeAction(g:test.changes, {
+  \ 'should_save': 1,
+  \ 'conn_id': 'test_conn',
+  \})
+  AssertEqual [2, 2], getpos('.')[1:2]
+
+  AssertEqual [{
+  \ 'conn_id': 'test_conn',
+  \ 'buffer': bufnr(''),
+  \}, {
+  \ 'conn_id': 'test_conn',
+  \ 'buffer': bufnr(''),
+  \}], g:notified_changes
+
+# ====C====
+Execute(Cursor column will move to the change end when cursor between start/end):
+  let g:test.changes = g:test.create_change(2, 3, 2, 8, 'value2')
+
+  for r in range(3, 8)
+    call WriteFileAndEdit()
+    call setpos('.', [0, 2, r, 0])
+    AssertEqual '  value: string', getline('.')
+    call ale#code_action#HandleCodeAction(g:test.changes, {
+    \ 'should_save': 1,
+    \ 'conn_id': 'test_conn',
+    \})
+    AssertEqual '  value2: string', getline('.')
+    AssertEqual [2, 9], getpos('.')[1:2]
+  endfor
+
+  AssertEqual [{
+  \ 'conn_id': 'test_conn',
+  \ 'buffer': bufnr(''),
+  \}, {
+  \ 'conn_id': 'test_conn',
+  \ 'buffer': bufnr(''),
+  \}, {
+  \ 'conn_id': 'test_conn',
+  \ 'buffer': bufnr(''),
+  \}, {
+  \ 'conn_id': 'test_conn',
+  \ 'buffer': bufnr(''),
+  \}, {
+  \ 'conn_id': 'test_conn',
+  \ 'buffer': bufnr(''),
+  \}, {
+  \ 'conn_id': 'test_conn',
+  \ 'buffer': bufnr(''),
+  \}], g:notified_changes
+
+
+# ====C
+Execute(Cursor column will move back when new text is shorter):
+  call WriteFileAndEdit()
+  call setpos('.', [0, 2, 8, 0])
+  AssertEqual '  value: string', getline('.')
+  call ale#code_action#HandleCodeAction(
+  \ g:test.create_change(2, 3, 2, 8, 'val'),
+  \ {
+  \   'should_save': 1,
+  \   'conn_id': 'test_conn',
+  \ })
+  AssertEqual '  val: string', getline('.')
+  AssertEqual [2, 6], getpos('.')[1:2]
+
+  AssertEqual [{
+  \ 'conn_id': 'test_conn',
+  \ 'buffer': bufnr(''),
+  \}], g:notified_changes
+
+
+# ==== C
+Execute(Cursor column will move forward when new text is longer):
+  call WriteFileAndEdit()
+
+  call setpos('.', [0, 2, 8, 0])
+  AssertEqual '  value: string', getline('.')
+  call ale#code_action#HandleCodeAction(
+  \ g:test.create_change(2, 3, 2, 8, 'longValue'),
+  \ {
+  \   'should_save': 1,
+  \   'conn_id': 'test_conn',
+  \ })
+  AssertEqual '  longValue: string', getline('.')
+  AssertEqual [2, 12], getpos('.')[1:2]
+
+  AssertEqual [{
+  \ 'conn_id': 'test_conn',
+  \ 'buffer': bufnr(''),
+  \}], g:notified_changes
+
+# =========
+# =
+# C
+Execute(Cursor line will move when updates are happening on lines above):
+  call WriteFileAndEdit()
+  call setpos('.', [0, 3, 1, 0])
+  AssertEqual '}', getline('.')
+  call ale#code_action#HandleCodeAction(
+  \ g:test.create_change(1, 1, 2, 1, "test\ntest\n"),
+  \ {
+  \   'should_save': 1,
+  \   'conn_id': 'test_conn',
+  \ })
+  AssertEqual '}', getline('.')
+  AssertEqual [4, 1], getpos('.')[1:2]
+
+  AssertEqual [{
+  \ 'conn_id': 'test_conn',
+  \ 'buffer': bufnr(''),
+  \}], g:notified_changes
+
+
+# =========
+# =C
+Execute(Cursor line and column will move when change on lines above and just before cursor column):
+  call WriteFileAndEdit()
+  call setpos('.', [0, 2, 2, 0])
+  AssertEqual '  value: string', getline('.')
+  call ale#code_action#HandleCodeAction(
+  \ g:test.create_change(1, 1, 2, 1, "test\ntest\n123"),
+  \ {
+  \   'should_save': 1,
+  \   'conn_id': 'test_conn',
+  \ })
+  AssertEqual '123  value: string', getline('.')
+  AssertEqual [3, 5], getpos('.')[1:2]
+
+  AssertEqual [{
+  \ 'conn_id': 'test_conn',
+  \ 'buffer': bufnr(''),
+  \}], g:notified_changes
+
+# =========
+# ======C==
+# =
+Execute(Cursor line and column will move at the end of changes):
+  call WriteFileAndEdit()
+  call setpos('.', [0, 2, 10, 0])
+  AssertEqual '  value: string', getline('.')
+  call ale#code_action#HandleCodeAction(
+  \ g:test.create_change(1, 1, 3, 1, "test\n"),
+  \ {
+  \   'should_save': 1,
+  \   'conn_id': 'test_conn',
+  \ })
+  AssertEqual '}', getline('.')
+  AssertEqual [2, 1], getpos('.')[1:2]
+
+  AssertEqual [{
+  \ 'conn_id': 'test_conn',
+  \ 'buffer': bufnr(''),
+  \}], g:notified_changes
+
+#      C ==
+# ===
+Execute(Cursor will not move when changes happening on lines >= cursor, but after cursor):
+  call WriteFileAndEdit()
+  call setpos('.', [0, 2, 3, 0])
+  AssertEqual '  value: string', getline('.')
+  call ale#code_action#HandleCodeAction(
+  \ g:test.create_change(2, 10, 3, 1, "number\n"),
+  \ {
+  \   'should_save': 1,
+  \   'conn_id': 'test_conn',
+  \ })
+  AssertEqual '  value: number', getline('.')
+  AssertEqual [2, 3], getpos('.')[1:2]
+
+  AssertEqual [{
+  \ 'conn_id': 'test_conn',
+  \ 'buffer': bufnr(''),
+  \}], g:notified_changes
+
+Execute(Cursor will not move when change covers entire file):
+  call WriteFileAndEdit()
+  call setpos('.', [0, 2, 3, 0])
+  call ale#code_action#HandleCodeAction(
+  \ g:test.create_change(1, 1, len(g:test.text) + 1, 1,
+  \   join(g:test.text + ['x'], "\n")),
+  \ {
+  \   'should_save': 1,
+  \   'conn_id': 'test_conn',
+  \ })
+  AssertEqual [2, 3], getpos('.')[1:2]
+
+  AssertEqual [{
+  \ 'conn_id': 'test_conn',
+  \ 'buffer': bufnr(''),
+  \}], g:notified_changes
+
+Execute(It should just modify file when should_save is set to v:false):
+  call WriteFileAndEdit()
+  let g:test.change = g:test.create_change(1, 1, 1, 1, "import { writeFile } from 'fs';\n")
+  call ale#code_action#HandleCodeAction(g:test.change, {
+  \ 'conn_id': 'test_conn',
+  \})
+  AssertEqual 1, getbufvar(bufnr(''), '&modified')
+  AssertEqual [
+  \ 'import { writeFile } from ''fs'';',
+  \ 'class Name {',
+  \ '  value: string',
+  \ '}',
+  \], getline(1, '$')
+
+  AssertEqual [{
+  \ 'conn_id': 'test_conn',
+  \ 'buffer': bufnr(''),
+  \}], g:notified_changes
+
+Given typescript(An example TypeScript file):
+  type Foo = {}
+
+  export interface ISomething {
+    fooLongName: Foo | null
+  }
+
+  export class SomethingElse implements ISomething {
+    // Bindings
+    fooLongName!: ISomething['fooLongName']
+  }
+
+Execute():
+  let g:changes = [
+  \ {'end': {'offset': 14, 'line': 4}, 'newText': 'foo', 'start': {'offset': 3, 'line': 4}},
+  \ {'end': {'offset': 40, 'line': 9}, 'newText': 'foo', 'start': {'offset': 29, 'line': 9}},
+  \ {'end': {'offset': 14, 'line': 9}, 'newText': 'foo', 'start': {'offset': 3, 'line': 9}},
+  \]
+
+  call ale#code_action#ApplyChanges(expand('%:p'), g:changes, {
+  \ 'conn_id': 'test_conn',
+  \})
+
+  AssertEqual [{
+  \ 'conn_id': 'test_conn',
+  \ 'buffer': bufnr(''),
+  \}], g:notified_changes
+
+Expect(The changes should be applied correctly):
+  type Foo = {}
+
+  export interface ISomething {
+    foo: Foo | null
+  }
+
+  export class SomethingElse implements ISomething {
+    // Bindings
+    foo!: ISomething['foo']
+  }