diff --git a/frontend/dashboard.js b/frontend/dashboard.js index 2d4996d..914cce9 100644 --- a/frontend/dashboard.js +++ b/frontend/dashboard.js @@ -1771,6 +1771,7 @@ qs('#pull-ci-state').textContent = 'CI unknown'; qs('#pull-merge-state').textContent = 'Review data not loaded'; qs('#merge-pull').disabled = true; + qs('#merge-pull').textContent = workSession.active() ? 'Merge & next' : 'Merge'; qs('#retry-pull-load').hidden = true; qs('#open-pull-gitea').href = item.url || '#'; qs('#close-pull-sheet').focus(); @@ -3376,8 +3377,14 @@ lastMyWork = lastMyWork.filter(item => !(item.kind === 'pull' && item.repository === merging.repository && item.number === merging.number) ); - refreshMyWorkView(); - qs('#my-work-action-status').textContent = merging.key + ' merged.'; + refreshMyWorkView({ reconcileSession:false }); + const continuingSession = workSession.active(); + if (workSession.active()) workSession.complete(); + if (continuingSession && workSession.active()) { + qs('#my-work-action-status').textContent = merging.key + ' merged. Next work item opened.'; + } else if (!continuingSession) { + qs('#my-work-action-status').textContent = merging.key + ' merged.'; + } } catch (error) { qs('#pull-sheet-status').textContent = error.message + ' The pull request remains in My Work; refresh and retry.'; button.disabled = false; diff --git a/tests/test_my_work.py b/tests/test_my_work.py index 2fb6a6f..1923552 100644 --- a/tests/test_my_work.py +++ b/tests/test_my_work.py @@ -1643,6 +1643,56 @@ async def test_closing_issue_advances_active_session_once_and_exposes_close_and_ ) +@pytest.mark.anyio +async def test_merging_pull_advances_active_session_once_and_exposes_merge_and_next(): + html = await dashboard() + + assert "qs('#merge-pull').textContent = workSession.active() ? 'Merge & next' : 'Merge';" in html + merge_handler = html.split("qs('#merge-pull').addEventListener('click'", 1)[1].split( + "qs('#keep-update-unread').addEventListener", 1 + )[0] + assert "refreshMyWorkView({ reconcileSession:false });" in merge_handler + assert "const continuingSession = workSession.active();" in merge_handler + assert "if (workSession.active()) workSession.complete();" in merge_handler + assert "merged. Next work item opened." in merge_handler + assert merge_handler.index("await pullController.merge") < merge_handler.index( + "if (workSession.active()) workSession.complete();" + ) + assert merge_handler.index("lastMyWork = lastMyWork.filter") < merge_handler.index( + "if (workSession.active()) workSession.complete();" + ) + + +@pytest.mark.anyio +async def test_pull_merge_keeps_non_session_copy_and_final_session_completion_announcement(): + html = await dashboard() + merge_handler = html.split("qs('#merge-pull').addEventListener('click'", 1)[1].split( + "qs('#keep-update-unread').addEventListener", 1 + )[0] + + assert "else if (!continuingSession)" in merge_handler + assert "merging.key + ' merged.'" in merge_handler + assert "else if (continuingSession" not in merge_handler + assert "onFinish: () =>" in html + assert "qs('#my-work-action-status').textContent = 'Work session complete.';" in html + + +@pytest.mark.anyio +async def test_failed_pull_merge_does_not_remove_or_advance_the_session(): + html = await dashboard() + merge_handler = html.split("qs('#merge-pull').addEventListener('click'", 1)[1].split( + "qs('#keep-update-unread').addEventListener", 1 + )[0] + success_path, failure_path = merge_handler.split("} catch (error) {", 1) + + assert "lastMyWork = lastMyWork.filter" in success_path + assert "workSession.complete()" in success_path + assert "lastMyWork = lastMyWork.filter" not in failure_path + assert "workSession.complete()" not in failure_path + assert "The pull request remains in My Work; refresh and retry." in failure_path + assert "button.disabled = false;" in failure_path + + def test_work_session_can_start_at_a_newly_created_item(): script = f""" const buildMyWork = require({json.dumps(str(MY_WORK))});