Create and Automate Tests for Khoj.el on Emacs

- Use ERT to test `khoj.el'
- Test extracting and rendering of Org, Markdown and Ledger entries from Khoj API response
- Automate `khoj.el' testing using Github workflow
- Fix, Simplify and Test the get text around point code for the "Find Similar" feature
This commit is contained in:
Debanjum 2023-01-23 20:40:18 -03:00 committed by GitHub
commit 477ef28e08
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 325 additions and 27 deletions

49
.github/workflows/test_khoj_el.yml vendored Normal file
View file

@ -0,0 +1,49 @@
name: test khoj.el
on:
push:
branches:
- 'master'
paths:
- src/interface/emacs/*.el
- src/interface/emacs/tests/*.el
- .github/workflows/test_khoj_el.yml
pull_request:
branches:
- 'master'
paths:
- src/interface/emacs/*.el
- src/interface/emacs/tests/*.el
- .github/workflows/test_khoj_el.yml
jobs:
test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
emacs_version:
- 27.1
- 27.2
- 28.1
- 28.2
- snapshot
steps:
- uses: purcell/setup-emacs@master
with:
version: ${{ matrix.emacs_version }}
- uses: actions/checkout@v3
- name: Test Khoj.el
run: |
# Run ERT tests on khoj.el
emacs -batch \
--eval "(progn \
(require 'package) \
(push '(\"melpa\" . \"https://melpa.org/packages/\") package-archives) \
(package-initialize) \
(unless package-archive-contents (package-refresh-contents)) \
(unless (package-installed-p 'transient) (package-install 'transient)))" \
-l ert \
-l ./src/interface/emacs/khoj.el \
-l ./src/interface/emacs/tests/khoj-tests.el \
-f ert-run-tests-batch-and-exit

View file

@ -50,6 +50,7 @@
(require 'json)
(require 'transient)
(require 'outline)
(eval-when-compile (require 'subr-x)) ;; for string-trim before Emacs 28.2
;; -------------------------
@ -385,35 +386,32 @@ Use `which-key` if available, else display simple message in echo area"
(defun khoj--get-current-outline-entry-text ()
"Get text under current outline section."
(with-current-buffer (current-buffer)
;; jump to cursor in current buffer
(goto-char (point))
;; trim leading whitespaces from text
(replace-regexp-in-string
"^[ \t\n]*" ""
;; trim trailing whitespaces from text
(replace-regexp-in-string
"[ \t\n]*$" ""
;; get text of current outline entry
(buffer-substring-no-properties
(save-excursion (outline-previous-heading) (point))
(save-excursion (outline-next-heading) (point)))))))
(string-trim
;; get text of current outline entry
(cond
;; when at heading of entry
((looking-at outline-regexp)
(buffer-substring-no-properties
(point)
(save-excursion (outline-next-heading) (point))))
;; when within entry
(t (buffer-substring-no-properties
(save-excursion (outline-previous-heading) (point))
(save-excursion (outline-next-heading) (point)))))))
(defun khoj--get-current-paragraph-text ()
"Get text in current paragraph at point."
(with-current-buffer (current-buffer)
;; jump to cursor in current buffer
(goto-char (point))
;; trim leading whitespaces from text
(replace-regexp-in-string
"^[ \t\n]*" ""
;; trim trailing whitespaces from text
(replace-regexp-in-string
"[ \t\n]*$" ""
;; get text of current entry
(buffer-substring-no-properties
(save-excursion (backward-paragraph) (point))
(save-excursion (forward-paragraph) (point)))))))
"Get trimmed text in current paragraph at point.
Paragraph only starts at first text after blank line."
(string-trim
(cond
;; when at end of a middle paragraph
((and (looking-at paragraph-start) (not (equal (point) (point-min))))
(buffer-substring-no-properties
(save-excursion (backward-paragraph) (point))
(point)))
;; else
(t (thing-at-point 'paragraph t)))))
(defun khoj--find-similar (&optional content-type)
"Find items of CONTENT-TYPE in khoj index similar to text surrounding point."

View file

@ -0,0 +1,251 @@
;;; khoj-tests.el --- Test suite for khoj.el -*- lexical-binding: t -*-
;; Copyright (C) 2023 Debanjum Singh Solanky
;; Author: Debanjum Singh Solanky <debanjum@gmail.com>
;; Version: 0.0.0
;; Package-Requires: ((emacs "27.1") (transient "0.3.0"))
;; URL: https://github.com/debanjum/khoj/tree/master/src/interface/emacs
;;; License:
;; This program 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.
;; This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;; This file contains the test suite for khoj.el.
;;; Code:
(require 'ert)
(require 'khoj)
;; ----------------------------------------------------
;; Test Extract and Render Entries of each Content Type
;; ----------------------------------------------------
(ert-deftest khoj-tests--extract-entries-as-markdown ()
"Test `json-response', `query' from API formatted as markdown."
(let ((user-query "Become God")
(json-response-from-khoj-backend
(json-read-from-string
"[\
{\
\"entry\": \"## Upgrade\\n\\n Penance to Immortality\\n\",\
\"score\": \"0.376\",\
\"additional\": {\
\"file\": \"/home/ravan/upgrade.md\",\
\"compiled\": \"## Upgrade Penance to Immortality\"\
}\
},\
{\
\"entry\": \"## Act\\n\\n Rule everything\\n\",\
\"score\": \"0.153\",\
\"additional\": {\
\"file\": \"/home/ravan/act.md\",\
\"compiled\": \"## Act Rule everything\"\
}\
}]\
")))
(should
(equal
(khoj--extract-entries-as-markdown json-response-from-khoj-backend user-query)
"\
# Become God\n\
## Upgrade\n\
\n\
Penance to Immortality\n\
## Act\n\
\n\
Rule everything\n"))))
(ert-deftest khoj-tests--extract-entries-as-org ()
"Test `json-response', `query' from API formatted as org."
(let ((user-query "Become God")
(json-response-from-khoj-backend
(json-read-from-string
"[\
{\
\"entry\": \"** Upgrade\\n\\n Penance to Immortality\\n\",\
\"score\": \"0.42\",\
\"additional\": {\
\"file\": \"/home/ravan/upgrade.md\",\
\"compiled\": \"** Upgrade Penance to Immortality\"\
}\
},\
{\
\"entry\": \"** Act\\n\\n Rule everything\\n\",\
\"score\": \"0.42\",\
\"additional\": {\
\"file\": \"/home/ravan/act.md\",\
\"compiled\": \"** Act Rule everything\"\
}\
}]\
")))
(should
(equal
(khoj--extract-entries-as-org json-response-from-khoj-backend user-query)
"\
* Become God\n\
** Upgrade\n\
\n\
Penance to Immortality\n\
** Act\n\
\n\
Rule everything\n\
\n\
#+STARTUP: showall hidestars inlineimages"))))
(ert-deftest khoj-tests--extract-entries-as-ledger ()
"Test `json-response', `query' from API formatted as beancount ledger."
(let ((user-query "Become God")
(json-response-from-khoj-backend
(json-read-from-string
"[\
{\
\"entry\": \"4242-04-01 * \\\"Penance Center\\\" \\\"Book Stay for 10,000 Years\\\"\\n Expenses:Health:Mental 15 GOLD\\n Assets:Commodities:Gold\",\
\"score\": \"0.42\",\
\"additional\": {\
\"file\": \"/home/ravan/ledger.beancount\",\
\"compiled\": \"4242-04-01 * \\\"Penance Center\\\" \\\"Book Stay for 10,000 Years\\\" Expenses:Health:Mental 15 GOLD Assets:Commodities:Gold\"\
}\
},\
{\
\"entry\": \"14242-04-01 * \\\"Brahma\\\" \\\"Boon for Invincibility from Higher Beings\\\"\\n Income:Health -1,00,00,000 LIFE\\n Assets:Commodities:Life\",\
\"score\": \"0.42\",\
\"additional\": {\
\"file\": \"/home/ravan/ledger.beancount\",\
\"compiled\": \"4242-04-01 * \\\"Brahma\\\" \\\"Boon for Invincibility from Higher Beings\\\" Income:Health -1,00,00,000 LIFE Assets:Commodities:Life\"\
}\
}]\
")))
(should
(equal
(khoj--extract-entries-as-ledger json-response-from-khoj-backend user-query)
";; Become God\n\
\n\
4242-04-01 * \"Penance Center\" \"Book Stay for 10,000 Years\"\n\
Expenses:Health:Mental 15 GOLD\n\
Assets:Commodities:Gold\n\
\n\
14242-04-01 * \"Brahma\" \"Boon for Invincibility from Higher Beings\"\n\
Income:Health -1,00,00,000 LIFE\n\
Assets:Commodities:Life\n\
\n\
\n\
"))))
;; -------------------------------------
;; Test Helpers for Find Similar Feature
;; -------------------------------------
(ert-deftest khoj-tests--get-current-outline-entry-text ()
"Test get current outline-mode entry text'."
(with-temp-buffer
(insert "\
* Become God\n\
** Upgrade\n\
\n\
Penance to Immortality\n\
** Act\n\
\n\
Rule everything\\n")
(goto-char (point-min))
;; Test getting current entry text from cursor at start of outline heading
(outline-next-visible-heading 1)
(should
(equal
(khoj--get-current-outline-entry-text)
"\
** Upgrade\n\
\n\
Penance to Immortality"))
;; Test getting current entry text from cursor within outline entry
(forward-line)
(should
(equal
(khoj--get-current-outline-entry-text)
"\
** Upgrade\n\
\n\
Penance to Immortality"))
))
(ert-deftest khoj-tests--get-current-paragraph-text ()
"Test get current paragraph text'."
(with-temp-buffer
(insert "\
* Become God\n\
** Upgrade\n\
\n\
Penance to Immortality\n\
** Act\n\
\n\
Rule everything\n")
;; Test getting current paragraph text from cursor at start of buffer
(goto-char (point-min))
(should
(equal
(khoj--get-current-paragraph-text)
"* Become God\n\
** Upgrade"))
;; Test getting current paragraph text from cursor within paragraph
(goto-char (point-min))
(forward-line 1)
(should
(equal
(khoj--get-current-paragraph-text)
"* Become God\n\
** Upgrade"))
;; Test getting current paragraph text from cursor at paragraph end
(goto-char (point-min))
(forward-line 2)
(should
(equal
(khoj--get-current-paragraph-text)
"* Become God\n\
** Upgrade"))
;; Test getting current paragraph text from cursor at start of middle paragraph
(goto-char (point-min))
(forward-line 3)
(should
(equal
(khoj--get-current-paragraph-text)
"Penance to Immortality\n\
** Act"))
;; Test getting current paragraph text from cursor at end of buffer
(goto-char (point-max))
(should
(equal
(khoj--get-current-paragraph-text)
"Rule everything"))
))
(provide 'khoj-tests)
;;; khoj-tests.el ends here