Compare commits
No commits in common. "34d5f86d5385965ea9acce26d44993b74ced9376" and "6913fc82570178522dee71fef03a41dbfe2a9398" have entirely different histories.
34d5f86d53
...
6913fc8257
|
|
@ -3205,14 +3205,14 @@
|
||||||
const button = event.currentTarget;
|
const button = event.currentTarget;
|
||||||
if (!activeFlushLogin || !deliveryCenter.retryable.length) return;
|
if (!activeFlushLogin || !deliveryCenter.retryable.length) return;
|
||||||
button.disabled = true;
|
button.disabled = true;
|
||||||
qs('#my-work-action-status').textContent = 'Retrying waiting deliveries…';
|
qs('#my-work-action-status').textContent = 'Retrying safe waiting deliveries…';
|
||||||
const [issueResult, authoredResult] = await Promise.all([issueOutbox.flush(activeFlushLogin), authoredOutbox.flush(activeFlushLogin)]);
|
const [issueResult, authoredResult] = await Promise.all([issueOutbox.flush(activeFlushLogin), authoredOutbox.flush(activeFlushLogin)]);
|
||||||
applyOutboxResult(issueResult);
|
applyOutboxResult(issueResult);
|
||||||
applyAuthoredOutboxResult(authoredResult);
|
applyAuthoredOutboxResult(authoredResult);
|
||||||
qs('#my-work-action-status').textContent = 'Waiting deliveries retried; attention stayed queued.';
|
qs('#my-work-action-status').textContent = 'Waiting deliveries retried. Items needing attention were skipped.';
|
||||||
});
|
});
|
||||||
list.querySelectorAll('.draft-resume').forEach(button => {
|
list.querySelectorAll('.draft-resume').forEach(button => {
|
||||||
button.onclick=async()=>{
|
button.addEventListener('click', async () => {
|
||||||
const item = lastDrafts[Number(button.dataset.draftIndex)];
|
const item = lastDrafts[Number(button.dataset.draftIndex)];
|
||||||
if (!item) return;
|
if (!item) return;
|
||||||
if (item.kind === 'unfiled-issue') {
|
if (item.kind === 'unfiled-issue') {
|
||||||
|
|
@ -3221,7 +3221,7 @@
|
||||||
} catch (error) { qs('#my-work-action-status').textContent = error.message; }
|
} catch (error) { qs('#my-work-action-status').textContent = error.message; }
|
||||||
} else if (item.kind === 'new-issue') openCreateIssueSheet();
|
} else if (item.kind === 'new-issue') openCreateIssueSheet();
|
||||||
else if (item.route) workRoute.open(item.route);
|
else if (item.route) workRoute.open(item.route);
|
||||||
};
|
});
|
||||||
});
|
});
|
||||||
list.querySelectorAll('.draft-continue').forEach(button => {
|
list.querySelectorAll('.draft-continue').forEach(button => {
|
||||||
button.addEventListener('click', () => {
|
button.addEventListener('click', () => {
|
||||||
|
|
@ -3268,7 +3268,7 @@
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
list.querySelectorAll('.draft-review-checklist').forEach(button => {
|
list.querySelectorAll('.draft-review-checklist').forEach(button => {
|
||||||
button.onclick=async()=>{
|
button.addEventListener('click', async () => {
|
||||||
const item = lastDrafts[Number(button.dataset.draftIndex)];
|
const item = lastDrafts[Number(button.dataset.draftIndex)];
|
||||||
const queued = authoredOutbox.list().find(candidate => candidate.id === item?.outbox_id);
|
const queued = authoredOutbox.list().find(candidate => candidate.id === item?.outbox_id);
|
||||||
if (!item?.checklist_conflict || !queued || !activeFlushLogin) return;
|
if (!item?.checklist_conflict || !queued || !activeFlushLogin) return;
|
||||||
|
|
@ -3301,7 +3301,7 @@
|
||||||
} finally {
|
} finally {
|
||||||
button.disabled = false;
|
button.disabled = false;
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
});
|
});
|
||||||
list.querySelectorAll('.draft-authorize').forEach(button => {
|
list.querySelectorAll('.draft-authorize').forEach(button => {
|
||||||
button.addEventListener('click', async () => {
|
button.addEventListener('click', async () => {
|
||||||
|
|
@ -3322,12 +3322,12 @@
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
list.querySelectorAll('.draft-copy').forEach(button => {
|
list.querySelectorAll('.draft-copy').forEach(button => {
|
||||||
button.onclick=async()=>{
|
button.addEventListener('click', async () => {
|
||||||
const item = lastDrafts[Number(button.dataset.draftIndex)];
|
const item = lastDrafts[Number(button.dataset.draftIndex)];
|
||||||
if (!item?.copy_text) return;
|
if (!item?.copy_text) return;
|
||||||
await navigator.clipboard.writeText(item.copy_text);
|
await navigator.clipboard.writeText(item.copy_text);
|
||||||
qs('#my-work-action-status').textContent = 'Queued content copied without sending it.';
|
qs('#my-work-action-status').textContent = 'Queued content copied without sending it.';
|
||||||
};
|
});
|
||||||
});
|
});
|
||||||
list.querySelectorAll('.draft-discard').forEach(button => {
|
list.querySelectorAll('.draft-discard').forEach(button => {
|
||||||
button.addEventListener('click', async () => {
|
button.addEventListener('click', async () => {
|
||||||
|
|
|
||||||
|
|
@ -109,15 +109,14 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
async function attend(item) {
|
async function attend(item) {
|
||||||
|
if (typeof document === 'undefined') return false;
|
||||||
const index = options.getIndex ? options.getIndex(item) : -1;
|
const index = options.getIndex ? options.getIndex(item) : -1;
|
||||||
const selector = item.quarantined ? '.draft-copy' :
|
const selector = item.quarantined ? '.draft-copy' :
|
||||||
item.checklist_conflict ? '.draft-review-checklist' : '.draft-resume';
|
item.checklist_conflict ? '.draft-review-checklist' : '.draft-resume';
|
||||||
const action = document.querySelector('#my-work-list ' + selector + '[data-draft-index="' + index + '"]');
|
const action = document.querySelector('#my-work-list ' + selector + '[data-draft-index="' + index + '"]');
|
||||||
if (!action) throw new Error('Delivery changed.');
|
if (!action) throw new Error('This delivery changed. Reopen recovery to load its current action.');
|
||||||
elements.dialog.close();
|
action.click();
|
||||||
action.scrollIntoView();
|
return true;
|
||||||
action.focus();
|
|
||||||
return await action.onclick();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function activate() {
|
function activate() {
|
||||||
|
|
@ -139,8 +138,7 @@
|
||||||
}
|
}
|
||||||
const result = render();
|
const result = render();
|
||||||
if (failure && elements?.status) {
|
if (failure && elements?.status) {
|
||||||
if (active && !elements.dialog.open) elements.dialog.showModal();
|
elements.status.textContent = failure + ' Try again when the connection is ready.';
|
||||||
elements.status.textContent = failure + ' Try again.';
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
})().finally(() => { inFlight = null; });
|
})().finally(() => { inFlight = null; });
|
||||||
|
|
|
||||||
|
|
@ -194,40 +194,6 @@ def test_release_artifact_keeps_mobile_delivery_recovery_single_flight(tmp_path:
|
||||||
page.evaluate("Promise.all([window.__firstRecovery, window.__secondRecovery])")
|
page.evaluate("Promise.all([window.__firstRecovery, window.__secondRecovery])")
|
||||||
expect(action).to_be_enabled()
|
expect(action).to_be_enabled()
|
||||||
assert page.evaluate("window.__deliveryAttempts") == 1
|
assert page.evaluate("window.__deliveryAttempts") == 1
|
||||||
|
|
||||||
page.evaluate(
|
|
||||||
"""
|
|
||||||
() => {
|
|
||||||
const destination = document.createElement('button');
|
|
||||||
destination.type = 'button';
|
|
||||||
destination.className = 'draft-resume';
|
|
||||||
destination.dataset.draftIndex = '0';
|
|
||||||
destination.textContent = 'Open current review';
|
|
||||||
window.__attentionAttempts = 0;
|
|
||||||
window.__attentionSettled = new Promise(resolve => { window.__finishAttention = resolve; });
|
|
||||||
destination.onclick = async () => {
|
|
||||||
window.__attentionAttempts += 1;
|
|
||||||
await window.__attentionSettled;
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
document.querySelector('#my-work-list').append(destination);
|
|
||||||
window.__attentionRecovery = createMobileDeliveryRecovery({
|
|
||||||
getItems: () => [{outbox_id:'review-attention', status:'attention', title:'Review feedback'}],
|
|
||||||
getIndex: () => 0,
|
|
||||||
});
|
|
||||||
window.__attentionRecovery.open();
|
|
||||||
window.__firstAttention = window.__attentionRecovery.activate();
|
|
||||||
window.__secondAttention = window.__attentionRecovery.activate();
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
expect(page.locator("#mobile-delivery-recovery")).to_be_hidden()
|
|
||||||
expect(page.locator("#my-work-list .draft-resume")).to_be_focused()
|
|
||||||
assert page.evaluate("window.__attentionAttempts") == 1
|
|
||||||
assert page.evaluate("document.documentElement.scrollWidth <= window.innerWidth")
|
|
||||||
page.evaluate("window.__finishAttention()")
|
|
||||||
page.evaluate("Promise.all([window.__firstAttention, window.__secondAttention])")
|
|
||||||
assert page.evaluate("window.__attentionAttempts") == 1
|
|
||||||
assert browser_errors == []
|
assert browser_errors == []
|
||||||
browser.close()
|
browser.close()
|
||||||
finally:
|
finally:
|
||||||
|
|
|
||||||
|
|
@ -72,8 +72,6 @@ def test_product_workflows_are_stable_lazy_feature_chunks(tmp_path):
|
||||||
assert b"function createQueueToday" in first.feature_bundles["today-timer"].runtime_bytes
|
assert b"function createQueueToday" in first.feature_bundles["today-timer"].runtime_bytes
|
||||||
assert b"function createConversationPager" in first.feature_bundles["today-timer"].runtime_bytes
|
assert b"function createConversationPager" in first.feature_bundles["today-timer"].runtime_bytes
|
||||||
assert b"function createConversationPager" not in first.feature_bundles["comment-actions"].runtime_bytes
|
assert b"function createConversationPager" not in first.feature_bundles["comment-actions"].runtime_bytes
|
||||||
assert b"function createMobileDeliveryRecovery" not in first.runtime_bytes
|
|
||||||
assert b"function createMobileDeliveryRecovery" in first.feature_bundles["today-timer"].runtime_bytes
|
|
||||||
assert b"gitea_time_logged" not in first.runtime_bytes
|
assert b"gitea_time_logged" not in first.runtime_bytes
|
||||||
assert b"gitea_time_logged" in security_center.runtime_bytes
|
assert b"gitea_time_logged" in security_center.runtime_bytes
|
||||||
# Core mobile workflows stay below 99 KiB, including synced Search views and Update decisions.
|
# Core mobile workflows stay below 99 KiB, including synced Search views and Update decisions.
|
||||||
|
|
|
||||||
|
|
@ -135,109 +135,6 @@ const createRecovery = require({json.dumps(str(RECOVERY))});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def test_attention_handoff_closes_modal_focuses_destination_and_awaits_work():
|
|
||||||
script = f"""
|
|
||||||
const createRecovery = require({json.dumps(str(RECOVERY))});
|
|
||||||
(async () => {{
|
|
||||||
let finish;
|
|
||||||
let handoffs = 0;
|
|
||||||
const settled = new Promise(resolve => {{finish = resolve}});
|
|
||||||
const destination = {{
|
|
||||||
focused:false, scrolled:false,
|
|
||||||
focus(){{this.focused=true}}, scrollIntoView(){{this.scrolled=true}},
|
|
||||||
async onclick(){{handoffs += 1; await settled; return true}},
|
|
||||||
}};
|
|
||||||
global.document = {{
|
|
||||||
getElementById: () => null,
|
|
||||||
querySelector: selector => selector.includes('draft-resume') ? destination : null,
|
|
||||||
}};
|
|
||||||
const element = () => ({{textContent:'', disabled:false}});
|
|
||||||
const elements = {{
|
|
||||||
dialog: {{open:false, showModal(){{this.open=true}}, close(){{this.open=false}}}},
|
|
||||||
title:element(), destination:element(), reason:element(), progress:element(),
|
|
||||||
action:element(), status:element(),
|
|
||||||
}};
|
|
||||||
const recovery = createRecovery({{
|
|
||||||
getItems: () => [{{outbox_id:'review', status:'attention', title:'Review feedback'}}],
|
|
||||||
getIndex: () => 3,
|
|
||||||
elements,
|
|
||||||
}});
|
|
||||||
recovery.open();
|
|
||||||
const first = recovery.activate();
|
|
||||||
const second = recovery.activate();
|
|
||||||
await Promise.resolve();
|
|
||||||
const pending = {{
|
|
||||||
dialogOpen:elements.dialog.open, disabled:elements.action.disabled,
|
|
||||||
focused:destination.focused, scrolled:destination.scrolled, handoffs,
|
|
||||||
}};
|
|
||||||
finish();
|
|
||||||
await Promise.all([first, second]);
|
|
||||||
process.stdout.write(JSON.stringify({{pending, handoffs, dialogOpen:elements.dialog.open}}));
|
|
||||||
}})();
|
|
||||||
"""
|
|
||||||
|
|
||||||
assert run_node(script) == {
|
|
||||||
"pending": {
|
|
||||||
"dialogOpen": False,
|
|
||||||
"disabled": True,
|
|
||||||
"focused": True,
|
|
||||||
"scrolled": True,
|
|
||||||
"handoffs": 1,
|
|
||||||
},
|
|
||||||
"handoffs": 1,
|
|
||||||
"dialogOpen": False,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def test_failed_attention_handoff_reopens_the_same_retryable_item():
|
|
||||||
script = f"""
|
|
||||||
const createRecovery = require({json.dumps(str(RECOVERY))});
|
|
||||||
(async () => {{
|
|
||||||
const destination = {{
|
|
||||||
focus(){{}}, scrollIntoView(){{}},
|
|
||||||
async onclick(){{throw new Error('Latest checklist unavailable')}},
|
|
||||||
}};
|
|
||||||
global.document = {{
|
|
||||||
getElementById: () => null,
|
|
||||||
querySelector: () => destination,
|
|
||||||
}};
|
|
||||||
const element = () => ({{textContent:'', disabled:false}});
|
|
||||||
const elements = {{
|
|
||||||
dialog: {{open:false, showModal(){{this.open=true}}, close(){{this.open=false}}}},
|
|
||||||
title:element(), destination:element(), reason:element(), progress:element(),
|
|
||||||
action:element(), status:element(),
|
|
||||||
}};
|
|
||||||
const recovery = createRecovery({{
|
|
||||||
getItems: () => [{{outbox_id:'conflict', checklist_conflict:true, title:'Checklist conflict'}}],
|
|
||||||
getIndex: () => 0,
|
|
||||||
elements,
|
|
||||||
}});
|
|
||||||
recovery.open();
|
|
||||||
const result = await recovery.activate();
|
|
||||||
process.stdout.write(JSON.stringify({{
|
|
||||||
result, dialogOpen:elements.dialog.open, status:elements.status.textContent,
|
|
||||||
action:elements.action.textContent,
|
|
||||||
}}));
|
|
||||||
}})();
|
|
||||||
"""
|
|
||||||
|
|
||||||
assert run_node(script) == {
|
|
||||||
"result": {
|
|
||||||
"count": 1,
|
|
||||||
"current": {
|
|
||||||
"id": "conflict",
|
|
||||||
"state": "attention",
|
|
||||||
"primary": "Review changes",
|
|
||||||
"position": 1,
|
|
||||||
"total": 1,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"dialogOpen": True,
|
|
||||||
"status": "Latest checklist unavailable Try again.",
|
|
||||||
"action": "Review changes",
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def test_recovery_retains_failed_delivery_with_actionable_status():
|
def test_recovery_retains_failed_delivery_with_actionable_status():
|
||||||
script = f"""
|
script = f"""
|
||||||
const createRecovery = require({json.dumps(str(RECOVERY))});
|
const createRecovery = require({json.dumps(str(RECOVERY))});
|
||||||
|
|
@ -273,7 +170,7 @@ const createRecovery = require({json.dumps(str(RECOVERY))});
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"disabled": False,
|
"disabled": False,
|
||||||
"status": "Network unavailable Try again.",
|
"status": "Network unavailable Try again when the connection is ready.",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -338,7 +235,6 @@ async def test_dashboard_packages_phone_safe_guided_delivery_recovery():
|
||||||
assert '<script src="static/mobile-delivery-recovery.js"></script>' in html
|
assert '<script src="static/mobile-delivery-recovery.js"></script>' in html
|
||||||
assert "const mobileDeliveryRecovery = createMobileDeliveryRecovery({" in html
|
assert "const mobileDeliveryRecovery = createMobileDeliveryRecovery({" in html
|
||||||
assert "activate: recoverMobileDelivery," in html
|
assert "activate: recoverMobileDelivery," in html
|
||||||
assert "button.onclick=async()=>" in html
|
|
||||||
assert "await (authored ? authoredOutbox : issueOutbox).retry(item.outbox_id, activeFlushLogin)" in html
|
assert "await (authored ? authoredOutbox : issueOutbox).retry(item.outbox_id, activeFlushLogin)" in html
|
||||||
assert "(authored ? applyAuthoredOutboxResult : applyOutboxResult)(result)" in html
|
assert "(authored ? applyAuthoredOutboxResult : applyOutboxResult)(result)" in html
|
||||||
assert "openDelivery: () => mobileDeliveryRecovery.open()" in html
|
assert "openDelivery: () => mobileDeliveryRecovery.open()" in html
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user