;;; ruby-mode-tests.el --- Test suite for ruby-mode ;; Copyright (C) 2012-2013 Free Software Foundation, Inc. ;; This file is part of GNU Emacs. ;; GNU Emacs is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or ;; (at your option) any later version. ;; GNU Emacs is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs. If not, see . ;;; Commentary: ;;; Code: (require 'ruby-mode) (defun ruby-should-indent (content column) "Assert indentation COLUMN on the last line of CONTENT." (ruby-with-temp-buffer content (ruby-indent-line) (should (= (current-indentation) column)))) (defun ruby-should-indent-buffer (expected content) "Assert that CONTENT turns into EXPECTED after the buffer is re-indented. The whitespace before and including \"|\" on each line is removed." (ruby-with-temp-buffer (ruby-test-string content) (indent-region (point-min) (point-max)) (should (string= (ruby-test-string expected) (buffer-string))))) (defmacro ruby-with-temp-buffer (contents &rest body) (declare (indent 1) (debug t)) `(with-temp-buffer (insert ,contents) (ruby-mode) ,@body)) (defun ruby-test-string (s &rest args) (apply 'format (replace-regexp-in-string "^[ \t]*|" "" s) args)) (defun ruby-assert-state (content index value &optional point) "Assert syntax state values at the end of CONTENT. VALUES-PLIST is a list with alternating index and value elements." (ruby-with-temp-buffer content (when point (goto-char point)) (syntax-propertize (point)) (should (eq (nth index (parse-partial-sexp (point-min) (point))) value)))) (defun ruby-assert-face (content pos face) (ruby-with-temp-buffer content (font-lock-fontify-buffer) (should (eq face (get-text-property pos 'face))))) (ert-deftest ruby-indent-after-symbol-made-from-string-interpolation () "It can indent the line after symbol made using string interpolation." (ruby-should-indent "def foo(suffix)\n :\"bar#{suffix}\"\n" ruby-indent-level)) (ert-deftest ruby-indent-after-js-style-symbol-with-block-beg-name () "JS-style hash symbol can have keyword name." (ruby-should-indent "link_to \"home\", home_path, class: \"foo\"\n" 0)) (ert-deftest ruby-discern-singleton-class-from-heredoc () (ruby-assert-state "foo <
  • #{@files.join(\"
  • \")}
  • \"")) (ruby-assert-state s 8 nil) (ruby-assert-face s 9 font-lock-string-face) (ruby-assert-face s 10 font-lock-variable-name-face) (ruby-assert-face s 41 font-lock-string-face))) (ert-deftest ruby-interpolation-suppresses-one-double-quote () (let ((s "\"foo#{'\"'}\"")) (ruby-assert-state s 8 nil) (ruby-assert-face s 8 font-lock-variable-name-face) (ruby-assert-face s 11 font-lock-string-face))) (ert-deftest ruby-interpolation-suppresses-one-backtick () (let ((s "`as#{'`'}das`")) (ruby-assert-state s 8 nil))) (ert-deftest ruby-interpolation-keeps-non-quote-syntax () (let ((s "\"foo#{baz.tee}bar\"")) (ruby-with-temp-buffer s (goto-char (point-min)) (ruby-mode) (font-lock-fontify-buffer) (search-forward "tee") (should (string= (thing-at-point 'symbol) "tee"))))) (ert-deftest ruby-interpolation-inside-percent-literal () (let ((s "%( #{boo} )")) (ruby-assert-face s 1 font-lock-string-face) (ruby-assert-face s 4 font-lock-variable-name-face) (ruby-assert-face s 10 font-lock-string-face) (ruby-assert-state s 8 nil))) (ert-deftest ruby-interpolation-inside-percent-literal-with-paren () :expected-result :failed (let ((s "%(^#{\")\"}^)")) (ruby-assert-face s 3 font-lock-string-face) (ruby-assert-face s 4 font-lock-variable-name-face) (ruby-assert-face s 10 font-lock-string-face) ;; It's confused by the closing paren in the middle. (ruby-assert-state s 8 nil))) (ert-deftest ruby-add-log-current-method-examples () (let ((pairs '(("foo" . "#foo") ("C.foo" . ".foo") ("self.foo" . ".foo")))) (dolist (pair pairs) (let ((name (car pair)) (value (cdr pair))) (ruby-with-temp-buffer (ruby-test-string "module M | class C | def %s | _ | end | end |end" name) (search-backward "_") (forward-line) (should (string= (ruby-add-log-current-method) (format "M::C%s" value)))))))) (ert-deftest ruby-add-log-current-method-outside-of-method () (ruby-with-temp-buffer (ruby-test-string "module M | class C | def foo | end | _ | end |end") (search-backward "_") (should (string= (ruby-add-log-current-method)"M::C")))) (ert-deftest ruby-add-log-current-method-in-singleton-class () (ruby-with-temp-buffer (ruby-test-string "class C | class << self | def foo | _ | end | end |end") (search-backward "_") (should (string= (ruby-add-log-current-method) "C.foo")))) (ert-deftest ruby-add-log-current-method-namespace-shorthand () (ruby-with-temp-buffer (ruby-test-string "class C::D | def foo | _ | end |end") (search-backward "_") (should (string= (ruby-add-log-current-method) "C::D#foo")))) (ert-deftest ruby-add-log-current-method-after-inner-class () (ruby-with-temp-buffer (ruby-test-string "module M | class C | class D | end | def foo | _ | end | end |end") (search-backward "_") (should (string= (ruby-add-log-current-method) "M::C#foo")))) (defvar ruby-block-test-example (ruby-test-string "class C | def foo | 1 | end | | def bar | 2 | end | | def baz |some do |3 | end | end |end")) (defmacro ruby-deftest-move-to-block (name &rest body) `(ert-deftest ,(intern (format "ruby-move-to-block-%s" name)) () (with-temp-buffer (insert ruby-block-test-example) (ruby-mode) ,@body))) (put 'ruby-deftest-move-to-block 'lisp-indent-function 'defun) (ruby-deftest-move-to-block works-on-do (goto-line 11) (ruby-end-of-block) (should (= 13 (line-number-at-pos))) (ruby-beginning-of-block) (should (= 11 (line-number-at-pos)))) (ruby-deftest-move-to-block zero-is-noop (goto-line 5) (ruby-move-to-block 0) (should (= 5 (line-number-at-pos)))) (ruby-deftest-move-to-block ok-with-three (goto-line 2) (ruby-move-to-block 3) (should (= 14 (line-number-at-pos)))) (ruby-deftest-move-to-block ok-with-minus-two (goto-line 10) (ruby-move-to-block -2) (should (= 2 (line-number-at-pos)))) (ert-deftest ruby-move-to-block-skips-percent-literal () (dolist (s (list (ruby-test-string "foo do | a = %%w( | def yaa | ) |end") (ruby-test-string "foo do | a = %%w| | end | | |end"))) (ruby-with-temp-buffer s (goto-line 1) (ruby-end-of-block) (should (= 5 (line-number-at-pos))) (ruby-beginning-of-block) (should (= 1 (line-number-at-pos)))))) (ert-deftest ruby-move-to-block-skips-heredoc () (ruby-with-temp-buffer (ruby-test-string "if something_wrong? | ActiveSupport::Deprecation.warn(<<-eowarn) | boo hoo | end | eowarn |end") (goto-line 1) (ruby-end-of-block) (should (= 6 (line-number-at-pos))) (ruby-beginning-of-block) (should (= 1 (line-number-at-pos))))) (ert-deftest ruby-move-to-block-does-not-fold-case () (ruby-with-temp-buffer (ruby-test-string "foo do | Module.to_s |end") (end-of-buffer) (let ((case-fold-search t)) (ruby-beginning-of-block)) (should (= 1 (line-number-at-pos))))) (ert-deftest ruby-beginning-of-defun-does-not-fold-case () (ruby-with-temp-buffer (ruby-test-string "class C | def bar | Class.to_s | end |end") (goto-line 4) (let ((case-fold-search t)) (beginning-of-defun)) (should (= 2 (line-number-at-pos))))) (ert-deftest ruby-end-of-defun-skips-to-next-line-after-the-method () (ruby-with-temp-buffer (ruby-test-string "class D | def tee | 'ho hum' | end |end") (goto-line 2) (end-of-defun) (should (= 5 (line-number-at-pos))))) (provide 'ruby-mode-tests) ;;; ruby-mode-tests.el ends here