Skip to content

Commit 2c01a37

Browse files
committed
fix: refresh menu attributes after settings restore
1 parent 79ab189 commit 2c01a37

3 files changed

Lines changed: 48 additions & 0 deletions

File tree

‎CONTRIBUTING.md‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,13 @@ Welcome to work! ("issues")
88
### https://github.com/code-charity/youtube/wiki/Contributing
99
you can also just check the (pinned-)issues(, readme & discussion, wiki, ..) <br><br>
1010
### Thanks for caring ♥
11+
12+
13+
### Settings restore regression tests
14+
15+
Run `npx jest --runInBand tests/unit/settings-import.test.js` to check file and
16+
browser-account restores with a delayed storage callback. Restores must wait for
17+
the batch write before updating the cache, notifying listeners, or closing the
18+
importer. A successful restore emits `storage-set` after populating the cache so
19+
the open menu refreshes its theme and visibility attributes through the listener
20+
in `menu/index.js`. Storage errors must leave the cache and importer unchanged.

‎menu/functions.js‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,8 @@ extension.applyImportedSettings = function (data, callback) {
141141

142142
// Populate the cache before notifying subscribers.
143143
Object.assign(satus.storage.data, data);
144+
// Preserve the write notification used to refresh the open menu's attributes.
145+
satus.events.trigger('storage-set');
144146
satus.events.trigger('storage-import');
145147

146148
if (callback) callback();

‎tests/unit/settings-import.test.js‎

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,42 @@ describe('Settings import persistence', () => {
101101
.toBeLessThan(context.close.mock.invocationCallOrder[0]);
102102
});
103103

104+
test('updates menu attributes after a browser-account restore persists', () => {
105+
const listeners = {};
106+
const attributes = {};
107+
const modalProvider = {close: jest.fn()};
108+
context.extension.skeleton.rendered = {
109+
setAttribute: (key, value) => { attributes[key] = value; },
110+
removeAttribute: (key) => { delete attributes[key]; }
111+
};
112+
context.satus.storage.data = {theme: 'light'};
113+
context.satus.storage.get = (key) => context.satus.storage.data[key];
114+
context.satus.storage.import = (callback) => callback(context.satus.storage.data);
115+
context.satus.locale = {import: (language, callback) => callback()};
116+
context.satus.parentify = jest.fn();
117+
context.satus.isset = (value) => value !== undefined && value !== null;
118+
context.satus.events.on = (event, listener) => { listeners[event] = listener; };
119+
context.satus.events.trigger.mockImplementation((event) => {
120+
if (listeners[event]) listeners[event]();
121+
});
122+
context.location.href = 'moz-extension://test/menu/index.html';
123+
vm.runInNewContext(
124+
fs.readFileSync(path.join(__dirname, '../../menu/index.js'), 'utf8'),
125+
context
126+
);
127+
128+
expect(attributes.theme).toBe('light');
129+
context.extension.pullSettings();
130+
modal.buttons.ok.on.click.call({modalProvider});
131+
expect(attributes.theme).toBe('light');
132+
expect(modalProvider.close).not.toHaveBeenCalled();
133+
134+
storageCallback();
135+
136+
expect(attributes.theme).toBe('dark');
137+
expect(modalProvider.close).toHaveBeenCalledTimes(1);
138+
});
139+
104140
test('keeps browser-account restore open until the local write completes', () => {
105141
const modalProvider = {close: jest.fn()};
106142

0 commit comments

Comments
 (0)