Stabilize responsive Playground app layout
This commit is contained in:
parent
dcb0ad9d83
commit
4bdf5ddaca
11
DESIGN.md
11
DESIGN.md
@ -115,10 +115,13 @@
|
||||
## Responsive behavior
|
||||
|
||||
- Wide/fullscreen: three-column grid (rail / list / detail).
|
||||
- Compact: rail becomes a top filter row, detail follows the list, and all
|
||||
controls remain intrinsic single-line widths.
|
||||
- Use `grid` for the product skeleton, `flex` for toolbars and action groups,
|
||||
and `row` only for compact intrinsic controls.
|
||||
- Compact: the same grid uses zero-minimum fractional tracks; rail, list, and
|
||||
detail shrink within the viewport instead of imposing min-content overflow,
|
||||
while the action group wraps through Flex and long table cells wrap inside
|
||||
their tracks.
|
||||
- Use `grid` for the product skeleton, `flex` for toolbars/action groups, and
|
||||
`row` only for compact intrinsic controls. `minmax(0, fr)` is the responsive
|
||||
track contract; do not reintroduce fixed child widths at the shell boundary.
|
||||
|
||||
## Interaction states
|
||||
|
||||
|
||||
@ -69,8 +69,11 @@ Component 边界,避免新增 helper 层或抽象泄漏。
|
||||
## 响应式与验证
|
||||
|
||||
- Wide/fullscreen 使用 rail / list / detail 三列 grid。
|
||||
- Compact 时筛选栏收为顶部工具行,detail 位于 list 后面;不使用固定宽度撑坏
|
||||
viewport,所有操作控件仍保持独立 hover/focus 语义。
|
||||
- Compact 时仍使用三列骨架,但每列采用零最小值的 fractional track,在 viewport
|
||||
内收缩而不是被 min-content 撑出边界;长表格单元格在自己的 track 内换行,动作组
|
||||
由 Flex 自动换行。不要在 shell 边界重新引入固定宽度。
|
||||
- `minmax(0, fr)` 是响应式 track 合同;`grid` 负责骨架,`flex` 负责 toolbar/action
|
||||
group,`row` 只负责紧凑 intrinsic 控件,所有操作控件仍保持独立 hover/focus 语义。
|
||||
- 用 SQLite 临时文件测试 mount/remount、筛选、分页、重复选行、mutation、错误
|
||||
状态和 cleanup;GUI 用干净 fullscreen 单窗口截图验证真实布局。
|
||||
- 目标:一次 Data mutation 对应一次 Runtime generation/publication;warm 交互
|
||||
|
||||
@ -126,27 +126,33 @@ ENTRY must contain a string `:pair', symbol `:root-component', symbol
|
||||
(with-current-buffer buffer (setq etaf-playground-current-example name))
|
||||
buffer))
|
||||
|
||||
(defun etaf-playground--display-buffer (buffer)
|
||||
"Display BUFFER interactively and return it."
|
||||
(unless noninteractive (pop-to-buffer buffer))
|
||||
buffer)
|
||||
(defun etaf-playground--mount-for-display (buffer-name name)
|
||||
"Display BUFFER-NAME before mounting pair NAME when running in a GUI.
|
||||
|
||||
Ebox resolves viewport-relative widths from the window that owns the target
|
||||
buffer. Mounting first would make an off-window daemon/terminal window the
|
||||
initial containing block, leaving a responsive pair permanently laid out at
|
||||
that stale width until a later explicit resize."
|
||||
(unless noninteractive
|
||||
;; Keep the current window as the containing block. `pop-to-buffer' may
|
||||
;; split a clean frame, cutting a responsive three-column app in half.
|
||||
(switch-to-buffer (get-buffer-create buffer-name)))
|
||||
(etaf-playground-mount-example buffer-name name))
|
||||
|
||||
;;;###autoload
|
||||
(defun etaf-playground-open (&optional buffer-name)
|
||||
"Open the registered default pair in BUFFER-NAME."
|
||||
(interactive)
|
||||
(etaf-playground--display-buffer
|
||||
(etaf-playground-mount-example
|
||||
(or buffer-name etaf-playground-buffer-name)
|
||||
etaf-playground-default-pair)))
|
||||
(etaf-playground--mount-for-display
|
||||
(or buffer-name etaf-playground-buffer-name)
|
||||
etaf-playground-default-pair))
|
||||
|
||||
;;;###autoload
|
||||
(defun etaf-playground-open-example (name &optional buffer-name)
|
||||
"Open registered pair NAME in BUFFER-NAME."
|
||||
(interactive (list (completing-read "Pair: " etaf-playground-example-names)))
|
||||
(etaf-playground--display-buffer
|
||||
(etaf-playground-mount-example
|
||||
(or buffer-name etaf-playground-buffer-name) name)))
|
||||
(etaf-playground--mount-for-display
|
||||
(or buffer-name etaf-playground-buffer-name) name))
|
||||
|
||||
;;;###autoload
|
||||
(defun etaf-playground-reset (&optional buffer-name)
|
||||
@ -158,8 +164,7 @@ ENTRY must contain a string `:pair', symbol `:root-component', symbol
|
||||
buffer))
|
||||
etaf-playground-default-pair)))
|
||||
(unless buffer (user-error "No ETAF Playground pair is mounted"))
|
||||
(etaf-playground--display-buffer
|
||||
(etaf-playground-mount-example name pair))))
|
||||
(etaf-playground--mount-for-display name pair)))
|
||||
|
||||
;;;###autoload
|
||||
(defun etaf-playground-close (&optional buffer-name)
|
||||
|
||||
@ -198,10 +198,45 @@ Show MESSAGE on success, or preserve the resulting error state."
|
||||
(concat "● " label)
|
||||
label)))
|
||||
|
||||
(defun etaf-research-shelf--button-style (palette variant disabled)
|
||||
"Return theme-aware style props for a Research Shelf action button.
|
||||
|
||||
The public `button' Component owns interaction and pressed state; this small
|
||||
adapter only maps the app palette to its ordinary presentation props so ghost
|
||||
buttons do not fall back to a light-theme paper surface in dark mode."
|
||||
(let ((secondary (eq variant 'secondary)))
|
||||
(list :color (plist-get palette (if disabled :muted
|
||||
(if secondary :paper :ink)))
|
||||
:bgcolor (plist-get palette (if disabled :soft
|
||||
(if secondary :mint :panel)))
|
||||
:border (plist-get palette (if secondary :mint :line))
|
||||
:face (if (and secondary (not disabled)) 'bold 'normal))))
|
||||
|
||||
(etaf-define-component etaf-research-shelf-button
|
||||
(&key theme label ref variant disabled on-press)
|
||||
"Compose the public Button with the Research Shelf theme palette."
|
||||
:setup
|
||||
(lambda ()
|
||||
(let* ((theme (etaf-current-prop :theme))
|
||||
(label (etaf-current-prop :label))
|
||||
(ref (etaf-current-prop :ref))
|
||||
(variant (etaf-current-prop :variant))
|
||||
(disabled (etaf-current-prop :disabled))
|
||||
(on-press (etaf-current-prop :on-press))
|
||||
(style (etaf-research-shelf--button-style
|
||||
theme variant disabled)))
|
||||
(etaf-view
|
||||
(button :label label :ref ref :variant variant :disabled disabled
|
||||
:on-press on-press
|
||||
:color (plist-get style :color)
|
||||
:bgcolor (plist-get style :bgcolor)
|
||||
:border (plist-get style :border)
|
||||
:face (plist-get style :face))))))
|
||||
|
||||
(defun etaf-research-shelf--filter-view (model form)
|
||||
"Return the filter rail from MODEL and static FILTER FORM."
|
||||
(etaf-view
|
||||
(column :class "research-shelf-filter-rail" :width 'stretch
|
||||
(column :class "research-shelf-filter-rail" :width 'stretch :min-width 0
|
||||
:padding '(1 1)
|
||||
:border (etaf-research-shelf--color model :line)
|
||||
:color (etaf-research-shelf--color model :ink)
|
||||
@ -211,40 +246,45 @@ Show MESSAGE on success, or preserve the resulting error state."
|
||||
:bgcolor (etaf-research-shelf--color model :panel))
|
||||
(label :text "VIEWS" :color (etaf-research-shelf--color model :muted)
|
||||
:bgcolor (etaf-research-shelf--color model :panel))
|
||||
(button :label (etaf-research-shelf--filter-label model form 'all "All")
|
||||
:ref 'research-shelf-filter-all
|
||||
:variant (if (eq (etaf-value (plist-get model :filter)) 'all)
|
||||
'secondary 'ghost)
|
||||
:on-press (lambda ()
|
||||
(etaf-research-shelf--set-filter model 'all)))
|
||||
(button :label (etaf-research-shelf--filter-label
|
||||
model form 'reading "In progress")
|
||||
:ref 'research-shelf-filter-reading
|
||||
:variant (if (eq (etaf-value (plist-get model :filter)) 'reading)
|
||||
'secondary 'ghost)
|
||||
:on-press (lambda ()
|
||||
(etaf-research-shelf--set-filter model 'reading)))
|
||||
(button :label (etaf-research-shelf--filter-label
|
||||
model form 'unread "Unread")
|
||||
:ref 'research-shelf-filter-unread
|
||||
:variant (if (eq (etaf-value (plist-get model :filter)) 'unread)
|
||||
'secondary 'ghost)
|
||||
:on-press (lambda ()
|
||||
(etaf-research-shelf--set-filter model 'unread)))
|
||||
(button :label (etaf-research-shelf--filter-label
|
||||
model form 'finished "Finished")
|
||||
:ref 'research-shelf-filter-finished
|
||||
:variant (if (eq (etaf-value (plist-get model :filter)) 'finished)
|
||||
'secondary 'ghost)
|
||||
:on-press (lambda ()
|
||||
(etaf-research-shelf--set-filter model 'finished)))
|
||||
(button :label (etaf-research-shelf--filter-label
|
||||
model form 'starred "★ Starred")
|
||||
:ref 'research-shelf-filter-starred
|
||||
:variant (if (eq (etaf-value (plist-get model :filter)) 'starred)
|
||||
'secondary 'ghost)
|
||||
:on-press (lambda ()
|
||||
(etaf-research-shelf--set-filter model 'starred)))
|
||||
(etaf-research-shelf-button
|
||||
:theme (etaf-research-shelf--theme model)
|
||||
:label (etaf-research-shelf--filter-label model form 'all "All")
|
||||
:ref 'research-shelf-filter-all
|
||||
:variant (if (eq (etaf-value (plist-get model :filter)) 'all)
|
||||
'secondary 'ghost)
|
||||
:on-press (lambda () (etaf-research-shelf--set-filter model 'all)))
|
||||
(etaf-research-shelf-button
|
||||
:theme (etaf-research-shelf--theme model)
|
||||
:label (etaf-research-shelf--filter-label
|
||||
model form 'reading "In progress")
|
||||
:ref 'research-shelf-filter-reading
|
||||
:variant (if (eq (etaf-value (plist-get model :filter)) 'reading)
|
||||
'secondary 'ghost)
|
||||
:on-press (lambda () (etaf-research-shelf--set-filter model 'reading)))
|
||||
(etaf-research-shelf-button
|
||||
:theme (etaf-research-shelf--theme model)
|
||||
:label (etaf-research-shelf--filter-label
|
||||
model form 'unread "Unread")
|
||||
:ref 'research-shelf-filter-unread
|
||||
:variant (if (eq (etaf-value (plist-get model :filter)) 'unread)
|
||||
'secondary 'ghost)
|
||||
:on-press (lambda () (etaf-research-shelf--set-filter model 'unread)))
|
||||
(etaf-research-shelf-button
|
||||
:theme (etaf-research-shelf--theme model)
|
||||
:label (etaf-research-shelf--filter-label
|
||||
model form 'finished "Finished")
|
||||
:ref 'research-shelf-filter-finished
|
||||
:variant (if (eq (etaf-value (plist-get model :filter)) 'finished)
|
||||
'secondary 'ghost)
|
||||
:on-press (lambda () (etaf-research-shelf--set-filter model 'finished)))
|
||||
(etaf-research-shelf-button
|
||||
:theme (etaf-research-shelf--theme model)
|
||||
:label (etaf-research-shelf--filter-label
|
||||
model form 'starred "★ Starred")
|
||||
:ref 'research-shelf-filter-starred
|
||||
:variant (if (eq (etaf-value (plist-get model :filter)) 'starred)
|
||||
'secondary 'ghost)
|
||||
:on-press (lambda () (etaf-research-shelf--set-filter model 'starred)))
|
||||
(spacer :height 1)
|
||||
(label :text "STORAGE" :color (etaf-research-shelf--color model :muted)
|
||||
:bgcolor (etaf-research-shelf--color model :panel))
|
||||
@ -252,9 +292,11 @@ Show MESSAGE on success, or preserve the resulting error state."
|
||||
(plist-get model :database-file))
|
||||
:color (etaf-research-shelf--color model :ink)
|
||||
:bgcolor (etaf-research-shelf--color model :panel))
|
||||
(button :label "↻ Reload library" :ref 'research-shelf-reload
|
||||
:variant 'ghost
|
||||
:on-press (lambda () (etaf-research-shelf--load model "✓ Library reloaded"))))))
|
||||
(etaf-research-shelf-button
|
||||
:theme (etaf-research-shelf--theme model)
|
||||
:label "↻ Reload library" :ref 'research-shelf-reload
|
||||
:variant 'ghost
|
||||
:on-press (lambda () (etaf-research-shelf--load model "✓ Library reloaded"))))))
|
||||
|
||||
(defun etaf-research-shelf--row-press (model row)
|
||||
"Select ROW as the single current record in MODEL."
|
||||
@ -265,7 +307,7 @@ Show MESSAGE on success, or preserve the resulting error state."
|
||||
"Return the main reading list for MODEL and static MAIN FORM."
|
||||
(let ((controller (etaf-research-shelf--controller model)))
|
||||
(etaf-view
|
||||
(column :class "research-shelf-list" :width 'stretch
|
||||
(column :class "research-shelf-list" :width 'stretch :min-width 0
|
||||
:padding '(1 2)
|
||||
:border (etaf-research-shelf--color model :line)
|
||||
:color (etaf-research-shelf--color model :ink)
|
||||
@ -281,27 +323,29 @@ Show MESSAGE on success, or preserve the resulting error state."
|
||||
(or (etaf-value (etaf-data-total controller)) 0))
|
||||
:color (etaf-research-shelf--color model :muted)
|
||||
:bgcolor (etaf-research-shelf--color model :panel)))
|
||||
(button :label "+ Add reading" :ref 'research-shelf-add
|
||||
:variant 'secondary
|
||||
:on-press
|
||||
(lambda ()
|
||||
(let ((id (etaf-value (plist-get model :next-id))))
|
||||
(etaf-research-shelf--mutate
|
||||
model 'insert
|
||||
(list :id id :title (format "New reading %d" id)
|
||||
:author "You" :kind "Notes" :status "unread"
|
||||
:progress 0 :priority "Medium" :starred 0
|
||||
:note "A new note waiting for your attention."
|
||||
:updated "Just now")
|
||||
"✓ Added to your shelf")
|
||||
(setf (etaf-value (plist-get model :next-id)) (1+ id))))))
|
||||
(etaf-research-shelf-button
|
||||
:theme (etaf-research-shelf--theme model)
|
||||
:label "+ Add reading" :ref 'research-shelf-add
|
||||
:variant 'secondary
|
||||
:on-press
|
||||
(lambda ()
|
||||
(let ((id (etaf-value (plist-get model :next-id))))
|
||||
(etaf-research-shelf--mutate
|
||||
model 'insert
|
||||
(list :id id :title (format "New reading %d" id)
|
||||
:author "You" :kind "Notes" :status "unread"
|
||||
:progress 0 :priority "Medium" :starred 0
|
||||
:note "A new note waiting for your attention."
|
||||
:updated "Just now")
|
||||
"✓ Added to your shelf")
|
||||
(setf (etaf-value (plist-get model :next-id)) (1+ id))))))
|
||||
(data-grid
|
||||
:controller controller
|
||||
:columns '((:key :title :label "Title" :width 30)
|
||||
(:key :author :label "Author" :width 16)
|
||||
(:key :status :label "Status" :width 14)
|
||||
(:key :progress :label "Progress" :width 10)
|
||||
(:key :kind :label "Kind" :width 10))
|
||||
:columns '((:key :title :label "Title" :width 22)
|
||||
(:key :author :label "Author" :width 12)
|
||||
(:key :status :label "Status" :width 11)
|
||||
(:key :progress :label "Progress" :width 9)
|
||||
(:key :kind :label "Kind" :width 8))
|
||||
:row-key (lambda (row) (plist-get row :id))
|
||||
:row-ref (lambda (row)
|
||||
(intern (format "research-shelf-row-%s"
|
||||
@ -321,7 +365,7 @@ Show MESSAGE on success, or preserve the resulting error state."
|
||||
(defun etaf-research-shelf--detail-view (model form)
|
||||
"Return the selected record inspector for MODEL and static FORM."
|
||||
(etaf-view
|
||||
(column :class "research-shelf-detail" :width 'stretch
|
||||
(column :class "research-shelf-detail" :width 'stretch :min-width 0
|
||||
:padding '(2 2)
|
||||
:border (etaf-research-shelf--color model :line)
|
||||
:color (etaf-research-shelf--color model :ink)
|
||||
@ -375,50 +419,56 @@ Show MESSAGE on success, or preserve the resulting error state."
|
||||
:setup
|
||||
(let ((model (etaf-current-prop :model)))
|
||||
(lambda ()
|
||||
(let* ((row (etaf-research-shelf--selected model))
|
||||
(let* ((theme (etaf-research-shelf--theme model))
|
||||
(row (etaf-research-shelf--selected model))
|
||||
(progress (or (and row (plist-get row :progress)) 0))
|
||||
(finished (and row (equal (plist-get row :status) "finished")))
|
||||
(archived (and row (equal (plist-get row :status) "archived"))))
|
||||
(etaf-view
|
||||
(flex :width 'stretch :flex-wrap 'wrap :gap '(1 (6))
|
||||
(button :label "+ 10%" :ref 'research-shelf-progress
|
||||
:variant 'secondary :disabled (or (null row) (>= progress 100))
|
||||
:on-press
|
||||
(lambda ()
|
||||
(when-let* ((current (etaf-research-shelf--selected model))
|
||||
(value (or (plist-get current :progress) 0)))
|
||||
(etaf-research-shelf--update-selected
|
||||
model (list :progress (min 100 (+ value 10))
|
||||
:status (if (>= (+ value 10) 100)
|
||||
"finished" "reading")
|
||||
:updated "Just now")
|
||||
"✓ Progress saved"))))
|
||||
(button :label "✓ Finish" :ref 'research-shelf-finish
|
||||
:variant 'secondary :disabled (or (null row) finished)
|
||||
:on-press
|
||||
(lambda ()
|
||||
(etaf-research-shelf--update-selected
|
||||
model '(:progress 100 :status "finished" :updated "Just now")
|
||||
"✓ Marked finished")))
|
||||
(button :label "★ Star" :ref 'research-shelf-star :variant 'ghost
|
||||
:disabled (null row)
|
||||
:on-press
|
||||
(lambda ()
|
||||
(when-let ((current (etaf-research-shelf--selected model)))
|
||||
(let ((current-starred
|
||||
(= 1 (or (plist-get current :starred) 0))))
|
||||
(etaf-research-shelf--update-selected
|
||||
model (list :starred (if current-starred 0 1)
|
||||
:updated "Just now")
|
||||
(if current-starred
|
||||
"Removed star" "★ Starred locally"))))))
|
||||
(button :label "Archive" :ref 'research-shelf-archive
|
||||
:variant 'ghost :disabled (or (null row) archived)
|
||||
:on-press
|
||||
(lambda ()
|
||||
(etaf-research-shelf--update-selected
|
||||
model '(:status "archived" :updated "Just now")
|
||||
"↗ Archived")))))))))
|
||||
(etaf-research-shelf-button
|
||||
:theme theme :label "+ 10%" :ref 'research-shelf-progress
|
||||
:variant 'secondary
|
||||
:disabled (or (null row) archived (>= progress 100))
|
||||
:on-press
|
||||
(lambda ()
|
||||
(when-let* ((current (etaf-research-shelf--selected model))
|
||||
(value (or (plist-get current :progress) 0)))
|
||||
(etaf-research-shelf--update-selected
|
||||
model (list :progress (min 100 (+ value 10))
|
||||
:status (if (>= (+ value 10) 100)
|
||||
"finished" "reading")
|
||||
:updated "Just now")
|
||||
"✓ Progress saved"))))
|
||||
(etaf-research-shelf-button
|
||||
:theme theme :label "✓ Finish" :ref 'research-shelf-finish
|
||||
:variant 'secondary :disabled (or (null row) finished archived)
|
||||
:on-press
|
||||
(lambda ()
|
||||
(etaf-research-shelf--update-selected
|
||||
model '(:progress 100 :status "finished" :updated "Just now")
|
||||
"✓ Marked finished")))
|
||||
(etaf-research-shelf-button
|
||||
:theme theme :label "★ Star" :ref 'research-shelf-star
|
||||
:variant 'ghost :disabled (null row)
|
||||
:on-press
|
||||
(lambda ()
|
||||
(when-let ((current (etaf-research-shelf--selected model)))
|
||||
(let ((current-starred
|
||||
(= 1 (or (plist-get current :starred) 0))))
|
||||
(etaf-research-shelf--update-selected
|
||||
model (list :starred (if current-starred 0 1)
|
||||
:updated "Just now")
|
||||
(if current-starred
|
||||
"Removed star" "★ Starred locally"))))))
|
||||
(etaf-research-shelf-button
|
||||
:theme theme :label "Archive" :ref 'research-shelf-archive
|
||||
:variant 'ghost :disabled (or (null row) archived)
|
||||
:on-press
|
||||
(lambda ()
|
||||
(etaf-research-shelf--update-selected
|
||||
model '(:status "archived" :updated "Just now")
|
||||
"↗ Archived")))))))))
|
||||
|
||||
(etaf-define-component etaf-research-shelf-filter-rail
|
||||
(&key model static-form)
|
||||
@ -497,7 +547,11 @@ structural children instead of leaking through a direct material `expr'."
|
||||
(setf (etaf-value (plist-get model :toast))
|
||||
(if value "Dark theme" "Light theme")))))
|
||||
(grid :class "research-shelf-workspace" :width 'stretch
|
||||
:grid-template-columns '(2fr 5fr 3fr) :gap '(1 (10))
|
||||
:grid-template-columns
|
||||
'((minmax (0) (fr 2))
|
||||
(minmax (0) (fr 5))
|
||||
(minmax (0) (fr 3)))
|
||||
:gap '(1 (6))
|
||||
:color (plist-get palette :ink)
|
||||
:bgcolor (plist-get palette :paper)
|
||||
(etaf-research-shelf-filter-rail :model model :static-form filters)
|
||||
@ -532,11 +586,15 @@ structural children instead of leaking through a direct material `expr'."
|
||||
(defun etaf-research-shelf-open (&optional buffer-name)
|
||||
"Mount and optionally display the Research Shelf application in BUFFER-NAME."
|
||||
(interactive)
|
||||
(let ((buffer (etaf-mount (or buffer-name "*ETAF Research Shelf*")
|
||||
(etaf-research-shelf-root
|
||||
(etaf-playground-read-static "research-shelf")))))
|
||||
(when (called-interactively-p 'interactive) (pop-to-buffer buffer))
|
||||
buffer))
|
||||
(let* ((name (or buffer-name "*ETAF Research Shelf*"))
|
||||
;; Put the target in its real GUI window before the first Ebox
|
||||
;; projection so `(viewport)' resolves against the user's frame.
|
||||
(buffer (get-buffer-create name)))
|
||||
(when (called-interactively-p 'interactive)
|
||||
(switch-to-buffer buffer))
|
||||
(etaf-mount buffer
|
||||
(etaf-research-shelf-root
|
||||
(etaf-playground-read-static "research-shelf")))))
|
||||
|
||||
(provide 'etaf-research-shelf)
|
||||
;;; research-shelf.el ends here
|
||||
|
||||
@ -72,6 +72,22 @@ database and mounts a test buffer before running BODY."
|
||||
(should-not (string-match-p "operations-console" framework))
|
||||
(should (string-match-p "research-shelf" catalog))))
|
||||
|
||||
(ert-deftest etaf-playground-displays-before-responsive-mount ()
|
||||
"GUI entry points establish the containing window before Ebox mount."
|
||||
(let ((calls nil)
|
||||
(noninteractive nil))
|
||||
(cl-letf (((symbol-function 'switch-to-buffer)
|
||||
(lambda (buffer)
|
||||
(push (list 'display (buffer-name buffer)) calls)
|
||||
buffer))
|
||||
((symbol-function 'etaf-playground-mount-example)
|
||||
(lambda (buffer name)
|
||||
(push (list 'mount buffer name) calls)
|
||||
buffer)))
|
||||
(etaf-playground--mount-for-display
|
||||
" *etaf-playground-display-order*" "research-shelf"))
|
||||
(should (equal '(display mount) (mapcar #'car (nreverse calls))))))
|
||||
|
||||
(ert-deftest etaf-playground-compile-builds-the-dependency-graph ()
|
||||
"Integration builds must compile the framework's dependency graph first."
|
||||
(let ((makefile (with-temp-buffer
|
||||
@ -189,6 +205,12 @@ database and mounts a test buffer before running BODY."
|
||||
(etaf-dispatch-event runtime 'research-shelf-star 'press)
|
||||
(should (string-match-p "Removed star"
|
||||
(etaf-playground-test--text buffer)))
|
||||
(etaf-dispatch-event runtime 'research-shelf-archive 'press)
|
||||
(should (equal t
|
||||
(plist-get
|
||||
(etaf-runtime-host-props-for runtime
|
||||
'research-shelf-finish)
|
||||
:disabled)))
|
||||
(etaf-dispatch-event runtime 'research-shelf-add 'press)
|
||||
(should (string-match-p "Added to your shelf"
|
||||
(etaf-playground-test--text buffer)))
|
||||
|
||||
Loading…
Reference in New Issue
Block a user