├── features ├── stubs │ ├── ansi-table-test.js │ ├── passing-tests │ └── failing-tests ├── run-all-tests.feature ├── support │ └── env.el ├── toggle-focus-rocket.feature ├── step-definitions │ └── basic-steps.el └── toggle-deferred.feature ├── .gitmodules ├── README.md ├── watch-tests.watchr ├── buster-test └── buster-mode.el /features/stubs/ansi-table-test.js: -------------------------------------------------------------------------------- 1 | Line 1 2 | Line 2 3 | Line 3: Hello world 4 | Line 4 5 | Line 5 6 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "util/ecukes"] 2 | path = util/ecukes 3 | url = https://github.com/rejeep/ecukes.git 4 | [submodule "util/espuds"] 5 | path = util/espuds 6 | url = https://github.com/rejeep/espuds.git 7 | -------------------------------------------------------------------------------- /features/run-all-tests.feature: -------------------------------------------------------------------------------- 1 | Feature: Run all tests 2 | 3 | Scenario: Opens a buffer with passing test results 4 | When I turn on buster-mode 5 | And I have passing tests 6 | And I press "C-c C-b ra" 7 | And I wait for the compilation to finish 8 | And I switch to buffer "*buster-test*" 9 | Then I should see "17 tests, 19 assertions, 1 runtime ... OK" 10 | And I should not see "" 11 | 12 | Scenario: Navigate to first error with failing test 13 | When I turn on buster-mode 14 | And I have failing tests 15 | And I press "C-c C-b ra" 16 | And I wait for the compilation to finish 17 | And I press "M-g M-n" 18 | Then I should see ": Hello world" 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # buster-mode 2 | 3 | buster-mode is a minor mode for emacs to speed up development when writing tests 4 | with [Buster.js](http://busterjs.org). 5 | 6 | A work in progress. You can watch us livecode it on http://emacsrocks.com 7 | 8 | ## Keybinding 9 | 10 | All keybindings in buster-mode start with `C-c C-b` and then a two-letter mnemonic shortcut. 11 | 12 | * `td`: toggle-deferred will toggle // in the name of the current test. 13 | * `tf`: toggle-focus-rocket will toggle => in the name of the current test. 14 | * `ra`: run-all-tests 15 | 16 | ## Development 17 | 18 | To fetch the test dependencies: 19 | 20 | $ cd /path/to/buster-mode 21 | $ git submodule init 22 | $ git submodule update 23 | 24 | Run the tests with: 25 | 26 | $ ./util/ecukes/ecukes features 27 | -------------------------------------------------------------------------------- /features/support/env.el: -------------------------------------------------------------------------------- 1 | (let* ((current-directory (file-name-directory load-file-name)) 2 | (features-directory (expand-file-name ".." current-directory)) 3 | (project-directory (expand-file-name ".." features-directory))) 4 | (setq buster-mode-root-path project-directory) 5 | (setq buster-mode-util-path (expand-file-name "util" project-directory))) 6 | 7 | (add-to-list 'load-path buster-mode-root-path) 8 | (add-to-list 'load-path (expand-file-name "espuds" buster-mode-util-path)) 9 | 10 | (require 'buster-mode) 11 | (require 'espuds) 12 | (require 'ert) 13 | 14 | (Before 15 | (switch-to-buffer 16 | (get-buffer-create "*testing-buffer*")) 17 | (erase-buffer) 18 | (transient-mark-mode 1) 19 | (cua-mode 0) 20 | (buster-mode 0) 21 | (setq set-mark-default-inactive nil) 22 | (deactivate-mark)) 23 | 24 | (After) 25 | -------------------------------------------------------------------------------- /features/stubs/passing-tests: -------------------------------------------------------------------------------- 1 | Running tests ... 2 | Running 17 tests in 1 runtime ... 3 | Running 17 tests in 1 runtime ... 12% done 4 | Running 17 tests in 1 runtime ... 12% done 5 | Running 17 tests in 1 runtime ... 18% done 6 | Running 17 tests in 1 runtime ... 18% done 7 | Running 17 tests in 1 runtime ... 35% done 8 | Running 17 tests in 1 runtime ... 35% done 9 | Running 17 tests in 1 runtime ... 47% done 10 | Running 17 tests in 1 runtime ... 47% done 11 | Running 17 tests in 1 runtime ... 76% done 12 | Running 17 tests in 1 runtime ... 76% done 13 | Running 17 tests in 1 runtime ... 82% done 14 | Running 17 tests in 1 runtime ... 82% done 15 | 17 tests, 19 assertions, 1 runtime ... OK 16 | -------------------------------------------------------------------------------- /watch-tests.watchr: -------------------------------------------------------------------------------- 1 | ENV["WATCHR"] = "1" 2 | system 'clear' 3 | 4 | def run(cmd) 5 | `#{cmd}` 6 | end 7 | 8 | def run_all_tests 9 | system('clear') 10 | result = run "env PATH=.:$PATH ./util/ecukes/ecukes" 11 | puts result 12 | end 13 | 14 | def run_test(file) 15 | system('clear') 16 | result = run "env PATH=.:$PATH ./util/ecukes/ecukes #{file}" 17 | puts result 18 | end 19 | 20 | run_all_tests 21 | watch('.*.feature') { |file| run_test file } 22 | watch('.*.el') { run_all_tests } 23 | 24 | # Ctrl-\ 25 | Signal.trap 'QUIT' do 26 | puts " --- Running all tests ---\n\n" 27 | run_all_tests 28 | end 29 | 30 | @interrupted = false 31 | 32 | # Ctrl-C 33 | Signal.trap 'INT' do 34 | if @interrupted then 35 | @wants_to_quit = true 36 | abort("\n") 37 | else 38 | puts "Interrupt a second time to quit" 39 | @interrupted = true 40 | Kernel.sleep 1.5 41 | # raise Interrupt, nil # let the run loop catch it 42 | run_all_tests 43 | @interrupted = false 44 | end 45 | end 46 | -------------------------------------------------------------------------------- /features/toggle-focus-rocket.feature: -------------------------------------------------------------------------------- 1 | Feature: Toggle focus rocket 2 | 3 | Scenario: Focus test 4 | When I insert: 5 | """ 6 | buster.testCase('Building Page', { 7 | "contains title after loading page": function () { 8 | assert.match(document.body.innerHTML, "Zombie TDD"); 9 | } 10 | }); 11 | """ 12 | And I turn on buster-mode 13 | And I go to the front of the word "assert" 14 | And I press "C-c C-b tf" 15 | Then I should see "=> contains" 16 | 17 | Scenario: Blur test 18 | When I insert: 19 | """ 20 | buster.testCase('Building Page', { 21 | "=> contains title after loading page": function () { 22 | assert.match(document.body.innerHTML, "Zombie TDD"); 23 | } 24 | }); 25 | """ 26 | And I turn on buster-mode 27 | And I go to the front of the word "assert" 28 | And I press "C-c C-b tf" 29 | Then I should not see "=> contains" 30 | 31 | Scenario: Blur test even when user hasn't added a space at the end 32 | When I insert: 33 | """ 34 | buster.testCase('Building Page', { 35 | "=>contains title after loading page": function () { 36 | assert.match(document.body.innerHTML, "Zombie TDD"); 37 | } 38 | }); 39 | """ 40 | And I turn on buster-mode 41 | And I go to the front of the word "assert" 42 | And I press "C-c C-b tf" 43 | Then I should not see "=>contains" 44 | -------------------------------------------------------------------------------- /features/stubs/failing-tests: -------------------------------------------------------------------------------- 1 | Running tests ... 2 | Running 17 tests in 1 runtime ... 3 | Failure: ANSI table draws multi-line cells 4 | [refute.equals] """Something In this 5 | cell 6 | Other There is 7 | stuff 8 | " expected not to be equal to "Something In this 9 | cell 10 | Other There is 11 | stuff 12 | " 13 | at Object.buster.testCase.draws multi-line cells (./features/stubs/ansi-table-test.js:3:5) 14 | Running 17 tests in 1 runtime ... 6% done 15 | Running 17 tests in 1 runtime ... 12% done 16 | Running 17 tests in 1 runtime ... 12% done 17 | Running 17 tests in 1 runtime ... 35% done 18 | Running 17 tests in 1 runtime ... 35% done 19 | Running 17 tests in 1 runtime ... 47% done 20 | Running 17 tests in 1 runtime ... 47% done 21 | Running 17 tests in 1 runtime ... 53% done 22 | Running 17 tests in 1 runtime ... 53% done 23 | Running 17 tests in 1 runtime ... 59% done 24 | Running 17 tests in 1 runtime ... 59% done 25 | Running 17 tests in 1 runtime ... 88% done 26 | Running 17 tests in 1 runtime ... 88% done 27 | 17 tests, 18 assertions, 1 runtime ... 1 failure 28 | -------------------------------------------------------------------------------- /features/step-definitions/basic-steps.el: -------------------------------------------------------------------------------- 1 | (When "^I go to character \"\\(.+\\)\"$" 2 | (lambda (char) 3 | (goto-char (point-min)) 4 | (let ((search (re-search-forward (format "%s" char) nil t)) 5 | (message "Can not go to character '%s' since it does not exist in the current buffer: %s")) 6 | (assert search nil message char (espuds-buffer-contents))))) 7 | 8 | (When "^I go to the \\(front\\|end\\) of the word \"\\(.+\\)\"$" 9 | (lambda (pos word) 10 | (goto-char (point-min)) 11 | (let ((search (re-search-forward (format "%s" word) nil t)) 12 | (message "Can not go to character '%s' since it does not exist in the current buffer: %s")) 13 | (assert search nil message word (espuds-buffer-contents)) 14 | (if (string-equal "front" pos) (backward-word))))) 15 | 16 | (When "^I wait for the compilation to finish$" 17 | (lambda () 18 | (setq ecukes--waiting-for-compilation t) 19 | 20 | (defun ecukes--compilation-finished (&rest ignore) 21 | (setq ecukes--waiting-for-compilation nil) 22 | (remove-hook 'compilation-finish-functions 'ecukes--compilation-finished)) 23 | 24 | (add-hook 'compilation-finish-functions 'ecukes--compilation-finished) 25 | 26 | (while ecukes--waiting-for-compilation 27 | (accept-process-output nil 0.005)) 28 | )) 29 | 30 | (And "^I have passing tests$" 31 | (lambda () 32 | (setq buster-compile-command "cat features/stubs/passing-tests"))) 33 | 34 | (And "^I have failing tests$" 35 | (lambda () 36 | (setq buster-compile-command "cat features/stubs/failing-tests"))) 37 | -------------------------------------------------------------------------------- /features/toggle-deferred.feature: -------------------------------------------------------------------------------- 1 | Feature: Toggle deferred 2 | 3 | Scenario: Attempting to defer test outside buster-mode 4 | When I insert: 5 | """ 6 | buster.testCase('Building Page', { 7 | "contains title after loading page": function () { 8 | assert.match(document.body.innerHTML, "Zombie TDD"); 9 | } 10 | }); 11 | """ 12 | And I go to the front of the word "assert" 13 | And I press "C-c C-b td" 14 | Then I should not see "// contains" 15 | 16 | Scenario: Deferring a test 17 | When I insert: 18 | """ 19 | buster.testCase('Building Page', { 20 | "contains title after loading page": function () { 21 | assert.match(document.body.innerHTML, "Zombie TDD"); 22 | } 23 | }); 24 | """ 25 | And I turn on buster-mode 26 | And I go to the front of the word "assert" 27 | And I press "C-c C-b td" 28 | Then I should see "// contains" 29 | And the cursor should be before "assert" 30 | 31 | Scenario: Undeferring a test 32 | When I insert: 33 | """ 34 | buster.testCase('Building Page', { 35 | "// contains title after loading page": function () { 36 | assert.match(document.body.innerHTML, "Zombie TDD"); 37 | } 38 | }); 39 | """ 40 | And I turn on buster-mode 41 | And I go to the front of the word "assert" 42 | And I press "C-c C-b td" 43 | Then I should not see "// contains" 44 | 45 | Scenario: Deferring a single quoted test 46 | When I insert: 47 | """ 48 | buster.testCase('Building Page', { 49 | 'contains title after loading page': function () { 50 | assert.match(document.body.innerHTML, "Zombie TDD"); 51 | } 52 | }); 53 | """ 54 | And I turn on buster-mode 55 | And I go to the front of the word "assert" 56 | And I press "C-c C-b td" 57 | Then I should see "'// contains" 58 | -------------------------------------------------------------------------------- /buster-test: -------------------------------------------------------------------------------- 1 | echo "Configuration: ....... 2 | cleanReporter: ..... 3 | lintScanner: ..................... 4 | growlReporter: ........ 5 | jslint-linter: ............. 6 | lintReporter: ... 7 | watchForLint: .. 8 | newFileReporter: ..... 9 | pluralize: .. 10 | print: ...... 11 | summaryReporter: ........A. 12 | repository: ................. 13 | checkedFile: ............ 14 | 13 test cases, 110 tests, 148 assertions, 0 failures, 0 errors, 0 timeouts" 15 | -------------------------------------------------------------------------------- /buster-mode.el: -------------------------------------------------------------------------------- 1 | ;;; buster-mode.el --- Minor mode to speed up development when writing tests with Buster.js 2 | 3 | ;; Copyright (C) 2011 Magnar Sveen, Christian Johansen 4 | 5 | ;; Authors: Magnar Sveen 6 | ;; Christian Johansen 7 | ;; Keywords: buster testing javascript 8 | 9 | ;; This program is free software; you can redistribute it and/or modify 10 | ;; it under the terms of the GNU General Public License as published by 11 | ;; the Free Software Foundation, either version 3 of the License, or 12 | ;; (at your option) any later version. 13 | 14 | ;; This program is distributed in the hope that it will be useful, 15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | ;; GNU General Public License for more details. 18 | 19 | ;; You should have received a copy of the GNU General Public License 20 | ;; along with this program. If not, see . 21 | 22 | ;;; Commentary: 23 | 24 | ;; A work in progress. You can watch us livecode it on http://emacsrocks.com 25 | 26 | ;; All keybindings in buster-mode start with `C-c C-b` and then a two-letter mnemonic shortcut. 27 | 28 | ;; * `td`: toggle-deferred will toggle // in the name of the current test. 29 | ;; * `tf`: toggle-focus-rocket will toggle => in the name of the current test. 30 | ;; * `ra`: run-all-tests 31 | 32 | ;;; Code: 33 | 34 | (require 'compile) 35 | 36 | (defun buster-goto-current-test () 37 | (search-backward-regexp "[\"'][^ ]* .+[\"']: function" nil t)) 38 | 39 | (defun buster-toggle-test-name-prefix (prefix) 40 | (save-excursion 41 | (buster-goto-current-test) 42 | (forward-char 1) 43 | (if (not (looking-at prefix)) 44 | (insert prefix " ") 45 | (delete-char (length prefix)) 46 | (delete-horizontal-space)))) 47 | 48 | (defun buster-toggle-deferred () 49 | (interactive) 50 | (buster-toggle-test-name-prefix "//")) 51 | 52 | (defun buster-toggle-focus-rocket () 53 | (interactive) 54 | (buster-toggle-test-name-prefix "=>")) 55 | 56 | (defvar buster-compile-command "buster-test" 57 | "Command used to run Buster tests") 58 | 59 | (defun buster-run-all-tests () 60 | (interactive) 61 | (compile buster-compile-command t)) 62 | 63 | (defvar buster-mode-map (make-sparse-keymap) 64 | "buster-mode keymap") 65 | 66 | (define-key buster-mode-map 67 | (kbd "C-c C-b td") 'buster-toggle-deferred) 68 | (define-key buster-mode-map 69 | (kbd "C-c C-b tf") 'buster-toggle-focus-rocket) 70 | (define-key buster-mode-map 71 | (kbd "C-c C-b ra") 'buster-run-all-tests) 72 | 73 | (defun buster-mode--clean-up-ansi-mess (&rest ignore) 74 | (with-current-buffer (buster-mode--compilation-buffer-name) 75 | (save-excursion 76 | (goto-char (point-min)) 77 | (while (search-forward "" nil t) 78 | (delete-char -5) 79 | (delete-char (- (current-column))))))) 80 | 81 | (defun buster-mode--compilation-buffer-name (&rest ignore) 82 | "*buster-test*") 83 | 84 | (define-minor-mode buster-mode 85 | "Buster mode" nil " Buster" buster-mode-map 86 | (if buster-mode 87 | (progn 88 | (add-to-list 'compilation-error-regexp-alist '("(\\([^: ]+\\):\\([0-9]+\\):\\([0-9]+\\))" 1 2 3)) 89 | (set (make-local-variable 'compilation-buffer-name-function) 'buster-mode--compilation-buffer-name) 90 | (add-hook 'comint-output-filter-functions 'buster-mode--clean-up-ansi-mess t)) 91 | (remove-hook 'comint-output-filter-functions 'buster-mode--clean-up-ansi-mess))) 92 | 93 | (provide 'buster-mode) 94 | 95 | ;;; buster-mode.el ends here 96 | --------------------------------------------------------------------------------