Merge pull request 'feat: CI regression: offline artifact browser journey does not flush after reconnect' (#928) from timmy/927-ci-regression-offline-artifact-browser-journey-d into main
This commit is contained in:
commit
9adfcd01b6
|
|
@ -6962,19 +6962,25 @@
|
||||||
setStatus('Offline');
|
setStatus('Offline');
|
||||||
if (!hasContextSnapshot) await hydrateOfflineWork();
|
if (!hasContextSnapshot) await hydrateOfflineWork();
|
||||||
}
|
}
|
||||||
function reconnectLiveData() {
|
const reconnectOutboxes = createReconnectOutboxes({
|
||||||
setStatus('Reconnecting…');
|
refresh: async () => {
|
||||||
contextPoller.refresh({ force: true }).then(snapshot => {
|
setStatus('Reconnecting…');
|
||||||
|
const snapshot = await contextPoller.refresh({ force: true });
|
||||||
if (!snapshot) {
|
if (!snapshot) {
|
||||||
offlineStatus.hidden = false;
|
offlineStatus.hidden = false;
|
||||||
setOfflineWorkMode(true);
|
setOfflineWorkMode(true);
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
offlineStatus.hidden = true;
|
offlineStatus.hidden = true;
|
||||||
setOfflineWorkMode(false);
|
setOfflineWorkMode(false);
|
||||||
if (selectedReview && offlineReview) openReviewSheet(selectedReview, reviewTrigger);
|
if (selectedReview && offlineReview) openReviewSheet(selectedReview, reviewTrigger);
|
||||||
});
|
return snapshot;
|
||||||
}
|
},
|
||||||
|
restoreIdentity: login => { activeFlushLogin = login; confirmedOwnerLogin = login; },
|
||||||
|
flushIssue: flushIssueOutbox,
|
||||||
|
flushAuthored: flushAuthoredOutbox,
|
||||||
|
flushNotificationReads: flushNotificationReadOutbox,
|
||||||
|
});
|
||||||
async function setOfflineWorkEnabled(enabled) {
|
async function setOfflineWorkEnabled(enabled) {
|
||||||
keepWorkOffline.checked = enabled;
|
keepWorkOffline.checked = enabled;
|
||||||
offlineWorkStore.setEnabled(enabled);
|
offlineWorkStore.setEnabled(enabled);
|
||||||
|
|
@ -7032,7 +7038,7 @@
|
||||||
updateDeliveryReceiptControls();
|
updateDeliveryReceiptControls();
|
||||||
if (!navigator.onLine) await showOfflineStatus();
|
if (!navigator.onLine) await showOfflineStatus();
|
||||||
window.addEventListener('offline', showOfflineStatus);
|
window.addEventListener('offline', showOfflineStatus);
|
||||||
window.addEventListener('online', reconnectLiveData);
|
window.addEventListener('online', reconnectOutboxes);
|
||||||
|
|
||||||
qs('#refresh').addEventListener('click', load);
|
qs('#refresh').addEventListener('click', load);
|
||||||
qs('#plan-today').addEventListener('click', event => openPlanToday(event.currentTarget));
|
qs('#plan-today').addEventListener('click', event => openPlanToday(event.currentTarget));
|
||||||
|
|
|
||||||
|
|
@ -1307,6 +1307,7 @@
|
||||||
<script src="static/outbox-coordinator.js"></script>
|
<script src="static/outbox-coordinator.js"></script>
|
||||||
<script src="static/background-issue-sync.js"></script>
|
<script src="static/background-issue-sync.js"></script>
|
||||||
<script src="static/issue-outbox.js"></script>
|
<script src="static/issue-outbox.js"></script>
|
||||||
|
<script src="static/reconnect-outboxes.js"></script>
|
||||||
<script src="static/authored-outbox.js"></script>
|
<script src="static/authored-outbox.js"></script>
|
||||||
<script src="static/offline-issue-close.js"></script>
|
<script src="static/offline-issue-close.js"></script>
|
||||||
<script src="static/offline-issue-blocker.js"></script>
|
<script src="static/offline-issue-blocker.js"></script>
|
||||||
|
|
|
||||||
25
frontend/reconnect-outboxes.js
Normal file
25
frontend/reconnect-outboxes.js
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
function createReconnectOutboxes({
|
||||||
|
refresh,
|
||||||
|
restoreIdentity,
|
||||||
|
flushIssue,
|
||||||
|
flushAuthored,
|
||||||
|
flushNotificationReads,
|
||||||
|
}) {
|
||||||
|
return async function reconnectOutboxes() {
|
||||||
|
const snapshot = await refresh();
|
||||||
|
const freshness = snapshot?.freshness?.sections?.context;
|
||||||
|
const identityFresh = snapshot?.context && !snapshot.context.error &&
|
||||||
|
!freshness?.stale && !freshness?.degraded && !freshness?.revalidating;
|
||||||
|
const login = identityFresh ? String(snapshot.context.user?.login || '').trim() : '';
|
||||||
|
if (!login) return false;
|
||||||
|
restoreIdentity(login);
|
||||||
|
await Promise.all([
|
||||||
|
flushIssue(),
|
||||||
|
flushAuthored(),
|
||||||
|
flushNotificationReads(),
|
||||||
|
]);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof module !== 'undefined' && module.exports) module.exports = createReconnectOutboxes;
|
||||||
|
|
@ -32,6 +32,7 @@ const SHELL = [
|
||||||
BASE + 'static/draft-capacity-dialog.js',
|
BASE + 'static/draft-capacity-dialog.js',
|
||||||
BASE + 'static/outbox-coordinator.js',
|
BASE + 'static/outbox-coordinator.js',
|
||||||
BASE + 'static/issue-outbox.js',
|
BASE + 'static/issue-outbox.js',
|
||||||
|
BASE + 'static/reconnect-outboxes.js',
|
||||||
BASE + 'static/authored-outbox.js',
|
BASE + 'static/authored-outbox.js',
|
||||||
BASE + 'static/offline-issue-close.js',
|
BASE + 'static/offline-issue-close.js',
|
||||||
BASE + 'static/offline-issue-blocker.js',
|
BASE + 'static/offline-issue-blocker.js',
|
||||||
|
|
|
||||||
51
tests/test_reconnect_outboxes.py
Normal file
51
tests/test_reconnect_outboxes.py
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
import json
|
||||||
|
import subprocess
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
ROOT = Path(__file__).resolve().parents[1]
|
||||||
|
RECONNECT = ROOT / "frontend" / "reconnect-outboxes.js"
|
||||||
|
|
||||||
|
|
||||||
|
def run_node(script: str) -> dict:
|
||||||
|
result = subprocess.run(
|
||||||
|
["node", "-e", script], cwd=ROOT, text=True, capture_output=True, check=True
|
||||||
|
)
|
||||||
|
return json.loads(result.stdout)
|
||||||
|
|
||||||
|
|
||||||
|
def test_successful_reconnect_restores_identity_and_flushes_unchanged_outboxes():
|
||||||
|
result = run_node(
|
||||||
|
f"""
|
||||||
|
const createReconnectOutboxes = require({json.dumps(str(RECONNECT))});
|
||||||
|
const calls = [];
|
||||||
|
const reconnect = createReconnectOutboxes({{
|
||||||
|
refresh: async () => ({{context:{{user:{{login:'timmy'}}}}}}),
|
||||||
|
restoreIdentity: login => calls.push(['identity', login]),
|
||||||
|
flushIssue: () => calls.push(['issue']),
|
||||||
|
flushAuthored: () => calls.push(['authored']),
|
||||||
|
flushNotificationReads: () => calls.push(['notification-read']),
|
||||||
|
}});
|
||||||
|
reconnect().then(result => process.stdout.write(JSON.stringify({{result, calls}})));
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
assert result == {
|
||||||
|
"result": True,
|
||||||
|
"calls": [
|
||||||
|
["identity", "timmy"],
|
||||||
|
["issue"],
|
||||||
|
["authored"],
|
||||||
|
["notification-read"],
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def test_dashboard_uses_reconnect_flush_after_live_identity_refresh():
|
||||||
|
index = (ROOT / "frontend" / "index.html").read_text()
|
||||||
|
dashboard = (ROOT / "frontend" / "dashboard.js").read_text()
|
||||||
|
|
||||||
|
assert '<script src="static/reconnect-outboxes.js"></script>' in index
|
||||||
|
assert "const reconnectOutboxes = createReconnectOutboxes({" in dashboard
|
||||||
|
assert "restoreIdentity: login => { activeFlushLogin = login; confirmedOwnerLogin = login; }" in dashboard
|
||||||
|
assert "window.addEventListener('online', reconnectOutboxes);" in dashboard
|
||||||
|
|
@ -930,6 +930,7 @@ def test_install_precaches_complete_subpath_scoped_app_shell():
|
||||||
"/dashboard/static/draft-capacity-dialog.js",
|
"/dashboard/static/draft-capacity-dialog.js",
|
||||||
"/dashboard/static/outbox-coordinator.js",
|
"/dashboard/static/outbox-coordinator.js",
|
||||||
"/dashboard/static/issue-outbox.js",
|
"/dashboard/static/issue-outbox.js",
|
||||||
|
"/dashboard/static/reconnect-outboxes.js",
|
||||||
"/dashboard/static/authored-outbox.js",
|
"/dashboard/static/authored-outbox.js",
|
||||||
"/dashboard/static/offline-issue-close.js",
|
"/dashboard/static/offline-issue-close.js",
|
||||||
"/dashboard/static/offline-issue-blocker.js",
|
"/dashboard/static/offline-issue-blocker.js",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user