1 ;;; test-ox-publish.el --- Tests for "ox-publish.el" -*- lexical-binding: t; -*-
3 ;; Copyright (C) 2016 Nicolas Goaziou
5 ;; Author: Nicolas Goaziou <mail@nicolasgoaziou.fr>
7 ;; This program is free software; you can redistribute it and/or modify
8 ;; it under the terms of the GNU General Public License as published by
9 ;; the Free Software Foundation, either version 3 of the License, or
10 ;; (at your option) any later version.
12 ;; This program is distributed in the hope that it will be useful,
13 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ;; GNU General Public License for more details.
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with this program. If not, see <http://www.gnu.org/licenses/>.
25 (defun org-test-publish (properties handler
)
26 "Publish a project defined by PROPERTIES.
27 Call HANDLER with the publishing directory as its sole argument.
28 Unless set otherwise in PROPERTIES, `:base-directory' is set to
29 \"examples/pub/\" sub-directory from test directory and
30 `:publishing-function' is set to `org-publish-attachment'."
32 (let* ((org-publish-use-timestamps-flag nil
)
33 (org-publish-cache nil
)
34 (base-dir (expand-file-name "examples/pub/" org-test-dir
))
35 (pub-dir (make-temp-file "org-test" t
))
36 (org-publish-timestamp-directory
37 (expand-file-name ".org-timestamps/" pub-dir
))
39 `("test" ,@(org-combine-plists
42 :publishing-function org-publish-attachment
)
44 `(:publishing-directory
,pub-dir
)))))
47 (org-publish-projects (list project
))
48 (funcall handler pub-dir
))
49 ;; Clear published data.
50 (delete-directory pub-dir t
)
51 ;; Delete auto-generated site-map file, if applicable.
52 (let ((site-map (and (plist-get properties
:auto-sitemap
)
54 (or (plist-get properties
:sitemap-filename
)
57 (when (and site-map
(file-exists-p site-map
))
58 (delete-file site-map
))))))
61 ;;; Mandatory properties
63 (ert-deftest test-org-publish
/base-extension
()
64 "Test `:base-extension' specifications"
67 (equal '("a.org" "b.org")
68 (org-test-publish '(:base-extension
"org")
70 (remove ".org-timestamps"
71 (cl-remove-if #'file-directory-p
72 (directory-files dir
)))))))
75 (org-test-publish '(:base-extension
"txt")
77 (remove ".org-timestamps"
78 (cl-remove-if #'file-directory-p
79 (directory-files dir
)))))))
80 ;; A nil value is equivalent to ".org".
82 (equal '("a.org" "b.org")
83 (org-test-publish '(:base-extension nil
)
85 (remove ".org-timestamps"
86 (cl-remove-if #'file-directory-p
87 (directory-files dir
)))))))
88 ;; Symbol `any' includes all files, even those without extension.
90 (equal '("a.org" "b.org" "file.txt" "noextension")
91 (org-test-publish '(:base-extension any
)
93 (remove ".org-timestamps"
94 (cl-remove-if #'file-directory-p
95 (directory-files dir
))))))))
100 (ert-deftest test-org-publish
/sitemap
()
101 "Test site-map specifications."
102 ;; Site-map creation is controlled with `:auto-sitemap'. It
103 ;; defaults to "sitemap.org".
107 (lambda (dir) (file-exists-p (expand-file-name "sitemap.org" dir
)))))
111 (lambda (dir) (file-exists-p (expand-file-name "sitemap.org" dir
)))))
112 ;; Site-map file name is controlled with `:sitemap-filename'.
115 '(:auto-sitemap t
:sitemap-filename
"mysitemap.org")
116 (lambda (dir) (file-exists-p (expand-file-name "mysitemap.org" dir
)))))
117 ;; Site-map title is controlled with `:sitemap-title'. It defaults
118 ;; to the project name.
120 (equal "#+TITLE: Sitemap for project test"
125 (insert-file-contents (expand-file-name "sitemap.org" dir
))
126 (buffer-substring (point) (line-end-position)))))))
128 (equal "#+TITLE: My title"
130 '(:auto-sitemap t
:sitemap-title
"My title")
133 (insert-file-contents (expand-file-name "sitemap.org" dir
))
134 (buffer-substring (point) (line-end-position)))))))
135 ;; Allowed site-map styles: `list' and `tree'.
140 - [[file:sub/c.org][C]]"
143 :sitemap-sort-folders ignore
146 :include
("a.org" "b.org" "sub/c.org"))
149 (insert-file-contents (expand-file-name "sitemap.org" dir
))
150 (buffer-substring (line-beginning-position 2) (point-max)))))))
156 - [[file:sub/c.org][C]]"
161 :include
("a.org" "b.org" "sub/c.org"))
164 (insert-file-contents (expand-file-name "sitemap.org" dir
))
165 (buffer-substring (line-beginning-position 2) (point-max)))))))
166 ;; When style is `list', `:sitemap-sort-folders' controls the order
167 ;; of appearance of directories among published files.
173 - [[file:sub/c.org][C]]"
178 :sitemap-sort-folders first
180 :include
("a.org" "sub/c.org"))
183 (insert-file-contents (expand-file-name "sitemap.org" dir
))
184 (buffer-substring (line-beginning-position 2) (point-max)))))))
189 - [[file:sub/c.org][C]]
195 :sitemap-sort-folders last
197 :include
("a.org" "sub/c.org"))
200 (insert-file-contents (expand-file-name "sitemap.org" dir
))
201 (buffer-substring (line-beginning-position 2) (point-max)))))))
202 ;; When style is `list', `:sitemap-sort-folders' can be used to
203 ;; toggle visibility of directories in the site-map.
205 (let ((case-fold-search t
))
212 :sitemap-sort-folders t
214 :include
("a.org" "sub/c.org"))
217 (insert-file-contents (expand-file-name "sitemap.org" dir
))
218 (buffer-substring (line-beginning-position 2) (point-max))))))))
226 :sitemap-sort-folders ignore
228 :include
("a.org" "sub/c.org"))
231 (insert-file-contents (expand-file-name "sitemap.org" dir
))
232 (buffer-substring (line-beginning-position 2) (point-max)))))))
233 ;; Using `:sitemap-sort-files', files can be sorted alphabetically
234 ;; (according to their title, or file name when there is none),
235 ;; chronologically a anti-chronologically.
241 - [[file:sub/c.org][C]]"
246 :sitemap-sort-folders ignore
247 :sitemap-sort-files alphabetically
249 :include
("a.org" "b.org" "sub/c.org"))
252 (insert-file-contents (expand-file-name "sitemap.org" dir
))
253 (buffer-substring (line-beginning-position 2) (point-max)))))))
258 - [[file:sub/c.org][C]]
264 :sitemap-sort-folders ignore
265 :sitemap-sort-files chronologically
267 :include
("a.org" "b.org" "sub/c.org"))
270 (insert-file-contents (expand-file-name "sitemap.org" dir
))
271 (buffer-substring (line-beginning-position 2) (point-max)))))))
276 - [[file:sub/c.org][C]]
282 :sitemap-sort-folders ignore
283 :sitemap-sort-files anti-chronologically
285 :include
("a.org" "b.org" "sub/c.org"))
288 (insert-file-contents (expand-file-name "sitemap.org" dir
))
289 (buffer-substring (line-beginning-position 2) (point-max)))))))
290 ;; `:sitemap-format-entry' formats entries in the site-map whereas
291 ;; `:sitemap-function' controls the full site-map.
299 :sitemap-format-entry
300 (lambda (f _s _p
) f
))
303 (insert-file-contents (expand-file-name "sitemap.org" dir
))
304 (buffer-substring (line-beginning-position 2) (point-max)))))))
311 :sitemap-function
(lambda (_title _f
) "Custom!"))
314 (insert-file-contents (expand-file-name "sitemap.org" dir
))
317 (equal "[[file:a.org][A]]"
323 (lambda (_title f
) (org-list-to-generic f nil
)))
326 (insert-file-contents (expand-file-name "sitemap.org" dir
))
327 (buffer-string)))))))
332 (ert-deftest test-org-publish
/resolve-external-link
()
333 "Test `org-publish-resolve-external-link' specifications."
334 ;; Function should preserve internal reference when used between
341 (org-export-create-backend
343 '((headline .
(lambda (h c i
)
344 (concat (org-export-get-reference h i
) " " c
)))
345 (paragraph .
(lambda (p c i
) c
))
346 (section .
(lambda (s c i
) c
))
347 (link .
(lambda (l c i
)
348 (let ((option (org-element-property :search-option l
))
349 (path (org-element-property :path l
)))
351 (org-publish-resolve-external-link
354 (lambda (plist filename pub-dir
)
355 (org-publish-org-to backend filename
".test" plist pub-dir
))))
357 (list :publishing-function
(list publish
))
361 (mapconcat (lambda (f) (org-file-contents (expand-file-name f dir
)))
362 (directory-files dir nil
"\\.test\\'")
365 ;; When optional argument PREFER-CUSTOM is non-nil, use custom ID
366 ;; instead of internal reference, whenever possible.
373 (let ((option (org-element-property :search-option l
))
374 (path (org-element-property :path l
)))
375 (push (org-publish-resolve-external-link option path t
)
379 (org-export-create-backend
380 :transcoders
`((headline .
(lambda (h c i
) c
))
381 (paragraph .
(lambda (p c i
) c
))
382 (section .
(lambda (s c i
) c
))
383 (link .
,link-transcoder
))))
385 (lambda (plist filename pub-dir
)
386 (org-publish-org-to backend filename
".test" plist pub-dir
))))
387 (org-test-publish (list :publishing-function
(list publish
)
389 :include
'("a.org" "b.org"))
391 (sort ids
#'string
<)))))
396 (ert-deftest test-org-publish
/get-project-from-filename
()
397 "Test `org-publish-get-project-from-filename' specifications."
398 ;; Check base directory.
400 (let* ((base (expand-file-name "examples/pub/" org-test-dir
))
401 (file (expand-file-name "a.org" base
))
402 (org-publish-project-alist `(("p" :base-directory
,base
))))
403 (org-publish-get-project-from-filename file
)))
404 ;; Return nil if no appropriate project is found.
406 (let* ((base (expand-file-name "examples/pub/" org-test-dir
))
407 (file (expand-file-name "a.org" base
))
408 (org-publish-project-alist `(("p" :base-directory
,base
))))
409 (org-publish-get-project-from-filename "/other/file.org")))
410 ;; Return the first project effectively publishing the provided
414 (let* ((base (expand-file-name "examples/pub/" org-test-dir
))
415 (file (expand-file-name "a.org" base
))
416 (org-publish-project-alist
417 `(("p1" :base-directory
"/other/")
418 ("p2" :base-directory
,base
)
419 ("p3" :base-directory
,base
))))
420 (car (org-publish-get-project-from-filename file
)))))
421 ;; When :recursive in non-nil, allow files in sub-directories.
423 (let* ((base (expand-file-name "examples/pub/" org-test-dir
))
424 (file (expand-file-name "sub/c.org" base
))
425 (org-publish-project-alist
426 `(("p" :base-directory
,base
:recursive t
))))
427 (org-publish-get-project-from-filename file
)))
429 (let* ((base (expand-file-name "examples/pub/" org-test-dir
))
430 (file (expand-file-name "sub/c.org" base
))
431 (org-publish-project-alist
432 `(("p" :base-directory
,base
:recursive nil
))))
433 (org-publish-get-project-from-filename file
)))
434 ;; Also, when :recursive is non-nil, follow symlinks to directories.
436 (let* ((base (expand-file-name "examples/pub/" org-test-dir
))
437 (file (expand-file-name "link/link.org" base
))
438 (org-publish-project-alist
439 `(("p" :base-directory
,base
:recursive t
))))
440 (org-publish-get-project-from-filename file
)))
442 (let* ((base (expand-file-name "examples/pub/" org-test-dir
))
443 (file (expand-file-name "link/link.org" base
))
444 (org-publish-project-alist
445 `(("p" :base-directory
,base
:recursive nil
))))
446 (org-publish-get-project-from-filename file
)))
447 ;; Check :base-extension.
449 (let* ((base (expand-file-name "examples/pub/" org-test-dir
))
450 (file (expand-file-name "file.txt" base
))
451 (org-publish-project-alist
452 `(("p" :base-directory
,base
:base-extension
"txt"))))
453 (org-publish-get-project-from-filename file
)))
455 (let* ((base (expand-file-name "examples/pub/" org-test-dir
))
456 (file (expand-file-name "file.txt" base
))
457 (org-publish-project-alist
458 `(("p" :base-directory
,base
:base-extension
"org"))))
459 (org-publish-get-project-from-filename file
)))
460 ;; When :base-extension has the special value `any', allow any
461 ;; extension, including none.
463 (let* ((base (expand-file-name "examples/pub/" org-test-dir
))
464 (file (expand-file-name "file.txt" base
))
465 (org-publish-project-alist
466 `(("p" :base-directory
,base
:base-extension any
))))
467 (org-publish-get-project-from-filename file
)))
469 (let* ((base (expand-file-name "examples/pub/" org-test-dir
))
470 (file (expand-file-name "noextension" base
))
471 (org-publish-project-alist
472 `(("p" :base-directory
,base
:base-extension any
))))
473 (org-publish-get-project-from-filename file
)))
474 ;; Pathological case: Handle both :extension any and :recursive t.
476 (let* ((base (expand-file-name "examples/pub/" org-test-dir
))
477 (file (expand-file-name "sub/c.org" base
))
478 (org-publish-project-alist
479 `(("p" :base-directory
,base
:recursive t
:base-extension any
))))
480 (org-publish-get-base-files (org-publish-get-project-from-filename file
))))
481 ;; Check :exclude property.
483 (let* ((base (expand-file-name "examples/pub/" org-test-dir
))
484 (file (expand-file-name "a.org" base
))
485 (org-publish-project-alist
486 `(("p" :base-directory
,base
:exclude
"a"))))
487 (org-publish-get-project-from-filename file
)))
489 (let* ((base (expand-file-name "examples/pub/" org-test-dir
))
490 (file (expand-file-name "a.org" base
))
491 (org-publish-project-alist
492 `(("p" :base-directory
,base
:exclude
"other"))))
493 (org-publish-get-project-from-filename file
)))
494 ;; The regexp matches against relative file name, not absolute one.
496 (let* ((base (expand-file-name "examples/pub/" org-test-dir
))
497 (file (expand-file-name "a.org" base
))
498 (org-publish-project-alist
499 `(("p" :base-directory
,base
:exclude
"examples/pub"))))
500 (org-publish-get-project-from-filename file
)))
501 ;; Check :include property.
503 (let* ((base (expand-file-name "examples/pub/" org-test-dir
))
504 (file (expand-file-name "file.txt" base
))
505 (org-publish-project-alist
506 `(("p" :base-directory
,base
:include
(,file
)))))
507 (org-publish-get-project-from-filename file
)))
508 ;; :include property has precedence over :exclude one.
510 (let* ((base (expand-file-name "examples/pub/" org-test-dir
))
511 (file (expand-file-name "a.org" base
))
512 (org-publish-project-alist
514 :base-directory
,base
515 :include
(,(file-name-nondirectory file
))
517 (org-publish-get-project-from-filename file
)))
518 ;; With optional argument, return a meta-project publishing provided
522 (let* ((base (expand-file-name "examples/pub/" org-test-dir
))
523 (file (expand-file-name "a.org" base
))
524 (org-publish-project-alist
525 `(("meta" :components
("p"))
526 ("p" :base-directory
,base
))))
527 (car (org-publish-get-project-from-filename file t
))))))
529 (ert-deftest test-org-publish
/file-relative-name
()
530 "Test `org-publish-file-relative-name' specifications."
531 ;; Turn absolute file names into relative ones if file belongs to
535 (let* ((base (expand-file-name "examples/pub/" org-test-dir
))
536 (file (expand-file-name "a.org" base
)))
537 (org-publish-file-relative-name file
`(:base-directory
,base
)))))
540 (let* ((base (expand-file-name "examples/" org-test-dir
))
541 (file (expand-file-name "pub/a.org" base
)))
542 (org-publish-file-relative-name file
`(:base-directory
,base
)))))
543 ;; Absolute file names that do not belong to base directory are
547 (let ((base (expand-file-name "examples/pub/" org-test-dir
)))
548 (org-publish-file-relative-name "/name.org"
549 `(:base-directory
,base
)))))
550 ;; Relative file names are unchanged.
553 (let ((base (expand-file-name "examples/pub/" org-test-dir
)))
554 (org-publish-file-relative-name "a.org" `(:base-directory
,base
))))))
557 (provide 'test-ox-publish
)
558 ;;; test-ox-publish.el ends here