diff --git a/test/issueflow-reconcile.test.sh b/test/issueflow-reconcile.test.sh index 8dcca61..f31b58d 100644 --- a/test/issueflow-reconcile.test.sh +++ b/test/issueflow-reconcile.test.sh @@ -1793,12 +1793,12 @@ cp "$ARRIVAL/labels.conf" "$FORGEJO_BOARD/labels.conf" 2>/dev/null || true printf '[]\n' >"$FORGEJO_BOARD/repos_owner_repo_pulls_state_open.json" printf '[]\n' >"$FORGEJO_BOARD/repos_owner_repo_pulls_state_closed.json" printf '%s\n' \ - '[{"number":60,"pull_request":null,"labels":[{"name":"ready"}],"title":"an issue"}, + '[{"number":60,"pull_request":null,"labels":[],"title":"an issue with no queue state"}, {"number":61,"pull_request":{"merged":false},"labels":[],"title":"a pull request"}]' \ >"$FORGEJO_BOARD/repos_owner_repo_issues_state_open.json" jq -n --arg at "$(iso_at "$INOW")" \ '{number:60,user:{login:"triage-one"},created_at:$at,body:"",pull_request:null, - labels:[{name:"ready"}],assignees:[]}' \ + labels:[],assignees:[]}' \ >"$FORGEJO_BOARD/repos_owner_repo_issues_60.json" printf '[]\n' >"$FORGEJO_BOARD/repos_owner_repo_issues_60_comments.json" forgejo_board_run() { @@ -1812,7 +1812,13 @@ check "a forgejo-shaped board is NOT read as empty" 1 "" \ grep -qF 'issueflow: no open issues.' <<<"$fjb_out" check "...the sweep completes over it" 0 "" \ grep -qF 'issueflow: reconciled.' <<<"$fjb_out" -check "...and the PR row is still excluded from the issue set" 1 "" \ +# TRAVERSAL, not merely a non-empty gather: the null-valued row has a +# deterministic outcome — no queue state means needs-triage is minted — so this +# proves reconcile_issue_pass actually ran over it, which "the board is not +# empty" does not (@codex-reviewer-andresmgsl, #210 review). +check "...the null-valued row is TRAVERSED, with an observable outcome" 0 "" \ + grep -qE '^issueflow: #60: needs-triage' <<<"$fjb_out" +check "...and the object-valued PR row is not reconciled as an issue" 1 "" \ grep -qE '^issueflow: #61' <<<"$fjb_out" # release_bodies is the THIRD producer and has its own has() site. A `release` @@ -1846,15 +1852,23 @@ check "...and the sweep still completes" 0 "" \ # The THIRD site is reconcile_issue_pass's per-issue payload check. Same key, # scalar rather than a list: null means issue, an object means PR. -pass_disc() { # $1 = the payload -> the exit status the guard would take - jq -e '.pull_request == null' <<<"$1" >/dev/null && echo issue || echo pr -} -check "a forgejo issue payload (key present, null) reads as an issue" 0 "issue" \ - pass_disc '{"number":60,"pull_request":null}' -check "...and an object-valued one reads as a PR" 0 "pr" \ - pass_disc '{"number":61,"pull_request":{"merged":false}}' -check "...and a github-shaped payload (key absent) still reads as an issue" 0 "issue" \ - pass_disc '{"number":60}' +# The scalar site, driven through the REAL path rather than through the jq +# expression it contains — asserting the expression in isolation is what let +# the regression through (@codex-reviewer-andresmgsl, #210 review). Same board +# harness, one row flipped: null-valued reconciles, object-valued stands down. +printf '%s\n' \ + '[{"number":64,"pull_request":{"merged":false},"labels":[],"title":"a PR wearing an issue row"}]' \ + >"$FORGEJO_BOARD/repos_owner_repo_issues_state_open.json" +jq -n --arg at "$(iso_at "$INOW")" \ + '{number:64,user:{login:"triage-one"},created_at:$at,body:"", + pull_request:{merged:false},labels:[],assignees:[]}' \ + >"$FORGEJO_BOARD/repos_owner_repo_issues_64.json" +printf '[]\n' >"$FORGEJO_BOARD/repos_owner_repo_issues_64_comments.json" +fjb3_out="$(forgejo_board_run)" +check "an object-valued row is not reconciled as an issue by the pass" 1 "" \ + grep -qE '^issueflow: #64' <<<"$fjb3_out" +check "...and the sweep reports the board as empty of ISSUES, correctly" 0 "" \ + grep -qF 'issueflow: no open issues.' <<<"$fjb3_out" # -- the rule is pinned at the source, because a comment did not hold -------- # `.pull_request == null` is stated in this file's own header AND at