Compare commits
2
Commits
v0.1.1
..
f46285fe4e
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f46285fe4e | ||
|
|
42c1ad75c8 |
No files matched your search
@@ -130,16 +130,26 @@ function installPopupDom() {
|
||||
};
|
||||
}
|
||||
|
||||
async function mountPopup() {
|
||||
async function mountPopupWithStorage(storageGet = async () => ({}), captureWrite = null) {
|
||||
const { dom, cleanup } = installPopupDom();
|
||||
// Override the chrome.storage.local stub so we can seed a value and capture writes.
|
||||
const writes = [];
|
||||
globalThis.chrome.storage.local.get = async (...args) => {
|
||||
const res = await storageGet(...args);
|
||||
return res;
|
||||
};
|
||||
globalThis.chrome.storage.local.set = async (items) => {
|
||||
if (captureWrite) captureWrite(items); else writes.push(items);
|
||||
};
|
||||
const moduleUrl = new URL('../src/viewer/index.js?test=' + Date.now(), import.meta.url);
|
||||
await import(moduleUrl.href);
|
||||
return { dom, cleanup };
|
||||
const flush = () => new Promise((resolve) => setTimeout(resolve, 0));
|
||||
return { dom, cleanup, writes, flush };
|
||||
}
|
||||
|
||||
describe('Viewer popup instructions', () => {
|
||||
it('renders the drafted instructions copy on mount with accessible labeling', async () => {
|
||||
const { dom, cleanup } = await mountPopup();
|
||||
const { dom, cleanup } = await mountPopupWithStorage();
|
||||
try {
|
||||
const doc = dom.window.document;
|
||||
const region = doc.querySelector('.instructions-panel');
|
||||
@@ -180,7 +190,7 @@ describe('Viewer popup instructions', () => {
|
||||
});
|
||||
|
||||
it('toggles the instructions panel open and closed', async () => {
|
||||
const { dom, cleanup } = await mountPopup();
|
||||
const { dom, cleanup } = await mountPopupWithStorage();
|
||||
try {
|
||||
const doc = dom.window.document;
|
||||
const toggle = doc.getElementById('instructions-toggle');
|
||||
@@ -194,11 +204,66 @@ describe('Viewer popup instructions', () => {
|
||||
if (toggle.textContent !== 'Show instructions') throw new Error('Collapsed label should switch to Show instructions');
|
||||
|
||||
toggle.click();
|
||||
if (toggle.getAttribute('aria-expanded') !== 'true') throw new Error('Toggle should expand the instructions');
|
||||
if (body.hidden) throw new Error('Instructions body should be visible after expanding');
|
||||
if (toggle.textContent !== 'Hide instructions') throw new Error('Expanded label should switch back to Hide instructions');
|
||||
} finally {
|
||||
if (toggle.getAttribute('aria-expanded') !== 'true') throw new Error('Toggle should expand the instructions');
|
||||
if (body.hidden) throw new Error('Instructions body should be visible after expanding');
|
||||
if (toggle.textContent !== 'Hide instructions') throw new Error('Expanded label should switch back to Hide instructions');
|
||||
} finally {
|
||||
cleanup();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
it('honors a stored hidden state on mount', async () => {
|
||||
const { dom, cleanup } = await mountPopupWithStorage(
|
||||
async () => ({ goon_instructions_visible: false })
|
||||
);
|
||||
try {
|
||||
const doc = dom.window.document;
|
||||
const toggle = doc.getElementById('instructions-toggle');
|
||||
const body = doc.getElementById('instructions-body');
|
||||
// Wait for the async storage.get() to resolve and apply.
|
||||
await new Promise((r) => setTimeout(r, 0));
|
||||
if (toggle.getAttribute('aria-expanded') !== 'false') throw new Error('Stored hidden state should start collapsed');
|
||||
if (!body.hidden) throw new Error('Stored hidden state should start hidden');
|
||||
if (toggle.textContent !== 'Show instructions') throw new Error('Stored hidden state should show the "Show instructions" label');
|
||||
} finally {
|
||||
cleanup();
|
||||
}
|
||||
});
|
||||
|
||||
it('persists the new visibility on every user toggle', async () => {
|
||||
let written = null;
|
||||
const { dom, cleanup, flush } = await mountPopupWithStorage(
|
||||
async () => ({}),
|
||||
(items) => { written = items; }
|
||||
);
|
||||
try {
|
||||
const doc = dom.window.document;
|
||||
const toggle = doc.getElementById('instructions-toggle');
|
||||
// Collapse -> must persist false.
|
||||
toggle.click();
|
||||
await flush();
|
||||
if (written === null) throw new Error('Collapsing the panel must write to chrome.storage.local');
|
||||
if (written.goon_instructions_visible !== false) throw new Error('Collapsing must persist goon_instructions_visible=false');
|
||||
// Expand -> must persist true.
|
||||
toggle.click();
|
||||
await flush();
|
||||
if (written.goon_instructions_visible !== true) throw new Error('Expanding must persist goon_instructions_visible=true');
|
||||
} finally {
|
||||
cleanup();
|
||||
}
|
||||
});
|
||||
|
||||
it('defaults a first-time user (no stored key) to shown', async () => {
|
||||
const { dom, cleanup } = await mountPopupWithStorage(async () => ({}));
|
||||
try {
|
||||
const doc = dom.window.document;
|
||||
const toggle = doc.getElementById('instructions-toggle');
|
||||
const body = doc.getElementById('instructions-body');
|
||||
await new Promise((r) => setTimeout(r, 0));
|
||||
if (toggle.getAttribute('aria-expanded') !== 'true') throw new Error('First-time user should start expanded');
|
||||
if (body.hidden) throw new Error('First-time instructions body should be visible on mount');
|
||||
} finally {
|
||||
cleanup();
|
||||
}
|
||||
});
|
||||
});
|
||||
+20
-2
@@ -6,6 +6,11 @@
|
||||
|
||||
const STORAGE_KEY = 'goon_videos';
|
||||
const TAGGED_KEY = 'goon_tagged';
|
||||
// Durable "hide instructions" toggle. Absent key === SHOWN (true), matching the
|
||||
// first-time "expanded on mount" behavior. chrome.storage.local is extension-wide,
|
||||
// so the viewer window and every popup instance read/write the same value — the
|
||||
// preference is respected application-wide and survives reloads / SW termination.
|
||||
const INSTRUCTIONS_VISIBLE_KEY = 'goon_instructions_visible';
|
||||
|
||||
// Set to true to enable verbose console output in the popup.
|
||||
const DEBUG = true; // TEMP: enabled for debugging — revert to false when done
|
||||
@@ -48,9 +53,22 @@ function setInstructionsExpanded(expanded) {
|
||||
}
|
||||
|
||||
if (instructionsToggle && instructionsBody) {
|
||||
setInstructionsExpanded(true);
|
||||
// On mount, read the stored visibility. An absent key means SHOWN (true), so a
|
||||
// first-time user still sees the steps. The viewer window reads the same
|
||||
// extension-wide key, so the choice is respected across the whole app.
|
||||
chrome.storage.local.get(INSTRUCTIONS_VISIBLE_KEY).then(stored => {
|
||||
const visible = stored[INSTRUCTIONS_VISIBLE_KEY];
|
||||
setInstructionsExpanded(visible === undefined ? true : visible);
|
||||
}).catch(() => {
|
||||
// Any read failure falls back to shown.
|
||||
setInstructionsExpanded(true);
|
||||
});
|
||||
// On every user toggle, apply in-DOM and persist. Both directions write, so
|
||||
// the state survives reloads and SW termination until the user flips it again.
|
||||
instructionsToggle.addEventListener('click', () => {
|
||||
setInstructionsExpanded(instructionsBody.hidden);
|
||||
const next = instructionsBody.hidden;
|
||||
setInstructionsExpanded(next);
|
||||
chrome.storage.local.set({ [INSTRUCTIONS_VISIBLE_KEY]: next });
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user