Skip to content

Instantly share code, notes, and snippets.

@hjdivad
Last active August 28, 2018 16:57
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hjdivad/ea726b2caac4a8385788 to your computer and use it in GitHub Desktop.
Save hjdivad/ea726b2caac4a8385788 to your computer and use it in GitHub Desktop.

Ember-QUnit Testing With Vim

It can be tedious (and slow) to go from a test in your editor to running that test in the browser. This is a process to speed this up slightly. When it's set up you'll be able to run an individual test by:

  1. put your cursor inside a test body
  2. hit T
  3. switch to chrome
  4. type 'test ' (sans quotes), paste your clipboard and hit enter

If you switch apps quickly (via ⌘ - tab or alfred or something) this can be a pretty quick process.

Screencast

There are four steps to getting this set up.

1. Create a Custom Search Engine For Module Testing

Create a custom search engine in Chrome. You want a URL something like:

http://localhost:4200/tests?nojshint=true&module=%s

If you use a keyword mtest you can now run a module's test suite by typing mtest MODULE_NAME in chrome's address bar.

2. Create a Custom Search Engine For Individual Test Testing

Create a custom search engine in Chrome. You want a URL something like:

http://localhost:4200/tests?nojshint=true&testId=%S

If you use a keyword test you can now run an individual test by typing test TEST_ID in chrome's address bar.

3. Download qunit-test-hash and put it in your path.

#!/usr/bin/env node

var argv = process.argv;

function generateHash( module, testName ) {
	var hex,
		i = 0,
		hash = 0,
		str = module + "\x1C" + testName,
		len = str.length;

	for ( ; i < len; i++ ) {
		hash  = ( ( hash << 5 ) - hash ) + str.charCodeAt( i );
		hash |= 0;
	}

	// Convert the possibly negative integer hash code into an 8 character hex string, which isn't
	// strictly necessary but increases user understanding that the id is a SHA-like hash
	hex = ( 0x100000000 + hash ).toString( 16 );
	if ( hex.length < 8 ) {
		hex = "0000000" + hex;
	}

	return hex.slice( -8 );
}


if (argv.length !== 4) {
  console.error("usage: qunit-test-hash MODULE TEST");
  process.exit(1);
} else {
  console.log(generateHash(argv[2], argv[3]));
}

4. Set up vim

You need to run some vimscript for your ember testing files. I recommend having a vimrc that checks for a project-local vimrc in the current working directory when it starts up.

You can check out my vimrc for an example.

If you have something like that, your project-local vimrc can include something like the following:

augroup ExtraTypes
  autocmd!
  autocmd BufNewFile,BufRead *-test.js set ft+=.ember-testing
augroup end

Then in $HOME/.vim/ftplugin/ember-testing.vim (or equivalent).

if !exists("*s:YankTestId")
  function s:GetTestName()
    let [_, x, y,_] = getpos('.') "get cursor position
    call cursor(x, 200) "move to 'end of line' in case we're on a test line at the first char position
    let test_line = search('^test', 'b')
    let [_, test_name_start_y] = searchpos("['\"]", 'n', line('.'))

    " grab the name of the test
    let test_line=getline('.')
    let test_string_delim = test_line[test_name_start_y-1]
    call cursor(test_line, test_name_start_y)
    let [_, test_name_end_y] = searchpos(test_string_delim, 'n', line('.'))
    let test_name_len = test_name_end_y - test_name_start_y - 1


    let test_name=strpart(test_line, test_name_start_y, test_name_len)

    " restore cursor
    call cursor(x,y)

    return test_name
  endfunction

  function s:YankTestId()
    let test_name=s:GetTestName()
    let module_name=s:GetModuleName()

    let test_arg=shellescape(test_name)
    let module_arg=shellescape(module_name)
    let test_id=system("qunit-test-hash " . module_arg . " " . test_arg)
    let @+= test_id
  endfunction
endif

if !exists("*s:YankModuleName")
  function s:GetModuleName()
    let [_, x, y,_] = getpos('.') "get cursor position
    call cursor(x, 200) "move to 'end of line' in case we're on a test line at the first char position
    let module_line = search('^module', 'b')
    let [_, module_name_start_y] = searchpos("['\"]", 'n', line('.'))

    " grab the name of the test
    let module_line=getline('.')
    let module_string_delim = module_line[module_name_start_y-1]
    call cursor(module_line, module_name_start_y)
    let [_, module_name_end_y] = searchpos("['\"]", 'n', line('.'))
    let module_name_len = module_name_end_y - module_name_start_y - 1

    let module_name=strpart(module_line, module_name_start_y, module_name_len)

    if match(module_line, 'moduleForComponent') != -1
      let module_name='component:' . module_name
    endif

    " restore cursor
    call cursor(x,y)

    return module_name
  endfunction

  function s:YankModuleName()
    let @+= s:GetModuleName()
  endfunction
endif

nmap <buffer> T :call <SID>YankTestId()<CR>
nmap <buffer> M :call <SID>YankModuleName()<CR>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment