initial: notify-display-test v0.1.0 — 10 assertions
This commit is contained in:
24
LICENSE
Normal file
24
LICENSE
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
Copyright (c) 2026 Calic. All rights reserved.
|
||||||
|
|
||||||
|
This software is part of the Sporel platform — **Tier 1 (Official /
|
||||||
|
Proprietary)** content per the Three-Tier Licensing Model documented in
|
||||||
|
`meta/docs/archive/design/vision.md §Licensing Model` (current source;
|
||||||
|
migration to `meta/docs/architecture/licensing-model.md` pending).
|
||||||
|
|
||||||
|
⚠ **WIP — Legal review required before public launch.** The terms below
|
||||||
|
reflect design intent only; the formalized license framework will be
|
||||||
|
finalized through legal counsel before the first public release. Until
|
||||||
|
then, this notice serves as a placeholder defending the platform owner's
|
||||||
|
rights against unintentional re-licensing.
|
||||||
|
|
||||||
|
No license is granted to copy, modify, distribute, sublicense, or otherwise
|
||||||
|
use this software in any form without prior written permission from the
|
||||||
|
copyright holder.
|
||||||
|
|
||||||
|
References:
|
||||||
|
- Tier 1 (this file): all rights reserved, proprietary, sold/distributed
|
||||||
|
via official channels (Steam, etc.)
|
||||||
|
- Tier 2 (Semi-Commercial Co-Development): bilateral contracts, revenue-
|
||||||
|
share — see vision.md §Licensing Model
|
||||||
|
- Tier 3 (Community Content): CC BY-NC-SA 4.0 + asymmetric CLA — applies
|
||||||
|
to community-uploaded libs/modules/assets, not this repo
|
||||||
143
init.lua
Normal file
143
init.lua
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
-- lib-core.notify-display-test v0.1.0 — 10 assertions
|
||||||
|
-- Exercises: attach_mode (log/toast/detail), validation, toast lifecycle,
|
||||||
|
-- widget factories, detail overwrite, detach cleanup, widget-channel tracking.
|
||||||
|
|
||||||
|
local notify = require("lib-core.notify")
|
||||||
|
local panel = require("lib-core.panel")
|
||||||
|
local display = require("lib-core.notify-display")
|
||||||
|
local T = engine.test
|
||||||
|
|
||||||
|
local M = {}
|
||||||
|
|
||||||
|
-- Helper: create a fresh set of test channels and reset all state
|
||||||
|
local function setup()
|
||||||
|
notify._test_clear_all()
|
||||||
|
-- panel has no _test_clear_all; unregister any widgets we might have registered
|
||||||
|
pcall(panel.unregister, "game-log")
|
||||||
|
pcall(panel.unregister, "detail-panel")
|
||||||
|
pcall(panel.unregister, "log-a")
|
||||||
|
pcall(panel.unregister, "log-b")
|
||||||
|
display._test_reset()
|
||||||
|
end
|
||||||
|
|
||||||
|
function M.run_tests(_ctx)
|
||||||
|
|
||||||
|
-- ==================================================================
|
||||||
|
-- 1. attach_mode("log") succeeds with valid panel_widget_id
|
||||||
|
-- ==================================================================
|
||||||
|
setup()
|
||||||
|
notify.create_channel{ id = "log-ch1", filter = {"event"}, display_mode = "log" }
|
||||||
|
local ok_log = pcall(display.attach_mode, "log", { panel_widget_id = "game-log" })
|
||||||
|
T.assert(ok_log, "attach_mode('log', {panel_widget_id='game-log'}) succeeds")
|
||||||
|
|
||||||
|
-- ==================================================================
|
||||||
|
-- 2. attach_mode("toast") with invalid position → loud-error
|
||||||
|
-- ==================================================================
|
||||||
|
setup()
|
||||||
|
local ok_bad_pos = pcall(display.attach_mode, "toast", { position = "invalid" })
|
||||||
|
T.assert(not ok_bad_pos, "attach_mode('toast') with invalid position raises an error")
|
||||||
|
|
||||||
|
-- ==================================================================
|
||||||
|
-- 3. attach_mode("detail") with valid panel_widget_id succeeds
|
||||||
|
-- ==================================================================
|
||||||
|
setup()
|
||||||
|
notify.create_channel{ id = "det-ch", filter = {"detail-ev"}, display_mode = "detail" }
|
||||||
|
local ok_detail = pcall(display.attach_mode, "detail", { panel_widget_id = "detail-panel" })
|
||||||
|
T.assert(ok_detail, "attach_mode('detail', {panel_widget_id='detail-panel'}) succeeds")
|
||||||
|
|
||||||
|
-- ==================================================================
|
||||||
|
-- 4. attach toast → post → _test_get_active_toasts returns 1 entry
|
||||||
|
-- ==================================================================
|
||||||
|
setup()
|
||||||
|
notify.create_channel{ id = "toast-ch", filter = {"hud"}, display_mode = "toast" }
|
||||||
|
display.attach_mode("toast", { position = "top-right", default_ttl = 10.0 })
|
||||||
|
notify.post{ tags = {"hud"}, text = "alert!" }
|
||||||
|
local toasts = display._test_get_active_toasts()
|
||||||
|
T.equals(#toasts, 1, "post to toast-channel produces 1 active toast")
|
||||||
|
T.equals(toasts[1].msg.text, "alert!", "toast message text is correct")
|
||||||
|
|
||||||
|
-- ==================================================================
|
||||||
|
-- 5. update(dt) past TTL → toast removed
|
||||||
|
-- ==================================================================
|
||||||
|
-- Test 5: TTL expiry via engine.time monkey-patch.
|
||||||
|
-- INTENTIONALLY no setup() call — depends on the toast posted in test 4
|
||||||
|
-- (active_toasts is preserved across tests when setup is skipped).
|
||||||
|
-- Reuse state from test 4; toasts[1].spawn_time is 0 (engine.time absent in test)
|
||||||
|
-- Force-expire by calling update with a dt larger than the spawn_time offset.
|
||||||
|
-- spawn_time = 0, ttl = 10.0; now = 0 → not expired.
|
||||||
|
-- We monkey-patch engine.time to return a future timestamp.
|
||||||
|
local saved_engine_time = engine.time
|
||||||
|
engine.time = { now = function() return 100.0 end }
|
||||||
|
display.update(0)
|
||||||
|
engine.time = saved_engine_time
|
||||||
|
toasts = display._test_get_active_toasts()
|
||||||
|
T.equals(#toasts, 0, "update() past TTL removes expired toasts")
|
||||||
|
|
||||||
|
-- ==================================================================
|
||||||
|
-- 6. create_log_widget returns table with render / handle_input / title
|
||||||
|
-- ==================================================================
|
||||||
|
local log_widget = display.create_log_widget({ widget_id = "game-log", title = "Events" })
|
||||||
|
T.assert(type(log_widget) == "table", "create_log_widget returns a table")
|
||||||
|
T.assert(type(log_widget.render) == "function","log widget_def has render function")
|
||||||
|
T.assert(type(log_widget.handle_input) == "function",
|
||||||
|
"log widget_def has handle_input function")
|
||||||
|
T.equals(log_widget.title, "Events", "log widget title is set from opts")
|
||||||
|
|
||||||
|
-- ==================================================================
|
||||||
|
-- 7. create_detail_widget + post → _test_get_last_detail returns msg
|
||||||
|
-- ==================================================================
|
||||||
|
setup()
|
||||||
|
notify.create_channel{ id = "dw-ch", filter = {"detail-ev"}, display_mode = "detail" }
|
||||||
|
|
||||||
|
local det_widget = display.create_detail_widget({ widget_id = "detail-panel", title = "Info" })
|
||||||
|
T.assert(type(det_widget) == "table", "create_detail_widget returns a table")
|
||||||
|
T.assert(type(det_widget.render) == "function","detail widget_def has render function")
|
||||||
|
|
||||||
|
-- Register widget first so that panel.open inside the subscribe callback succeeds
|
||||||
|
panel.register("detail-panel", det_widget)
|
||||||
|
display.attach_mode("detail", { panel_widget_id = "detail-panel" })
|
||||||
|
notify.post{ tags = {"detail-ev"}, text = "important!" }
|
||||||
|
local last = display._test_get_last_detail()
|
||||||
|
T.assert(last ~= nil, "_test_get_last_detail is set after detail post")
|
||||||
|
T.equals(last.text, "important!", "detail message text is correct")
|
||||||
|
T.assert(panel.is_open(), "panel is open after detail message auto-open")
|
||||||
|
|
||||||
|
-- ==================================================================
|
||||||
|
-- 8. Two log-channels mapped to same panel_widget_id → 2 entries tracked
|
||||||
|
-- ==================================================================
|
||||||
|
setup()
|
||||||
|
notify.create_channel{ id = "log-a", filter = {"ev-a"}, display_mode = "log" }
|
||||||
|
notify.create_channel{ id = "log-b", filter = {"ev-b"}, display_mode = "log" }
|
||||||
|
display.attach_mode("log", { panel_widget_id = "game-log" })
|
||||||
|
local tracked = display._test_get_widget_channels("game-log")
|
||||||
|
T.equals(#tracked, 2, "two log-channels both tracked under same panel_widget_id")
|
||||||
|
|
||||||
|
-- ==================================================================
|
||||||
|
-- 9. detach_mode("toast") removes toast-channel subscriptions
|
||||||
|
-- ==================================================================
|
||||||
|
setup()
|
||||||
|
notify.create_channel{ id = "toast-a", filter = {"t"}, display_mode = "toast" }
|
||||||
|
display.attach_mode("toast", {})
|
||||||
|
local count_before = display._test_subscriber_count()
|
||||||
|
display.detach_mode("toast")
|
||||||
|
local count_after = display._test_subscriber_count()
|
||||||
|
T.assert(count_before > count_after,
|
||||||
|
"detach_mode('toast') reduces subscriber count")
|
||||||
|
T.equals(count_after, 0, "subscriber count is 0 after detach_mode('toast')")
|
||||||
|
|
||||||
|
-- ==================================================================
|
||||||
|
-- 10. Detail overwrite: post msg-A then msg-B → last_detail == B
|
||||||
|
-- ==================================================================
|
||||||
|
setup()
|
||||||
|
notify.create_channel{ id = "ow-ch", filter = {"ow"}, display_mode = "detail" }
|
||||||
|
local ow_widget = display.create_detail_widget({ widget_id = "detail-panel", title = "D" })
|
||||||
|
panel.register("detail-panel", ow_widget)
|
||||||
|
display.attach_mode("detail", { panel_widget_id = "detail-panel" })
|
||||||
|
notify.post{ tags = {"ow"}, text = "A" }
|
||||||
|
notify.post{ tags = {"ow"}, text = "B" }
|
||||||
|
local overwritten = display._test_get_last_detail()
|
||||||
|
T.equals(overwritten.text, "B",
|
||||||
|
"second detail post overwrites first (_test_get_last_detail.text == 'B')")
|
||||||
|
end
|
||||||
|
|
||||||
|
return M
|
||||||
6
manifest.core
Normal file
6
manifest.core
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"id": "lib-core.notify-display-test.core",
|
||||||
|
"kind": "lib",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"license": "Proprietary"
|
||||||
|
}
|
||||||
11
manifest.lib
Normal file
11
manifest.lib
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"id": "lib-core.notify-display-test",
|
||||||
|
"role": "test",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"api_min": "0.1",
|
||||||
|
"deps": [
|
||||||
|
{"id": "lib-core.notify-display", "version": "0.1.0"},
|
||||||
|
{"id": "lib-core.notify", "version": "0.1.0"},
|
||||||
|
{"id": "lib-core.panel", "version": "0.1.0"}
|
||||||
|
]
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user