419 lines
17 KiB
EmacsLisp
419 lines
17 KiB
EmacsLisp
(require 'chronometrist)
|
|
|
|
(ert-deftest chronometrist-format-duration ()
|
|
(should
|
|
(equal (chronometrist-format-duration 0) " -"))
|
|
(should
|
|
(equal (chronometrist-format-duration 1) " 1"))
|
|
(should
|
|
(equal (chronometrist-format-duration 10) " 10"))
|
|
(should
|
|
(equal (chronometrist-format-duration 70) " 1:10"))
|
|
(should
|
|
(equal (chronometrist-format-duration (+ (* 10 60) 10))
|
|
" 10:10"))
|
|
(should
|
|
(equal (chronometrist-format-duration (+ (* 1 60 60) (* 10 60) 10))
|
|
" 1:10:10"))
|
|
(should
|
|
(equal (chronometrist-format-duration (+ (* 10 60 60) (* 10 60) 10))
|
|
"10:10:10")))
|
|
|
|
(ert-deftest chronometrist-previous-week-start ()
|
|
(let ((chronometrist-report-week-start-day "Sunday")
|
|
(ts (chronometrist-iso-date-to-ts "2018-09-02")))
|
|
(should (ts= (chronometrist-previous-week-start
|
|
(chronometrist-iso-date-to-ts "2018-09-01"))
|
|
(chronometrist-iso-date-to-ts "2018-08-26")))
|
|
(should (ts= ts (chronometrist-previous-week-start
|
|
(chronometrist-iso-date-to-ts "2018-09-02"))))
|
|
(should (ts= ts (chronometrist-previous-week-start
|
|
(chronometrist-iso-date-to-ts "2018-09-03"))))
|
|
(should (ts= ts (chronometrist-previous-week-start
|
|
(chronometrist-iso-date-to-ts "2018-09-04"))))
|
|
(should (ts= ts (chronometrist-previous-week-start
|
|
(chronometrist-iso-date-to-ts "2018-09-05"))))
|
|
(should (ts= ts (chronometrist-previous-week-start
|
|
(chronometrist-iso-date-to-ts "2018-09-06"))))
|
|
(should (ts= ts (chronometrist-previous-week-start
|
|
(chronometrist-iso-date-to-ts "2018-09-07"))))
|
|
(should (ts= ts (chronometrist-previous-week-start
|
|
(chronometrist-iso-date-to-ts "2018-09-08"))))))
|
|
|
|
(ert-deftest chronometrist-plist-remove ()
|
|
(should
|
|
|
|
(equal (chronometrist-plist-remove '(:a 1 :b 2 :c 3 :d 4) :a)
|
|
'(:b 2 :c 3 :d 4)))
|
|
(should
|
|
|
|
(equal (chronometrist-plist-remove '(:a 1 :b 2 :c 3 :d 4) :b)
|
|
'(:a 1 :c 3 :d 4)))
|
|
(should
|
|
(equal (chronometrist-plist-remove '(:a 1 :b 2 :c 3 :d 4) :c)
|
|
'(:a 1 :b 2 :d 4)))
|
|
(should
|
|
(equal (chronometrist-plist-remove '(:a 1 :b 2 :c 3 :d 4) :d)
|
|
'(:a 1 :b 2 :c 3)))
|
|
(should
|
|
(equal (chronometrist-plist-remove '(:a 1 :b 2 :c 3 :d 4) :a :b)
|
|
'(:c 3 :d 4)))
|
|
(should
|
|
(equal (chronometrist-plist-remove '(:a 1 :b 2 :c 3 :d 4) :a :d)
|
|
'(:b 2 :c 3)))
|
|
(should
|
|
(equal (chronometrist-plist-remove '(:a 1 :b 2 :c 3 :d 4) :c :d)
|
|
'(:a 1 :b 2)))
|
|
(should (equal
|
|
(chronometrist-plist-remove '(:a 1 :b 2 :c 3 :d 4) :a :b :c :d)
|
|
nil))
|
|
(should
|
|
(equal (chronometrist-plist-remove '(:a 1 :b 2 :c 3 :d 4) :d :a)
|
|
'(:b 2 :c 3))))
|
|
|
|
(ert-deftest plist-p ()
|
|
(should (eq t (chronometrist-plist-p '(:a 1 :b 2))))
|
|
(should (eq nil (chronometrist-plist-p '(0 :a 1 :b 2))))
|
|
(should (eq nil (chronometrist-plist-p '(:a 1 :b 2 3)))))
|
|
|
|
(ert-deftest plist-pp-buffer ()
|
|
(should
|
|
(equal
|
|
(chronometrist-plist-pp-to-string
|
|
'(:name "Task"
|
|
:tags (foo bar)
|
|
:comment ((70 . "baz")
|
|
"zot"
|
|
(16 . "frob")
|
|
(20 20 "quux"))
|
|
:start "2020-06-25T19:27:57+0530"
|
|
:stop "2020-06-25T19:43:30+0530"))
|
|
(concat
|
|
"(:name \"Task\"\n"
|
|
" :tags (foo bar)\n"
|
|
" :comment ((70 . \"baz\")\n"
|
|
" \"zot\"\n"
|
|
" (16 . \"frob\")\n"
|
|
" (20 20 \"quux\"))\n"
|
|
" :start \"2020-06-25T19:27:57+0530\"\n"
|
|
" :stop \"2020-06-25T19:43:30+0530\")")))
|
|
(should
|
|
(equal
|
|
(chronometrist-plist-pp-to-string
|
|
'(:name "Singing"
|
|
:tags (classical solo)
|
|
:piece ((:composer "Gioachino Rossini"
|
|
:name "Il barbiere di Siviglia"
|
|
:aria ("All'idea di quel metallo" "Dunque io son"))
|
|
(:composer "Ralph Vaughan Williams"
|
|
:name "Songs of Travel"
|
|
:movement ((4 . "Youth and Love")
|
|
(5 . "In Dreams")
|
|
(7 . "Wither Must I Wander?")))
|
|
(:composer "Ralph Vaughan Williams"
|
|
:name "Merciless Beauty"
|
|
:movement 1)
|
|
(:composer "Franz Schubert"
|
|
:name "Winterreise"
|
|
:movement ((1 . "Gute Nacht")
|
|
(2 . "Die Wetterfahne")
|
|
(4 . "Erstarrung"))))
|
|
:start "2020-11-01T12:01:20+0530"
|
|
:stop "2020-11-01T13:08:32+0530"))
|
|
(concat
|
|
"(:name \"Singing\"\n"
|
|
" :tags (classical solo)\n"
|
|
" :piece ((:composer \"Gioachino Rossini\"\n"
|
|
" :name \"Il barbiere di Siviglia\"\n"
|
|
" :aria (\"All'idea di quel metallo\" \"Dunque io son\"))\n"
|
|
" (:composer \"Ralph Vaughan Williams\"\n"
|
|
" :name \"Songs of Travel\"\n"
|
|
" :movement ((4 . \"Youth and Love\")\n"
|
|
" (5 . \"In Dreams\")\n"
|
|
" (7 . \"Wither Must I Wander?\")))\n"
|
|
" (:composer \"Ralph Vaughan Williams\"\n"
|
|
" :name \"Merciless Beauty\"\n"
|
|
" :movement 1)\n"
|
|
" (:composer \"Franz Schubert\"\n"
|
|
" :name \"Winterreise\"\n"
|
|
" :movement ((1 . \"Gute Nacht\")\n"
|
|
" (2 . \"Die Wetterfahne\")\n"
|
|
" (4 . \"Erstarrung\"))))\n"
|
|
" :start \"2020-11-01T12:01:20+0530\"\n"
|
|
" :stop \"2020-11-01T13:08:32+0530\")")))
|
|
(should (equal
|
|
(chronometrist-plist-pp-to-string
|
|
'(:name "Cooking"
|
|
:tags (lunch)
|
|
:recipe (:name "moong-masoor ki dal"
|
|
:url "https://www.mirchitales.com/moong-masoor-dal-red-and-yellow-lentil-curry/")
|
|
:start "2020-09-23T15:22:39+0530"
|
|
:stop "2020-09-23T16:29:49+0530"))
|
|
(concat
|
|
"(:name \"Cooking\"\n"
|
|
" :tags (lunch)\n"
|
|
" :recipe (:name \"moong-masoor ki dal\"\n"
|
|
" :url \"https://www.mirchitales.com/moong-masoor-dal-red-and-yellow-lentil-curry/\")\n"
|
|
" :start \"2020-09-23T15:22:39+0530\"\n"
|
|
" :stop \"2020-09-23T16:29:49+0530\")")))
|
|
(should (equal
|
|
(chronometrist-plist-pp-to-string
|
|
'(:name "Exercise"
|
|
:tags (warm-up)
|
|
:start "2018-11-21T15:35:04+0530"
|
|
:stop "2018-11-21T15:38:41+0530"
|
|
:comment ("stretching" (25 10 "push-ups"))))
|
|
(concat
|
|
"(:name \"Exercise\"\n"
|
|
" :tags (warm-up)\n"
|
|
" :start \"2018-11-21T15:35:04+0530\"\n"
|
|
" :stop \"2018-11-21T15:38:41+0530\"\n"
|
|
" :comment (\"stretching\" (25 10 \"push-ups\")))"))))
|
|
|
|
(defvar chronometrist-test-file
|
|
(make-temp-file
|
|
"chronometrist-test-" nil ".sexp"
|
|
(with-output-to-string
|
|
(mapc
|
|
(lambda (plist)
|
|
;; to use this, we'd have to move `chronometrist-plist-pp' before this
|
|
;; definition, and I'm perfectly content with where it is
|
|
;; right now
|
|
(chronometrist-plist-pp plist) (princ "\n\n")
|
|
;; (print plist) (princ "\n")
|
|
)
|
|
'((:name "Programming"
|
|
:start "2018-01-01T00:00:00+0530"
|
|
:stop "2018-01-01T01:00:00+0530")
|
|
(:name "Swimming"
|
|
:start "2018-01-01T02:00:00+0530"
|
|
:stop "2018-01-01T03:00:00+0530")
|
|
(:name "Cooking"
|
|
:start "2018-01-01T04:00:00+0530"
|
|
:stop "2018-01-01T05:00:00+0530")
|
|
(:name "Guitar"
|
|
:start "2018-01-01T06:00:00+0530"
|
|
:stop "2018-01-01T07:00:00+0530")
|
|
(:name "Cycling"
|
|
:start "2018-01-01T08:00:00+0530"
|
|
:stop "2018-01-01T09:00:00+0530")
|
|
(:name "Programming"
|
|
:start "2018-01-02T23:00:00+0530"
|
|
:stop "2018-01-03T01:00:00+0530")
|
|
(:name "Cooking"
|
|
:start "2018-01-03T23:00:00+0530"
|
|
:stop "2018-01-04T01:00:00+0530")
|
|
(:name "Programming"
|
|
:tags (bug-hunting)
|
|
:project "Chronometrist"
|
|
:component "goals"
|
|
:start "2020-05-09T20:03:25+0530"
|
|
:stop "2020-05-09T20:05:55+0530")
|
|
(:name "Arrangement/new edition"
|
|
:tags (new edition)
|
|
:song "Songs of Travel"
|
|
:composer "Vaughan Williams, Ralph"
|
|
:start "2020-05-10T00:04:14+0530"
|
|
:stop "2020-05-10T00:25:48+0530")
|
|
(:name "Guitar"
|
|
:tags (classical warm-up)
|
|
:start "2020-05-10T15:41:14+0530"
|
|
:stop "2020-05-10T15:55:42+0530")
|
|
(:name "Guitar"
|
|
:tags (classical solo)
|
|
:start "2020-05-10T16:00:00+0530"
|
|
:stop "2020-05-10T16:30:00+0530")
|
|
(:name "Programming"
|
|
:tags (reading)
|
|
:book "Smalltalk-80: The Language and Its Implementation"
|
|
:start "2020-05-10T16:33:17+0530"
|
|
:stop "2020-05-10T17:10:48+0530"))))))
|
|
|
|
(defmacro chronometrist-tests--change-type-and-update (state)
|
|
`(prog1 (chronometrist-file-change-type ,state)
|
|
(setq ,state
|
|
(list :last (chronometrist-file-hash :before-last nil)
|
|
:rest (chronometrist-file-hash nil :before-last t)))))
|
|
|
|
(ert-deftest task-list ()
|
|
(let ((task-list (chronometrist-task-list)))
|
|
(should (listp task-list))
|
|
(should (seq-every-p #'stringp task-list))))
|
|
|
|
(ert-deftest file-hash ()
|
|
(-let* ((chronometrist-file chronometrist-test-file)
|
|
((last-start last-end)
|
|
(chronometrist-file-hash :before-last nil))
|
|
((rest-start rest-end rest-hash)
|
|
(chronometrist-file-hash nil :before-last t)))
|
|
(message "chronometrist - file-hash test - file path is %s"
|
|
chronometrist-test-file)
|
|
(should (= 1 rest-start))
|
|
(should (= 1254 rest-end))
|
|
(should (= 1256 last-start))
|
|
(should (= 1426 last-end))))
|
|
|
|
(ert-deftest chronometrist-file-change-type ()
|
|
(let* ((chronometrist-file chronometrist-test-file)
|
|
(test-contents (with-current-buffer (find-file-noselect chronometrist-file)
|
|
(buffer-substring (point-min) (point-max))))
|
|
(chronometrist--file-state-old chronometrist--file-state)
|
|
(chronometrist--file-state (list :last (chronometrist-file-hash :before-last nil)
|
|
:rest (chronometrist-file-hash nil :before-last t)))
|
|
(chronometrist-events-old chronometrist-events))
|
|
(chronometrist-events-populate)
|
|
(unwind-protect
|
|
(progn
|
|
(should
|
|
(eq nil (chronometrist-file-change-type chronometrist--file-state)))
|
|
(should
|
|
(eq :append
|
|
(progn
|
|
(chronometrist-sexp-new
|
|
'(:name "Append Test"
|
|
:start "2021-02-01T13:06:46+0530"
|
|
:stop "2021-02-01T13:06:49+0530"))
|
|
(chronometrist-tests--change-type-and-update chronometrist--file-state))))
|
|
(should
|
|
(eq :modify
|
|
(progn
|
|
(chronometrist-sexp-replace-last
|
|
'(:name "Modify Test"
|
|
:tags (some tags)
|
|
:start "2021-02-01T13:06:46+0530"
|
|
:stop "2021-02-01T13:06:49+0530"))
|
|
(chronometrist-tests--change-type-and-update chronometrist--file-state))))
|
|
(should
|
|
(eq :remove
|
|
(progn
|
|
(chronometrist-sexp-in-file chronometrist-file
|
|
(goto-char (point-max))
|
|
(backward-list 1)
|
|
(chronometrist-sexp-delete-list 1)
|
|
(save-buffer))
|
|
(chronometrist-tests--change-type-and-update chronometrist--file-state))))
|
|
(should
|
|
(eq t
|
|
(progn
|
|
(chronometrist-sexp-in-file chronometrist-file
|
|
(goto-char (point-min))
|
|
(chronometrist-plist-pp '(:name "Other Change Test"
|
|
:start "2021-02-02T17:39:40+0530"
|
|
:stop "2021-02-02T17:39:44+0530")
|
|
(current-buffer))
|
|
(save-buffer))
|
|
(chronometrist-tests--change-type-and-update chronometrist--file-state)))))
|
|
;; restore test file contents
|
|
(with-current-buffer (find-file-noselect chronometrist-file)
|
|
(delete-region (point-min) (point-max))
|
|
(insert test-contents)
|
|
(save-buffer))
|
|
(setq chronometrist--file-state chronometrist--file-state-old
|
|
chronometrist-events chronometrist-events-old))))
|
|
|
|
(ert-deftest chronometrist-apply-time ()
|
|
(should
|
|
(equal (ts-format "%FT%T%z" (chronometrist-apply-time "01:02:03" "2021-02-17T01:20:18+0530"))
|
|
"2021-02-17T01:02:03+0530")))
|
|
|
|
(ert-deftest chronometrist-events-maybe-split ()
|
|
(should
|
|
(null (chronometrist-events-maybe-split
|
|
'(:name "Task"
|
|
:start "2021-02-17T01:33:12+0530"
|
|
:stop "2021-02-17T01:56:08+0530"))))
|
|
(should
|
|
(equal (chronometrist-events-maybe-split
|
|
'(:name "Guitar"
|
|
:tags (classical warm-up)
|
|
:start "2021-02-12T23:45:21+0530"
|
|
:stop "2021-02-13T00:03:46+0530"))
|
|
'((:name "Guitar"
|
|
:tags (classical warm-up)
|
|
:start "2021-02-12T23:45:21+0530"
|
|
:stop "2021-02-13T00:00:00+0530")
|
|
(:name "Guitar"
|
|
:tags (classical warm-up)
|
|
:start "2021-02-13T00:00:00+0530"
|
|
:stop "2021-02-13T00:03:46+0530")))))
|
|
|
|
(ert-deftest chronometrist-task-time-one-day ()
|
|
(let ((chronometrist-file-old chronometrist-file)
|
|
(chronometrist-file chronometrist-test-file)
|
|
(chronometrist--file-state-old chronometrist--file-state)
|
|
(chronometrist-events-old chronometrist-events)
|
|
(ts-1 (chronometrist-iso-date-to-ts "2018-01-01"))
|
|
(ts-2 (chronometrist-iso-date-to-ts "2018-01-02"))
|
|
(ts-3 (chronometrist-iso-date-to-ts "2018-01-03"))
|
|
(1-hour 3600))
|
|
(chronometrist-events-populate)
|
|
(unwind-protect
|
|
(progn
|
|
(should
|
|
(equal (chronometrist-task-time-one-day "Programming" ts-1)
|
|
1-hour))
|
|
(should
|
|
(equal (chronometrist-task-time-one-day "Swimming" ts-1)
|
|
1-hour))
|
|
(should
|
|
(equal (chronometrist-task-time-one-day "Cooking" ts-1)
|
|
1-hour))
|
|
(should
|
|
(equal (chronometrist-task-time-one-day "Guitar" ts-1)
|
|
1-hour))
|
|
(should
|
|
(equal (chronometrist-task-time-one-day "Cycling" ts-1)
|
|
1-hour))
|
|
(should
|
|
(equal (chronometrist-task-time-one-day "Programming" ts-2)
|
|
1-hour))
|
|
(should
|
|
(equal (chronometrist-task-time-one-day "Programming" ts-3)
|
|
1-hour)))
|
|
(setq chronometrist-file chronometrist-file-old
|
|
chronometrist--file-state chronometrist--file-state-old)
|
|
;; Not sure why simply assigning `chronometrist-events-old' did not restore
|
|
;; the value - it seems to work in `chronometrist-file-change-type'
|
|
(chronometrist-events-populate))))
|
|
|
|
(ert-deftest chronometrist-midnight-spanning-p ()
|
|
(should
|
|
(null
|
|
(chronometrist-midnight-spanning-p "2021-02-17T01:33:12+0530"
|
|
"2021-02-17T01:56:08+0530"
|
|
"00:00:00")))
|
|
(should
|
|
(equal
|
|
(chronometrist-midnight-spanning-p "2021-02-19T23:45:36+0530"
|
|
"2021-02-20T00:18:40+0530"
|
|
"00:00:00")
|
|
'((:start "2021-02-19T23:45:36+0530"
|
|
:stop "2021-02-20T00:00:00+0530")
|
|
(:start "2021-02-20T00:00:00+0530"
|
|
:stop "2021-02-20T00:18:40+0530"))))
|
|
(should
|
|
(equal
|
|
(chronometrist-midnight-spanning-p "2021-02-19T23:45:36+0530"
|
|
"2021-02-20T03:18:40+0530"
|
|
"01:20:30")
|
|
'((:start "2021-02-19T23:45:36+0530"
|
|
:stop "2021-02-20T01:20:30+0530")
|
|
(:start "2021-02-20T01:20:30+0530"
|
|
:stop "2021-02-20T03:18:40+0530")))))
|
|
|
|
(ert-deftest chronometrist-details-row-helper ()
|
|
(let ((tags '(a b c))
|
|
(plist '(:a 1 :b 2 :c 3)))
|
|
(let ((chronometrist-details-display-tags nil)
|
|
(chronometrist-details-display-key-values nil))
|
|
(should (equal (chronometrist-details-rows-helper tags) ""))
|
|
(should (equal (chronometrist-details-rows-helper plist) "")))
|
|
(let ((chronometrist-details-display-tags "%s")
|
|
(chronometrist-details-display-key-values "%s"))
|
|
(should (equal (chronometrist-details-rows-helper nil) ""))
|
|
(should (equal (chronometrist-details-rows-helper nil) ""))
|
|
(should (equal (chronometrist-details-rows-helper tags)
|
|
"a b c"))
|
|
(should (equal (chronometrist-details-rows-helper plist)
|
|
"1 2 3")))))
|