branch: elpa/projectile
commit 1c29f1bc235d0eaeba4988e87ac3e3be8d20bae4
Author: Bozhidar Batsov <[email protected]>
Commit: Bozhidar Batsov <[email protected]>
Consolidate the four --with-project test macros into one
The replace, replace-review, scan-async and search-review suites each
carried a near-identical --with-project macro (sandbox, create files,
truename'd root, native indexing, fresh caches, stubbed project-root).
Replace them with a single projectile-test-with-project in the shared
helpers.
Three suites now call it directly; the replace suite keeps its own thin
macro that delegates to the shared one and adds the smart-case bindings
(search-upper-case / case-replace) its case-sensitivity specs rely on.
No behavior change; 889 specs green, including the case-sensitivity specs.
---
test/projectile-replace-review-test.el | 100 +++++++++++----------------------
test/projectile-replace-test.el | 40 +++----------
test/projectile-scan-async-test.el | 54 +++++-------------
test/projectile-search-review-test.el | 80 ++++++++------------------
test/projectile-test-helpers.el | 35 ++++++++++++
5 files changed, 114 insertions(+), 195 deletions(-)
diff --git a/test/projectile-replace-review-test.el
b/test/projectile-replace-review-test.el
index fe46fb16d2..a9b168014c 100644
--- a/test/projectile-replace-review-test.el
+++ b/test/projectile-replace-review-test.el
@@ -30,38 +30,6 @@
(require 'projectile-test-helpers)
-(defmacro projectile-replace-review-test--with-project (files &rest body)
- "Evaluate BODY in a sandbox project containing FILES.
-
-FILES is a literal alist of (NAME . CONTENT) file specs created relative
-to the project root. A `.projectile' marker is created; include one in
-FILES to override its contents (e.g. to add ignore rules). BODY runs
-with `default-directory' at the root and `projectile-project-root'
-stubbed accordingly. Project buffers and the results buffer are killed
-afterwards."
- (declare (indent 1) (debug (sexp &rest form)))
- `(projectile-test-with-sandbox
- (make-directory "project" t)
- (with-temp-file "project/.projectile")
- ,@(mapcar (lambda (spec)
- `(progn
- (when-let* ((dir (file-name-directory ,(car spec))))
- (make-directory (expand-file-name dir "project") t))
- (with-temp-file (expand-file-name ,(car spec) "project")
- (insert ,(cdr spec)))))
- files)
- (let ((default-directory (file-name-as-directory
- (projectile-test-project-root)))
- (projectile-indexing-method 'native)
- (projectile-projects-cache (make-hash-table :test 'equal))
- (projectile-projects-cache-time (make-hash-table :test 'equal))
- (projectile-enable-caching nil)
- (case-fold-search t))
- (spy-on 'projectile-project-root :and-return-value default-directory)
- (unwind-protect
- (progn ,@body)
- (projectile-test-kill-project-buffers default-directory)))))
-
(defun projectile-replace-review-test--run (term replacement &optional
regexp-p)
"Drive the review command for TERM/REPLACEMENT and return the results buffer.
REGEXP-P selects `projectile-replace-regexp-review'."
@@ -90,7 +58,7 @@ REGEXP-P selects `projectile-replace-regexp-review'."
(describe "projectile-replace-review (literal)"
(it "finds every literal match and applies them to a file on disk"
- (projectile-replace-review-test--with-project
+ (projectile-test-with-project
(("a.txt" . "foo one foo\n")
("lib/b.txt" . "start foo end\n"))
(projectile-test-use-plain-grep)
@@ -106,7 +74,7 @@ REGEXP-P selects `projectile-replace-regexp-review'."
:to-equal "start bar end\n"))))
(it "applies multiple matches on one line in descending order"
- (projectile-replace-review-test--with-project
+ (projectile-test-with-project
(("m.txt" . "xx xx xx\n"))
(projectile-test-use-plain-grep)
(let ((buf (projectile-replace-review-test--run "xx" "yyy")))
@@ -117,7 +85,7 @@ REGEXP-P selects `projectile-replace-regexp-review'."
:to-equal "yyy yyy yyy\n"))))
(it "edits an already-open buffer in place rather than the file on disk"
- (projectile-replace-review-test--with-project
+ (projectile-test-with-project
(("open.txt" . "first foo\nlast foo\n"))
(projectile-test-use-plain-grep)
(find-file-noselect (expand-file-name "open.txt"))
@@ -134,7 +102,7 @@ REGEXP-P selects `projectile-replace-regexp-review'."
:to-equal "first bar\nlast bar\n"))))
(it "leaves a disabled match untouched and applies only the enabled ones"
- (projectile-replace-review-test--with-project
+ (projectile-test-with-project
(("t.txt" . "foo foo foo\n"))
(projectile-test-use-plain-grep)
(let ((buf (projectile-replace-review-test--run "foo" "bar")))
@@ -149,7 +117,7 @@ REGEXP-P selects `projectile-replace-regexp-review'."
(describe "projectile-replace-regexp-review"
(it "honors Emacs-only regexp constructs a shell regexp couldn't express"
- (projectile-replace-review-test--with-project
+ (projectile-test-with-project
;; \_< \_> are Emacs symbol boundaries: grep/rg cannot express them
(("s.txt" . "foo foobar barfoo foo\n"))
(let ((buf (projectile-replace-review-test--run "\\_<foo\\_>" "X"
'regexp)))
@@ -161,7 +129,7 @@ REGEXP-P selects `projectile-replace-regexp-review'."
:to-equal "X foobar barfoo X\n"))))
(it "substitutes capture groups in the replacement"
- (projectile-replace-review-test--with-project
+ (projectile-test-with-project
(("c.txt" . "foo_bar and baz_qux\n"))
(let ((buf (projectile-replace-review-test--run
"\\([a-z]+\\)_\\([a-z]+\\)" "\\2-\\1" 'regexp)))
@@ -170,7 +138,7 @@ REGEXP-P selects `projectile-replace-regexp-review'."
:to-equal "bar-foo and qux-baz\n"))))
(it "excludes files ignored via .projectile"
- (projectile-replace-review-test--with-project
+ (projectile-test-with-project
((".projectile" . "-secret\n")
("keep.txt" . "foo\n")
("secret/hide.txt" . "foo\n"))
@@ -203,7 +171,7 @@ REGEXP-P selects `projectile-replace-regexp-review'."
(describe "projectile-replace write-back safety"
(it "skips a closed file that changed on disk since the scan"
- (projectile-replace-review-test--with-project
+ (projectile-test-with-project
(("a.txt" . "hello foo world\nsecond foo line\n"))
(projectile-test-use-plain-grep)
(let ((buf (projectile-replace-review-test--run "foo" "bar")))
@@ -217,7 +185,7 @@ REGEXP-P selects `projectile-replace-regexp-review'."
"PREPENDED LINE\nhello foo world\nsecond foo line\n"))))
(it "does not hang scanning a regexp that matches empty at end of buffer"
- (projectile-replace-review-test--with-project
+ (projectile-test-with-project
(("z.txt" . "aaa\nbbb\n"))
;; `^' matches the empty string at every line start, including at
;; end-of-buffer; the scan must terminate instead of spinning forever
@@ -226,7 +194,7 @@ REGEXP-P selects `projectile-replace-regexp-review'."
(expect (plist-member result :matches) :to-be-truthy))))
(it "applies via disk when the scanned buffer was killed before apply"
- (projectile-replace-review-test--with-project
+ (projectile-test-with-project
(("k.txt" . "foo here\n"))
(projectile-test-use-plain-grep)
(find-file-noselect (expand-file-name "k.txt"))
@@ -239,7 +207,7 @@ REGEXP-P selects `projectile-replace-regexp-review'."
:to-equal "bar here\n"))))
(it "edits the buffer, not disk, for a file opened and modified after scan"
- (projectile-replace-review-test--with-project
+ (projectile-test-with-project
(("o.txt" . "foo tail\n"))
(projectile-test-use-plain-grep)
(let ((buf (projectile-replace-review-test--run "foo" "bar")))
@@ -257,7 +225,7 @@ REGEXP-P selects `projectile-replace-regexp-review'."
:to-equal "foo tail\n")))))
(it "skips a live buffer's match when text is inserted before it after the
scan"
- (projectile-replace-review-test--with-project
+ (projectile-test-with-project
(("p.txt" . "keep\nfoo tail\n"))
(projectile-test-use-plain-grep)
;; open before the scan so the match is tagged against the live buffer
@@ -273,7 +241,7 @@ REGEXP-P selects `projectile-replace-regexp-review'."
(expect (buffer-string) :to-equal "PREPENDED\nkeep\nfoo tail\n")))))
(it "preserves CRLF line endings on the disk write-back path"
- (projectile-replace-review-test--with-project
+ (projectile-test-with-project
(("crlf.txt" . "foo\r\nbar\r\n"))
(projectile-test-use-plain-grep)
(let ((buf (projectile-replace-review-test--run "foo" "baz")))
@@ -283,7 +251,7 @@ REGEXP-P selects `projectile-replace-regexp-review'."
:to-equal "baz\r\nbar\r\n"))))
(it "keeps applying the remaining files when one file's write fails"
- (projectile-replace-review-test--with-project
+ (projectile-test-with-project
(("g.txt" . "foo\n")
("h.txt" . "foo\n"))
(projectile-test-use-plain-grep)
@@ -300,7 +268,7 @@ REGEXP-P selects `projectile-replace-regexp-review'."
:to-equal "bar\n"))))
(it "does not force-save a buffer that had unsaved edits"
- (projectile-replace-review-test--with-project
+ (projectile-test-with-project
(("u.txt" . "foo mid\n"))
(projectile-test-use-plain-grep)
(find-file-noselect (expand-file-name "u.txt"))
@@ -319,7 +287,7 @@ REGEXP-P selects `projectile-replace-regexp-review'."
(describe "projectile-replace-review case-sensitivity toggle"
(it "flips which matches are found and re-renders"
- (projectile-replace-review-test--with-project
+ (projectile-test-with-project
(("case.txt" . "Foo foo FOO\n"))
(projectile-test-use-plain-grep)
(let ((buf (projectile-replace-review-test--run "foo" "bar")))
@@ -339,7 +307,7 @@ REGEXP-P selects `projectile-replace-regexp-review'."
(expect (length projectile-replace--matches) :to-equal 3)))))
(it "applies only the case-sensitive survivors after a toggle"
- (projectile-replace-review-test--with-project
+ (projectile-test-with-project
(("s.txt" . "Foo foo\n"))
(projectile-test-use-plain-grep)
(let ((buf (projectile-replace-review-test--run "foo" "bar")))
@@ -353,7 +321,7 @@ REGEXP-P selects `projectile-replace-regexp-review'."
(it "still excludes ignored files on the case-insensitive fallback path"
;; the case-insensitive literal search scans the full file list rather
;; than the grep narrowing, so it must still honor .projectile ignores
- (projectile-replace-review-test--with-project
+ (projectile-test-with-project
((".projectile" . "-secret\n")
("keep.txt" . "FOO\n")
("secret/hide.txt" . "FOO\n"))
@@ -376,7 +344,7 @@ REGEXP-P selects `projectile-replace-regexp-review'."
:to-equal "FOO\n"))))
(it "re-enables all matches when re-scanning (documented reset)"
- (projectile-replace-review-test--with-project
+ (projectile-test-with-project
(("e.txt" . "foo foo foo\n"))
(projectile-test-use-plain-grep)
(let ((buf (projectile-replace-review-test--run "foo" "bar")))
@@ -394,7 +362,7 @@ REGEXP-P selects `projectile-replace-regexp-review'."
(describe "projectile-replace-review regexp/literal toggle"
(it "re-scans and changes the count for a term with metacharacters"
- (projectile-replace-review-test--with-project
+ (projectile-test-with-project
(("meta.txt" . "a.b axb a.b\n"))
(projectile-test-use-plain-grep)
(let ((buf (projectile-replace-review-test--run "a.b" "Z")))
@@ -409,7 +377,7 @@ REGEXP-P selects `projectile-replace-regexp-review'."
(expect (length projectile-replace--matches) :to-equal 3)))))
(it "refuses an invalid regexp and stays literal without erroring"
- (projectile-replace-review-test--with-project
+ (projectile-test-with-project
(("br.txt" . "foo[bar\n"))
(projectile-test-use-plain-grep)
(let ((buf (projectile-replace-review-test--run "foo[" "X")))
@@ -423,7 +391,7 @@ REGEXP-P selects `projectile-replace-regexp-review'."
(describe "projectile-replace-review match filtering"
(it "keeps only matches whose line matches and applies just those"
- (projectile-replace-review-test--with-project
+ (projectile-test-with-project
(("f.txt" . "keep foo here\ndrop foo there\nkeep foo again\n"))
(projectile-test-use-plain-grep)
(let ((buf (projectile-replace-review-test--run "foo" "bar")))
@@ -437,7 +405,7 @@ REGEXP-P selects `projectile-replace-regexp-review'."
:to-equal "keep bar here\ndrop foo there\nkeep bar again\n"))))
(it "flushes matches whose line matches and applies the survivors"
- (projectile-replace-review-test--with-project
+ (projectile-test-with-project
(("f.txt" . "keep foo here\ndrop foo there\nkeep foo again\n"))
(projectile-test-use-plain-grep)
(let ((buf (projectile-replace-review-test--run "foo" "bar")))
@@ -449,7 +417,7 @@ REGEXP-P selects `projectile-replace-regexp-review'."
:to-equal "keep bar here\ndrop foo there\nkeep bar again\n"))))
(it "restores a filtered-away match on re-search"
- (projectile-replace-review-test--with-project
+ (projectile-test-with-project
(("f.txt" . "keep foo here\ndrop foo there\n"))
(projectile-test-use-plain-grep)
(let ((buf (projectile-replace-review-test--run "foo" "bar")))
@@ -465,7 +433,7 @@ REGEXP-P selects `projectile-replace-regexp-review'."
(describe "projectile-replace-review file filtering"
(it "keeps only matches whose file matches the regexp"
- (projectile-replace-review-test--with-project
+ (projectile-test-with-project
(("keep.txt" . "foo\n")
("lib/skip.txt" . "foo\n"))
(projectile-test-use-plain-grep)
@@ -485,7 +453,7 @@ REGEXP-P selects `projectile-replace-regexp-review'."
:to-equal "foo\n"))))
(it "flushes matches whose project-relative path matches the regexp"
- (projectile-replace-review-test--with-project
+ (projectile-test-with-project
(("keep.txt" . "foo\n")
("lib/skip.txt" . "foo\n"))
(projectile-test-use-plain-grep)
@@ -504,7 +472,7 @@ REGEXP-P selects `projectile-replace-regexp-review'."
(describe "projectile-replace-review status header"
(it "reflects the mode flags and updates when they toggle"
- (projectile-replace-review-test--with-project
+ (projectile-test-with-project
(("h.txt" . "foo\n"))
(projectile-test-use-plain-grep)
(let ((buf (projectile-replace-review-test--run "foo" "bar")))
@@ -520,7 +488,7 @@ REGEXP-P selects `projectile-replace-regexp-review'."
:to-match "\\[regexp\\]"))))
(it "shows (none) when there is no replacement yet"
- (projectile-replace-review-test--with-project
+ (projectile-test-with-project
(("h.txt" . "foo\n"))
(projectile-test-use-plain-grep)
(let ((buf (projectile-replace-review-test--run "foo" "")))
@@ -528,7 +496,7 @@ REGEXP-P selects `projectile-replace-regexp-review'."
:to-match "with (none)"))))
(it "notes when the list has been filtered"
- (projectile-replace-review-test--with-project
+ (projectile-test-with-project
(("h.txt" . "keep foo\ndrop foo\n"))
(projectile-test-use-plain-grep)
(let ((buf (projectile-replace-review-test--run "foo" "bar")))
@@ -546,7 +514,7 @@ REGEXP-P selects `projectile-replace-regexp-review'."
(describe "projectile-replace-review export to grep-mode"
(it "renders the shown matches as a navigable grep-mode buffer"
- (projectile-replace-review-test--with-project
+ (projectile-test-with-project
(("a.txt" . "foo one foo\n")
("lib/b.txt" . "start foo end\n"))
(projectile-test-use-plain-grep)
@@ -575,7 +543,7 @@ REGEXP-P selects `projectile-replace-regexp-review'."
(kill-buffer gbuf)))))
(it "exports only the filtered (shown) matches, not the removed ones"
- (projectile-replace-review-test--with-project
+ (projectile-test-with-project
(("keep.txt" . "keep foo\n")
("drop.txt" . "drop foo\n"))
(projectile-test-use-plain-grep)
@@ -590,7 +558,7 @@ REGEXP-P selects `projectile-replace-regexp-review'."
(kill-buffer gbuf))))))
(it "errors when there are no matches to export"
- (projectile-replace-review-test--with-project
+ (projectile-test-with-project
(("z.txt" . "foo\n"))
(projectile-test-use-plain-grep)
(let ((buf (projectile-replace-review-test--run "foo" "bar")))
@@ -599,7 +567,7 @@ REGEXP-P selects `projectile-replace-regexp-review'."
(expect (projectile-replace--export) :to-throw 'user-error)))))
(it "excludes matches toggled off, matching what apply would do"
- (projectile-replace-review-test--with-project
+ (projectile-test-with-project
(("e.txt" . "foo\nfoo\nfoo\n"))
(projectile-test-use-plain-grep)
(let ((buf (projectile-replace-review-test--run "foo" "bar")))
@@ -619,7 +587,7 @@ REGEXP-P selects `projectile-replace-regexp-review'."
(kill-buffer gbuf))))))
(it "does not create a phantom grep hit for a numeric term like 10:30"
- (projectile-replace-review-test--with-project
+ (projectile-test-with-project
(("t.txt" . "before 10:30 after\n"))
(projectile-test-use-plain-grep)
(let ((buf (projectile-replace-review-test--run "10:30" "NOON")))
diff --git a/test/projectile-replace-test.el b/test/projectile-replace-test.el
index 0d792e4635..98ab552c33 100644
--- a/test/projectile-replace-test.el
+++ b/test/projectile-replace-test.el
@@ -28,41 +28,15 @@
(require 'projectile-test-helpers)
(defmacro projectile-replace-test--with-project (files &rest body)
- "Evaluate BODY in a sandbox project containing FILES.
-
-FILES is a literal alist of (NAME . CONTENT) file specs, created
-relative to the project root. BODY runs with `default-directory' set
-to the project root, `projectile-project-root' stubbed accordingly,
-native indexing with fresh caches, and default case handling. Buffers
-visiting project files are killed afterwards; the replace commands
-modify buffers without saving them, so leftovers would leak into the
-next spec."
+ "Like `projectile-test-with-project' but with the replace smart-case
bindings.
+BODY additionally runs with `search-upper-case' and `case-replace' set, so
+the case-handling expectations are independent of the environment: a
+lower-case search folds case, a mixed-case one doesn't."
(declare (indent 1) (debug (sexp &rest form)))
- `(projectile-test-with-sandbox
- (make-directory "project" t)
- (with-temp-file "project/.projectile")
- ,@(mapcar (lambda (spec)
- `(progn
- (when-let* ((dir (file-name-directory ,(car spec))))
- (make-directory (expand-file-name dir "project") t))
- (with-temp-file (expand-file-name ,(car spec) "project")
- (insert ,(cdr spec)))))
- files)
- (let ((default-directory (file-name-as-directory
- (projectile-test-project-root)))
- (projectile-indexing-method 'native)
- (projectile-projects-cache (make-hash-table :test 'equal))
- (projectile-projects-cache-time (make-hash-table :test 'equal))
- (projectile-enable-caching nil)
- ;; make the case-handling expectations independent of the
- ;; environment: lower-case input folds case, mixed-case doesn't
- (case-fold-search t)
- (search-upper-case t)
+ `(projectile-test-with-project ,files
+ (let ((search-upper-case t)
(case-replace t))
- (spy-on 'projectile-project-root :and-return-value default-directory)
- (unwind-protect
- (progn ,@body)
- (projectile-test-kill-project-buffers default-directory)))))
+ ,@body)))
(defun projectile-replace-test--replace (old new &optional regexp-p)
"Replace OLD with NEW in the current project, auto-confirming everything.
diff --git a/test/projectile-scan-async-test.el
b/test/projectile-scan-async-test.el
index a4cd6f0f1c..54acf7d051 100644
--- a/test/projectile-scan-async-test.el
+++ b/test/projectile-scan-async-test.el
@@ -35,32 +35,6 @@
(require 'projectile-test-helpers)
-(defmacro projectile-scan-async-test--with-project (files &rest body)
- "Evaluate BODY in a sandbox project containing FILES.
-FILES is a literal alist of (NAME . CONTENT) file specs relative to the
-project root. BODY runs with `default-directory' at the root and
-`projectile-project-root' stubbed accordingly."
- (declare (indent 1) (debug (sexp &rest form)))
- `(projectile-test-with-sandbox
- (make-directory "project" t)
- (with-temp-file "project/.projectile")
- ,@(mapcar (lambda (spec)
- `(progn
- (when-let* ((dir (file-name-directory ,(car spec))))
- (make-directory (expand-file-name dir "project") t))
- (with-temp-file (expand-file-name ,(car spec) "project")
- (insert ,(cdr spec)))))
- files)
- (let ((default-directory (file-name-as-directory
- (projectile-test-project-root)))
- (projectile-indexing-method 'native)
- (projectile-projects-cache (make-hash-table :test 'equal))
- (projectile-projects-cache-time (make-hash-table :test 'equal))
- (projectile-enable-caching nil)
- (case-fold-search t))
- (spy-on 'projectile-project-root :and-return-value default-directory)
- ,@body)))
-
(defun projectile-scan-async-test--seed (root)
"Return a results buffer in `projectile-replace-mode' seeded for a foo scan."
(let ((buf (get-buffer-create "*projectile-scan-async-test*")))
@@ -95,7 +69,7 @@ project root. BODY runs with `default-directory' at the root
and
(describe "projectile-replace--gather-async"
(it "produces the same final matches as the synchronous gather"
- (projectile-scan-async-test--with-project
+ (projectile-test-with-project
(("a.txt" . "foo one foo\n")
("b.txt" . "start foo end\n")
("lib/c.txt" . "foo\nfoo\n")
@@ -119,7 +93,7 @@ project root. BODY runs with `default-directory' at the
root and
(kill-buffer buf)))))
(it "streams matches in chunk by chunk and ends with the full set"
- (projectile-scan-async-test--with-project
+ (projectile-test-with-project
(("a.txt" . "foo\nfoo\n")
("b.txt" . "foo\n")
("c.txt" . "foo\nfoo\n")
@@ -149,7 +123,7 @@ project root. BODY runs with `default-directory' at the
root and
(kill-buffer buf)))))
(it "keeps case sensitivity in a late chunk (parity with sync)"
- (projectile-scan-async-test--with-project
+ (projectile-test-with-project
(("a.txt" . "foo\n")
("b.txt" . "foo\n")
("c.txt" . "foo\n")
@@ -180,7 +154,7 @@ project root. BODY runs with `default-directory' at the
root and
(kill-buffer buf)))))
(it "truncates at the same match as sync on a chunk-boundary budget"
- (projectile-scan-async-test--with-project
+ (projectile-test-with-project
(("a.txt" . "foo\n") ("b.txt" . "foo\n") ("c.txt" . "foo\n")
("d.txt" . "foo\n") ("e.txt" . "foo\n") ("f.txt" . "foo\n"))
(let* ((root default-directory)
@@ -202,7 +176,7 @@ project root. BODY runs with `default-directory' at the
root and
(kill-buffer buf)))))
(it "runs ON-DONE in the buffer once scanning finishes"
- (projectile-scan-async-test--with-project
+ (projectile-test-with-project
(("a.txt" . "foo\n")
("b.txt" . "foo\n"))
(let* ((root default-directory)
@@ -222,7 +196,7 @@ project root. BODY runs with `default-directory' at the
root and
(kill-buffer buf)))))
(it "honors projectile-replace-max-matches and sets truncated"
- (projectile-scan-async-test--with-project
+ (projectile-test-with-project
(("a.txt" . "foo\nfoo\n")
("b.txt" . "foo\nfoo\n")
("c.txt" . "foo\nfoo\n"))
@@ -241,7 +215,7 @@ project root. BODY runs with `default-directory' at the
root and
(describe "projectile-replace async scanning-state gating"
(it "refuses to apply while a scan is still running"
- (projectile-scan-async-test--with-project
+ (projectile-test-with-project
(("a.txt" . "foo\n"))
(let ((buf (projectile-scan-async-test--seed default-directory)))
(unwind-protect
@@ -251,7 +225,7 @@ project root. BODY runs with `default-directory' at the
root and
(kill-buffer buf)))))
(it "refuses to export while a scan is still running"
- (projectile-scan-async-test--with-project
+ (projectile-test-with-project
(("a.txt" . "foo\n"))
(let ((buf (projectile-scan-async-test--seed default-directory)))
(unwind-protect
@@ -262,7 +236,7 @@ project root. BODY runs with `default-directory' at the
root and
(it "refuses to filter while a scan is still running"
;; a later chunk would append past the filter, leaving an incoherent list
- (projectile-scan-async-test--with-project
+ (projectile-test-with-project
(("a.txt" . "foo\n"))
(let ((buf (projectile-scan-async-test--seed default-directory)))
(unwind-protect
@@ -273,7 +247,7 @@ project root. BODY runs with `default-directory' at the
root and
(kill-buffer buf)))))
(it "lets apply and export proceed once scanning has cleared"
- (projectile-scan-async-test--with-project
+ (projectile-test-with-project
(("a.txt" . "foo\n"))
(let ((buf (projectile-scan-async-test--seed default-directory)))
(unwind-protect
@@ -286,7 +260,7 @@ project root. BODY runs with `default-directory' at the
root and
(describe "projectile-replace async cancellation"
(it "cancels an in-flight timer when a re-scan starts"
- (projectile-scan-async-test--with-project
+ (projectile-test-with-project
(("a.txt" . "foo\n")
("b.txt" . "foo\n")
("c.txt" . "foo\n"))
@@ -309,7 +283,7 @@ project root. BODY runs with `default-directory' at the
root and
(kill-buffer buf)))))
(it "cancels the timer and drops it from timer-list when the buffer is
killed"
- (projectile-scan-async-test--with-project
+ (projectile-test-with-project
(("a.txt" . "foo\n")
("b.txt" . "foo\n")
("c.txt" . "foo\n"))
@@ -325,7 +299,7 @@ project root. BODY runs with `default-directory' at the
root and
(expect (memq old timer-list) :to-be nil)))))
(it "guards the chunk callback against a killed buffer"
- (projectile-scan-async-test--with-project
+ (projectile-test-with-project
(("a.txt" . "foo\n"))
(let* ((root default-directory)
(candidates (projectile-scan-async-test--candidates root))
@@ -336,7 +310,7 @@ project root. BODY runs with `default-directory' at the
root and
:not :to-throw))))
(it "ignores a chunk carrying a superseded scan generation"
- (projectile-scan-async-test--with-project
+ (projectile-test-with-project
(("a.txt" . "foo\nfoo\n"))
(let* ((root default-directory)
(candidates (projectile-scan-async-test--candidates root))
diff --git a/test/projectile-search-review-test.el
b/test/projectile-search-review-test.el
index f4f5346b35..8ba419978a 100644
--- a/test/projectile-search-review-test.el
+++ b/test/projectile-search-review-test.el
@@ -30,38 +30,6 @@
(require 'projectile-test-helpers)
-(defmacro projectile-search-review-test--with-project (files &rest body)
- "Evaluate BODY in a sandbox project containing FILES.
-
-FILES is a literal alist of (NAME . CONTENT) file specs created relative
-to the project root. A `.projectile' marker is created; include one in
-FILES to override its contents (e.g. to add ignore rules). BODY runs
-with `default-directory' at the root and `projectile-project-root'
-stubbed accordingly. Project buffers and the results buffers are killed
-afterwards."
- (declare (indent 1) (debug (sexp &rest form)))
- `(projectile-test-with-sandbox
- (make-directory "project" t)
- (with-temp-file "project/.projectile")
- ,@(mapcar (lambda (spec)
- `(progn
- (when-let* ((dir (file-name-directory ,(car spec))))
- (make-directory (expand-file-name dir "project") t))
- (with-temp-file (expand-file-name ,(car spec) "project")
- (insert ,(cdr spec)))))
- files)
- (let ((default-directory (file-name-as-directory
- (projectile-test-project-root)))
- (projectile-indexing-method 'native)
- (projectile-projects-cache (make-hash-table :test 'equal))
- (projectile-projects-cache-time (make-hash-table :test 'equal))
- (projectile-enable-caching nil)
- (case-fold-search t))
- (spy-on 'projectile-project-root :and-return-value default-directory)
- (unwind-protect
- (progn ,@body)
- (projectile-test-kill-project-buffers default-directory)))))
-
(defun projectile-search-review-test--run (term &optional regexp-p)
"Drive the search review command for TERM and return the results buffer.
REGEXP-P selects `projectile-search-regexp-review'."
@@ -85,7 +53,7 @@ REGEXP-P selects `projectile-search-regexp-review'."
(describe "projectile-search-review (literal)"
(it "finds every literal match grouped by file, read-only, no apply keys"
- (projectile-search-review-test--with-project
+ (projectile-test-with-project
(("a.txt" . "foo one foo\n")
("lib/b.txt" . "start foo end\n"))
(projectile-test-use-plain-grep)
@@ -106,7 +74,7 @@ REGEXP-P selects `projectile-search-regexp-review'."
(expect (buffer-string) :not :to-match "\\[[ X]\\]")))))
(it "renders each match as LINE:COL: with the matched span present"
- (projectile-search-review-test--with-project
+ (projectile-test-with-project
(("a.txt" . "alpha foo beta\n"))
(projectile-test-use-plain-grep)
(let ((buf (projectile-search-review-test--run "foo")))
@@ -114,7 +82,7 @@ REGEXP-P selects `projectile-search-regexp-review'."
(expect (buffer-string) :to-match "1:7: alpha foo beta")))))
(it "reports no matches without popping a buffer"
- (projectile-search-review-test--with-project
+ (projectile-test-with-project
(("a.txt" . "nothing here\n"))
(projectile-test-use-plain-grep)
(spy-on 'message)
@@ -123,7 +91,7 @@ REGEXP-P selects `projectile-search-regexp-review'."
(describe "projectile-search-regexp-review"
(it "honors Emacs-only regexp constructs a shell regexp couldn't express"
- (projectile-search-review-test--with-project
+ (projectile-test-with-project
(("s.txt" . "foo foobar barfoo foo\n"))
(let ((buf (projectile-search-review-test--run "\\_<foo\\_>" 'regexp)))
(with-current-buffer buf
@@ -133,7 +101,7 @@ REGEXP-P selects `projectile-search-regexp-review'."
(describe "projectile-search-review visit"
(it "RET resolves the right file and line/column"
- (projectile-search-review-test--with-project
+ (projectile-test-with-project
(("a.txt" . "line one\nsecond foo here\n")
("lib/b.txt" . "foo at top\n"))
(projectile-test-use-plain-grep)
@@ -163,7 +131,7 @@ REGEXP-P selects `projectile-search-regexp-review'."
(describe "projectile-search-review filtering"
(it "prunes matches by line and marks the list filtered"
- (projectile-search-review-test--with-project
+ (projectile-test-with-project
(("f.txt" . "keep foo here\ndrop foo there\nkeep foo again\n"))
(projectile-test-use-plain-grep)
(let ((buf (projectile-search-review-test--run "foo")))
@@ -178,7 +146,7 @@ REGEXP-P selects `projectile-search-regexp-review'."
(expect projectile-replace--filtered :to-be nil)))))
(it "prunes matches by file"
- (projectile-search-review-test--with-project
+ (projectile-test-with-project
(("keep.txt" . "foo\n")
("lib/skip.txt" . "foo\n"))
(projectile-test-use-plain-grep)
@@ -194,7 +162,7 @@ REGEXP-P selects `projectile-search-regexp-review'."
(describe "projectile-search-review case and regexp toggles"
(it "re-scans when case sensitivity flips"
- (projectile-search-review-test--with-project
+ (projectile-test-with-project
(("case.txt" . "Foo foo FOO\n"))
(projectile-test-use-plain-grep)
(let ((buf (projectile-search-review-test--run "foo")))
@@ -209,7 +177,7 @@ REGEXP-P selects `projectile-search-regexp-review'."
:to-equal "foo")))))
(it "re-scans when literal/regexp flips"
- (projectile-search-review-test--with-project
+ (projectile-test-with-project
(("meta.txt" . "a.b axb a.b\n"))
(projectile-test-use-plain-grep)
(let ((buf (projectile-search-review-test--run "a.b")))
@@ -223,7 +191,7 @@ REGEXP-P selects `projectile-search-regexp-review'."
(describe "projectile-search-review status header"
(it "shows the term, counts and mode flags"
- (projectile-search-review-test--with-project
+ (projectile-test-with-project
(("h.txt" . "foo\n"))
(projectile-test-use-plain-grep)
(let ((buf (projectile-search-review-test--run "foo")))
@@ -246,7 +214,7 @@ REGEXP-P selects `projectile-search-regexp-review'."
(describe "projectile-search-review export to grep-mode"
(it "renders the shown matches as a navigable grep-mode buffer"
- (projectile-search-review-test--with-project
+ (projectile-test-with-project
(("a.txt" . "foo one foo\n")
("lib/b.txt" . "start foo end\n"))
(projectile-test-use-plain-grep)
@@ -265,7 +233,7 @@ REGEXP-P selects `projectile-search-regexp-review'."
(describe "projectile-search-review to-replace bridge"
(it "opens the replace reviewer preloaded with the same term"
- (projectile-search-review-test--with-project
+ (projectile-test-with-project
(("a.txt" . "foo one foo\n"))
(projectile-test-use-plain-grep)
(let ((buf (projectile-search-review-test--run "foo")))
@@ -286,7 +254,7 @@ REGEXP-P selects `projectile-search-regexp-review'."
(expect (buffer-string) :to-match "\\[X\\]"))))))
(it "carries literal-ness through from a regexp search"
- (projectile-search-review-test--with-project
+ (projectile-test-with-project
(("s.txt" . "foo foobar foo\n"))
(let ((buf (projectile-search-review-test--run "\\_<foo\\_>" 'regexp)))
(with-current-buffer buf
@@ -406,7 +374,7 @@ REGEXP-P selects `projectile-search-regexp-review'."
(describe "projectile-search--rg-ingest streaming and cap"
(it "honors projectile-replace-max-matches and marks the list truncated"
- (projectile-search-review-test--with-project
+ (projectile-test-with-project
(("a.txt" . "foo\n"))
(let ((buf (get-buffer-create projectile-search-buffer-name))
(line (lambda (n)
@@ -434,7 +402,7 @@ REGEXP-P selects `projectile-search-regexp-review'."
(describe "projectile-search-review ripgrep process lifecycle"
(it "cancel-scan kills the running process, leaving no orphan"
(assume (executable-find "sleep") "needs a sleep executable")
- (projectile-search-review-test--with-project
+ (projectile-test-with-project
(("a.txt" . "foo\n"))
;; stub the command so we get a controllable long-running process
;; without depending on ripgrep being installed
@@ -455,7 +423,7 @@ REGEXP-P selects `projectile-search-regexp-review'."
(it "killing the results buffer kills the running process"
(assume (executable-find "sleep") "needs a sleep executable")
- (projectile-search-review-test--with-project
+ (projectile-test-with-project
(("a.txt" . "foo\n"))
(cl-letf (((symbol-function 'projectile-search--rg-command)
(lambda (&rest _) (list "sleep" "30"))))
@@ -488,7 +456,7 @@ REGEXP-P selects `projectile-search-regexp-review'."
(expect (projectile-search--rg-fastpath-p t) :to-be nil)))
(it "routes a literal search-mode buffer to the ripgrep gather"
- (projectile-search-review-test--with-project
+ (projectile-test-with-project
(("a.txt" . "foo\n"))
(let ((buf (get-buffer-create projectile-search-buffer-name)))
(projectile-replace--seed buf #'projectile-search-mode
@@ -501,7 +469,7 @@ REGEXP-P selects `projectile-search-regexp-review'."
(expect 'projectile-replace--gather-async :not :to-have-been-called))))
(it "routes a regexp search-mode buffer to the elisp path (no rg)"
- (projectile-search-review-test--with-project
+ (projectile-test-with-project
(("a.txt" . "foo\n"))
(let ((buf (get-buffer-create projectile-search-buffer-name)))
(projectile-replace--seed buf #'projectile-search-mode
@@ -514,7 +482,7 @@ REGEXP-P selects `projectile-search-regexp-review'."
(expect 'projectile-replace--gather-async :to-have-been-called))))
(it "never routes a replace-mode buffer to ripgrep, even for a literal"
- (projectile-search-review-test--with-project
+ (projectile-test-with-project
(("a.txt" . "foo\n"))
(let ((buf (get-buffer-create projectile-replace-buffer-name)))
(projectile-replace--seed buf #'projectile-replace-mode
@@ -527,7 +495,7 @@ REGEXP-P selects `projectile-search-regexp-review'."
(expect 'projectile-replace--gather-async :to-have-been-called))))
(it "projectile-search-use-ripgrep nil forces the elisp path"
- (projectile-search-review-test--with-project
+ (projectile-test-with-project
(("a.txt" . "foo\n"))
(let ((buf (get-buffer-create projectile-search-buffer-name)))
(projectile-replace--seed buf #'projectile-search-mode
@@ -542,7 +510,7 @@ REGEXP-P selects `projectile-search-regexp-review'."
(describe "projectile-search-review ripgrep end-to-end"
(it "finds matches with a correct character column on a multibyte line"
(assume (executable-find "rg") "ripgrep is not installed")
- (projectile-search-review-test--with-project
+ (projectile-test-with-project
(("mb.txt" . "café foo bar\n")
("plain.txt" . "foo\n"))
(let ((buf (get-buffer-create projectile-search-buffer-name))
@@ -562,7 +530,7 @@ REGEXP-P selects `projectile-search-regexp-review'."
(it "honors projectile-replace-max-matches over a real ripgrep stream"
(assume (executable-find "rg") "ripgrep is not installed")
- (projectile-search-review-test--with-project
+ (projectile-test-with-project
(("a.txt" . "foo\nfoo\nfoo\n"))
(let ((buf (get-buffer-create projectile-search-buffer-name))
(root default-directory)
@@ -578,7 +546,7 @@ REGEXP-P selects `projectile-search-regexp-review'."
(it "excludes a path-rooted .projectile ignore from the ripgrep results"
(assume (executable-find "rg") "ripgrep is not installed")
- (projectile-search-review-test--with-project
+ (projectile-test-with-project
((".projectile" . "-/vendor\n")
("keep.txt" . "foo\n")
("vendor/hidden.txt" . "foo\n"))
@@ -603,7 +571,7 @@ REGEXP-P selects `projectile-search-regexp-review'."
(describe "projectile-search-review ripgrep vs elisp parity"
(it "the ripgrep fast-path finds the same matches as the elisp scan"
(assume (executable-find "rg") "needs a real ripgrep")
- (projectile-search-review-test--with-project
+ (projectile-test-with-project
(("a.txt" . "foo one\nno match here\nfoo two\n")
("sub/b.txt" . "prefix foo suffix\n")
("c.txt" . "nothing to see\n"))
diff --git a/test/projectile-test-helpers.el b/test/projectile-test-helpers.el
index 60ec0ba448..b7307f56db 100644
--- a/test/projectile-test-helpers.el
+++ b/test/projectile-test-helpers.el
@@ -332,6 +332,41 @@ matter which of rg/ag/ack happens to be installed."
(insert-file-contents (expand-file-name file)))
(buffer-string)))
+(defmacro projectile-test-with-project (files &rest body)
+ "Evaluate BODY in a sandbox `project/' containing FILES.
+FILES is a literal alist of (RELPATH . CONTENT) specs created under a
+`project/' directory; a `.projectile' marker is added (include one in
+FILES to override its contents, e.g. to add ignore rules). BODY runs
+with `default-directory' at the truename'd project root,
+`projectile-project-root' stubbed to it, native indexing with fresh
+caches, caching off and `case-fold-search' on. Buffers visiting project
+files, and the search/replace results buffers, are killed afterwards.
+
+This is the shared core behind the per-suite search/replace project
+macros; a suite that needs extra dynamic bindings (e.g. the replace
+specs' smart-case settings) can wrap BODY in its own `let'."
+ (declare (indent 1) (debug (sexp &rest form)))
+ `(projectile-test-with-sandbox
+ (make-directory "project" t)
+ (with-temp-file "project/.projectile")
+ ,@(mapcar (lambda (spec)
+ `(progn
+ (when-let* ((dir (file-name-directory ,(car spec))))
+ (make-directory (expand-file-name dir "project") t))
+ (with-temp-file (expand-file-name ,(car spec) "project")
+ (insert ,(cdr spec)))))
+ files)
+ (let ((default-directory (file-name-as-directory
(projectile-test-project-root)))
+ (projectile-indexing-method 'native)
+ (projectile-projects-cache (make-hash-table :test 'equal))
+ (projectile-projects-cache-time (make-hash-table :test 'equal))
+ (projectile-enable-caching nil)
+ (case-fold-search t))
+ (spy-on 'projectile-project-root :and-return-value default-directory)
+ (unwind-protect
+ (progn ,@body)
+ (projectile-test-kill-project-buffers default-directory)))))
+
(defun file-handler-for-tests (operation &rest args)
"Handler for # files.
Just delegates OPERATION and ARGS for all operations except for