feat: defer selected updates as unread batch (Closes #659)
This commit is contained in:
1 parent
7421a8f62d
commit
ea3712ca3e
6 files changed
+109
-3
No files matched your search
@@ -1343,6 +1343,59 @@ process.stdout.write(JSON.stringify({{noIdentity, invalid, failedWrite}}));
|
||||
}
|
||||
|
||||
|
||||
def test_later_queue_defers_a_batch_atomically_with_one_wake_time_and_change_per_item():
|
||||
script = f"""
|
||||
const createLaterWork = require({json.dumps(str(LATER_WORK))});
|
||||
const values = new Map();
|
||||
const changes = [];
|
||||
let writes = 0;
|
||||
let fail = false;
|
||||
const storage = {{
|
||||
getItem:key => values.get(key) || null,
|
||||
setItem:(key,value) => {{ writes += 1; if (fail) throw new Error('quota'); values.set(key,value); }},
|
||||
removeItem:key => values.delete(key),
|
||||
}};
|
||||
const first = {{kind:'update',repository:'stackchain/api',number:17,notification_id:91}};
|
||||
const second = {{kind:'update',repository:'stackchain/web',number:8,notification_id:92}};
|
||||
const store = createLaterWork({{
|
||||
storage, getLogin:() => 'timmy', now:() => new Date('2026-08-08T12:00:00Z'),
|
||||
setTimer:() => 1, clearTimer:() => {{}},
|
||||
onChange:(...change) => changes.push(change),
|
||||
}});
|
||||
const deferred = store.deferMany([first, second], new Date('2026-08-09T09:00:00Z'));
|
||||
const saved = store.partition([first, second]);
|
||||
const beforeFailure = JSON.stringify(store.read());
|
||||
fail = true;
|
||||
const unavailable = store.deferMany([
|
||||
{{kind:'update',repository:'stackchain/api',number:19,notification_id:93}},
|
||||
{{kind:'update',repository:'stackchain/api',number:20,notification_id:94}},
|
||||
], new Date('2026-08-10T09:00:00Z'));
|
||||
process.stdout.write(JSON.stringify({{
|
||||
deferred, unavailable, writes, changes,
|
||||
later:saved.later.map(item => [item.notification_id,item.deferred_until]),
|
||||
unchanged:beforeFailure === JSON.stringify(store.read()),
|
||||
}}));
|
||||
"""
|
||||
result = subprocess.run(
|
||||
["node", "-e", script], check=True, capture_output=True, text=True
|
||||
)
|
||||
|
||||
assert json.loads(result.stdout) == {
|
||||
"deferred": "deferred",
|
||||
"unavailable": "unavailable",
|
||||
"writes": 2,
|
||||
"changes": [
|
||||
["defer", "update:stackchain/api:17:91", "2026-08-09T09:00:00.000Z"],
|
||||
["defer", "update:stackchain/web:8:92", "2026-08-09T09:00:00.000Z"],
|
||||
],
|
||||
"later": [
|
||||
[91, "2026-08-09T09:00:00.000Z"],
|
||||
[92, "2026-08-09T09:00:00.000Z"],
|
||||
],
|
||||
"unchanged": True,
|
||||
}
|
||||
|
||||
|
||||
def test_later_queue_prunes_missing_work_and_wakes_expired_items_without_reload():
|
||||
script = f"""
|
||||
const createLaterWork = require({json.dumps(str(LATER_WORK))});
|
||||
@@ -5582,6 +5635,20 @@ async def test_updates_view_offers_accessible_sticky_mobile_subset_selection():
|
||||
assert "body: JSON.stringify({ ids })" in html
|
||||
|
||||
|
||||
@pytest.mark.anyio
|
||||
async def test_selected_updates_can_be_deferred_together_without_marking_them_read():
|
||||
html = await dashboard()
|
||||
|
||||
assert 'id="defer-selected-today"' in html
|
||||
assert 'id="defer-selected-tomorrow"' in html
|
||||
assert 'laterWork.deferMany(selectedUpdates, until)' in html
|
||||
assert "notificationSelection.cancel()" in html
|
||||
assert "Selection unchanged." in html
|
||||
assert "work stays unread and unchanged in Gitea" in html
|
||||
assert '.my-work-bulk-actions { display:grid;' in html
|
||||
assert '.my-work-bulk-actions button { min-height:44px; width:100%; }' in html
|
||||
|
||||
|
||||
@pytest.mark.anyio
|
||||
async def test_updates_view_discloses_incomplete_inbox_and_loads_more_on_mobile():
|
||||
html = await dashboard()
|
||||
|
||||
Reference in new issue
Block a user