Use mw.storage directly

Bug: T77349
Change-Id: I8a494f20b4d9f4930fa89681857990416c0e840c
This commit is contained in:
Simon Legner 2024-08-10 14:17:30 +02:00
parent f27c355342
commit aa2951f436
8 changed files with 98 additions and 115 deletions

View file

@ -26,9 +26,12 @@ class Config {
* @param {mw.Map} mwConfig
* @param {Object} mwUser
* @param {mw.Api} api
* @param {mw.SafeStorage} localStorage
*/
constructor( viewerConfig, mwConfig, mwUser, api, localStorage ) {
constructor(
viewerConfig = mw.config.get( 'wgMultimediaViewer', {} ),
mwConfig = mw.config,
mwUser = mw.user,
api = new mw.Api() ) {
/**
* A plain object storing MediaViewer-specific settings
*
@ -56,13 +59,6 @@ class Config {
* @type {mw.Api}
*/
this.api = api;
/**
* The localStorage object, for dependency injection
*
* @type {mw.SafeStorage}
*/
this.localStorage = localStorage;
}
/**
@ -73,7 +69,7 @@ class Config {
* @return {string|null} stored value or fallback or null if neither exists
*/
getFromLocalStorage( key, fallback ) {
const value = this.localStorage.get( key );
const value = mw.storage.get( key );
// localStorage will only store strings; if values `null`, `false` or
// `0` are set, they'll come out as `"null"`, `"false"` or `"0"`, so we
@ -98,7 +94,7 @@ class Config {
* @return {boolean} whether storing the item was successful
*/
setInLocalStorage( key, value ) {
return this.localStorage.set( key, value );
return mw.storage.set( key, value );
}
/**
@ -108,7 +104,7 @@ class Config {
* @return {boolean} whether storing the item was successful
*/
removeFromLocalStorage( key ) {
this.localStorage.remove( key );
mw.storage.remove( key );
// mw.storage.remove catches all exceptions and returns false if any
// occur, so we can't distinguish between actual issues, and
@ -187,7 +183,7 @@ class Config {
* @return {boolean}
*/
shouldShowStatusInfo() {
return !isMediaViewerEnabledOnClick( this.mwConfig, this.mwUser, this.localStorage ) && this.getFromLocalStorage( 'mmv-showStatusInfo' ) === '1';
return !isMediaViewerEnabledOnClick( this.mwConfig, this.mwUser, mw.storage ) && this.getFromLocalStorage( 'mmv-showStatusInfo' ) === '1';
}
/**

View file

@ -38,13 +38,7 @@ class MultimediaViewerBootstrap {
// TODO lazy-load config and htmlUtils
/** @property {Config} config - */
this.config = new Config(
mw.config.get( 'wgMultimediaViewer', {} ),
mw.config,
mw.user,
new mw.Api(),
mw.storage
);
this.config = new Config();
this.validExtensions = this.config.extensions();

View file

@ -63,20 +63,12 @@ class LightboxInterface extends UiElement {
super( $wrapper );
this.$wrapper = $wrapper;
this.localStorage = mw.storage;
// When opening we might override the theme-color, so remember the original value
const metaElement = document.querySelector( 'meta[name="theme-color"]' );
this.originalThemeColor = metaElement ? metaElement.getAttribute( 'content' ) : null;
/** @property {Config} config - */
this.config = new Config(
mw.config.get( 'wgMultimediaViewer', {} ),
mw.config,
mw.user,
new mw.Api(),
this.localStorage
);
this.config = new Config();
/**
* @property {ThumbnailWidthCalculator}
@ -118,7 +110,7 @@ class LightboxInterface extends UiElement {
this.setupCanvasButtons();
this.panel = new MetadataPanel( this.$postDiv, this.$aboveFold, this.localStorage, this.config );
this.panel = new MetadataPanel( this.$postDiv, this.$aboveFold, this.config );
this.buttons = new CanvasButtons( this.$preDiv, this.$closeButton, this.$fullscreenButton );
this.canvas = new Canvas( this.$innerWrapper, this.$imageWrapper, this.$wrapper );

View file

@ -33,10 +33,9 @@ class MetadataPanel extends UiElement {
* @param {jQuery} $aboveFold The brighter headline of the metadata panel (.mw-mmv-above-fold).
* Called "aboveFold" for historical reasons, but actually a part of the next sibling of the element
* is also above the fold (bottom of the screen).
* @param {mw.SafeStorage} localStorage the localStorage object, for dependency injection
* @param {Config} config A configuration object.
*/
constructor( $container, $aboveFold, localStorage, config ) {
constructor( $container, $aboveFold, config ) {
super( $container );
this.$aboveFold = $aboveFold;
@ -44,7 +43,7 @@ class MetadataPanel extends UiElement {
/** @property {Config} config - */
this.config = config;
this.initializeHeader( localStorage );
this.initializeHeader();
this.initializeImageMetadata();
this.initializeAboutLinks();
}
@ -165,14 +164,11 @@ class MetadataPanel extends UiElement {
/* Initialization methods */
/**
* Initializes the header, which contains the title, credit, and license elements.
*
* @param {mw.SafeStorage} localStorage the localStorage object, for dependency injection
*/
initializeHeader( localStorage ) {
initializeHeader() {
this.progressBar = new ProgressBar( this.$aboveFold );
this.scroller = new MetadataPanelScroller( this.$container, this.$aboveFold,
localStorage );
this.scroller = new MetadataPanelScroller( this.$container, this.$aboveFold );
this.$titleDiv = $( '<div>' )
.addClass( 'mw-mmv-title-contain' )

View file

@ -24,16 +24,12 @@ class MetadataPanelScroller extends UiElement {
/**
* @param {jQuery} $container The container for the panel (.mw-mmv-post-image).
* @param {jQuery} $aboveFold The control bar element (.mw-mmv-above-fold).
* @param {mw.SafeStorage} localStorage the localStorage object, for dependency injection
*/
constructor( $container, $aboveFold, localStorage ) {
constructor( $container, $aboveFold ) {
super( $container );
this.$aboveFold = $aboveFold;
/** @property {mw.SafeStorage} localStorage */
this.localStorage = localStorage;
/** @property {boolean} panelWasOpen state flag which will be used to detect open <-> closed transitions */
this.panelWasOpen = null;
@ -66,9 +62,9 @@ class MetadataPanelScroller extends UiElement {
}, 250 ) );
this.$container.on( 'mmv-metadata-open', () => {
if ( !this.hasOpenedMetadata && this.localStorage.store ) {
if ( !this.hasOpenedMetadata && mw.storage.store ) {
this.hasOpenedMetadata = true;
this.localStorage.set( 'mmv.hasOpenedMetadata', '1' );
mw.storage.set( 'mmv.hasOpenedMetadata', '1' );
}
} );
@ -133,7 +129,7 @@ class MetadataPanelScroller extends UiElement {
}
initialize() {
const value = this.localStorage.get( 'mmv.hasOpenedMetadata' );
const value = mw.storage.get( 'mmv.hasOpenedMetadata' );
// localStorage will only store strings; if values `null`, `false` or
// `0` are set, they'll come out as `"null"`, `"false"` or `"0"`, so we

View file

@ -18,9 +18,14 @@
const { isMediaViewerEnabledOnClick } = require( 'mmv.head' );
const { Config } = require( 'mmv.bootstrap' );
const { createLocalStorage, getDisabledLocalStorage, getFakeLocalStorage, getUnsupportedLocalStorage } = require( './mmv.testhelpers.js' );
const storage = mw.storage;
( function () {
QUnit.module( 'mmv.Config', QUnit.newMwEnvironment() );
QUnit.module( 'mmv.Config', QUnit.newMwEnvironment( {
afterEach: function () {
mw.storage = storage;
}
} ) );
QUnit.test( 'constructor', ( assert ) => {
const config = new Config( {}, {}, {}, {}, null );
@ -28,112 +33,112 @@ const { createLocalStorage, getDisabledLocalStorage, getFakeLocalStorage, getUns
} );
QUnit.test( 'getFromLocalStorage', function ( assert ) {
let localStorage, config;
let config;
localStorage = getUnsupportedLocalStorage(); // no browser support
config = new Config( {}, {}, {}, {}, localStorage );
mw.storage = getUnsupportedLocalStorage(); // no browser support
config = new Config( {}, {}, {}, {} );
assert.strictEqual( config.getFromLocalStorage( 'foo' ), null, 'Returns null when not supported' );
assert.strictEqual( config.getFromLocalStorage( 'foo', 'bar' ), 'bar', 'Returns fallback when not supported' );
localStorage = getDisabledLocalStorage(); // browser supports it but disabled
config = new Config( {}, {}, {}, {}, localStorage );
mw.storage = getDisabledLocalStorage(); // browser supports it but disabled
config = new Config( {}, {}, {}, {} );
assert.strictEqual( config.getFromLocalStorage( 'foo' ), null, 'Returns null when disabled' );
assert.strictEqual( config.getFromLocalStorage( 'foo', 'bar' ), 'bar', 'Returns fallback when disabled' );
localStorage = createLocalStorage( { getItem: this.sandbox.stub() } );
config = new Config( {}, {}, {}, {}, localStorage );
mw.storage = createLocalStorage( { getItem: this.sandbox.stub() } );
config = new Config( {}, {}, {}, {} );
localStorage.store.getItem.withArgs( 'foo' ).returns( null );
mw.storage.store.getItem.withArgs( 'foo' ).returns( null );
assert.strictEqual( config.getFromLocalStorage( 'foo' ), null, 'Returns null when key not set' );
assert.strictEqual( config.getFromLocalStorage( 'foo', 'bar' ), 'bar', 'Returns fallback when key not set' );
localStorage.store.getItem.reset();
localStorage.store.getItem.withArgs( 'foo' ).returns( 'boom' );
mw.storage.store.getItem.reset();
mw.storage.store.getItem.withArgs( 'foo' ).returns( 'boom' );
assert.strictEqual( config.getFromLocalStorage( 'foo' ), 'boom', 'Returns correct value' );
assert.strictEqual( config.getFromLocalStorage( 'foo', 'bar' ), 'boom', 'Returns correct value ignoring fallback' );
} );
QUnit.test( 'setInLocalStorage', function ( assert ) {
let localStorage, config;
let config;
localStorage = getUnsupportedLocalStorage(); // no browser support
config = new Config( {}, {}, {}, {}, localStorage );
mw.storage = getUnsupportedLocalStorage(); // no browser support
config = new Config( {}, {}, {}, {} );
assert.strictEqual( config.setInLocalStorage( 'foo', 'bar' ), false, 'Returns false when not supported' );
localStorage = getDisabledLocalStorage(); // browser supports it but disabled
config = new Config( {}, {}, {}, {}, localStorage );
mw.storage = getDisabledLocalStorage(); // browser supports it but disabled
config = new Config( {}, {}, {}, {} );
assert.strictEqual( config.setInLocalStorage( 'foo', 'bar' ), false, 'Returns false when disabled' );
localStorage = createLocalStorage( { setItem: this.sandbox.stub(), removeItem: this.sandbox.stub() } );
config = new Config( {}, {}, {}, {}, localStorage );
mw.storage = createLocalStorage( { setItem: this.sandbox.stub(), removeItem: this.sandbox.stub() } );
config = new Config( {}, {}, {}, {} );
assert.strictEqual( config.setInLocalStorage( 'foo', 'bar' ), true, 'Returns true when works' );
localStorage.store.setItem.throwsException( 'localStorage full!' );
mw.storage.store.setItem.throwsException( 'localStorage full!' );
assert.strictEqual( config.setInLocalStorage( 'foo', 'bar' ), false, 'Returns false on error' );
} );
QUnit.test( 'Localstorage remove', function ( assert ) {
let localStorage, config;
let config;
localStorage = getUnsupportedLocalStorage(); // no browser support
config = new Config( {}, {}, {}, {}, localStorage );
mw.storage = getUnsupportedLocalStorage(); // no browser support
config = new Config( {}, {}, {}, {} );
assert.strictEqual( config.removeFromLocalStorage( 'foo' ), true, 'Returns true when not supported' );
localStorage = getDisabledLocalStorage(); // browser supports it but disabled
config = new Config( {}, {}, {}, {}, localStorage );
mw.storage = getDisabledLocalStorage(); // browser supports it but disabled
config = new Config( {}, {}, {}, {} );
assert.strictEqual( config.removeFromLocalStorage( 'foo' ), true, 'Returns true when disabled' );
localStorage = createLocalStorage( { removeItem: this.sandbox.stub() } );
config = new Config( {}, {}, {}, {}, localStorage );
mw.storage = createLocalStorage( { removeItem: this.sandbox.stub() } );
config = new Config( {}, {}, {}, {} );
assert.strictEqual( config.removeFromLocalStorage( 'foo' ), true, 'Returns true when works' );
} );
QUnit.test( 'isMediaViewerEnabledOnClick', function ( assert ) {
const localStorage = createLocalStorage( { getItem: this.sandbox.stub() } );
mw.storage = createLocalStorage( { getItem: this.sandbox.stub() } );
const mwConfig = { get: this.sandbox.stub() };
const mwUser = { isNamed: this.sandbox.stub() };
mwUser.isNamed.returns( true );
mwConfig.get.withArgs( 'wgMediaViewer' ).returns( true );
mwConfig.get.withArgs( 'wgMediaViewerOnClick' ).returns( true );
assert.strictEqual( isMediaViewerEnabledOnClick( mwConfig, mwUser, localStorage ), true, 'Returns true for logged-in with standard settings' );
assert.strictEqual( isMediaViewerEnabledOnClick( mwConfig, mwUser ), true, 'Returns true for logged-in with standard settings' );
mwUser.isNamed.returns( true );
mwConfig.get.withArgs( 'wgMediaViewer' ).returns( false );
mwConfig.get.withArgs( 'wgMediaViewerOnClick' ).returns( true );
assert.strictEqual( isMediaViewerEnabledOnClick( mwConfig, mwUser, localStorage ), false, 'Returns false if opted out via user JS flag' );
assert.strictEqual( isMediaViewerEnabledOnClick( mwConfig, mwUser ), false, 'Returns false if opted out via user JS flag' );
mwUser.isNamed.returns( true );
mwConfig.get.withArgs( 'wgMediaViewer' ).returns( true );
mwConfig.get.withArgs( 'wgMediaViewerOnClick' ).returns( false );
assert.strictEqual( isMediaViewerEnabledOnClick( mwConfig, mwUser, localStorage ), false, 'Returns false if opted out via preferences' );
assert.strictEqual( isMediaViewerEnabledOnClick( mwConfig, mwUser ), false, 'Returns false if opted out via preferences' );
mwUser.isNamed.returns( false );
mwConfig.get.withArgs( 'wgMediaViewer' ).returns( false );
mwConfig.get.withArgs( 'wgMediaViewerOnClick' ).returns( true );
assert.strictEqual( isMediaViewerEnabledOnClick( mwConfig, mwUser, localStorage ), false, 'Returns false if anon user opted out via user JS flag' );
assert.strictEqual( isMediaViewerEnabledOnClick( mwConfig, mwUser ), false, 'Returns false if anon user opted out via user JS flag' );
mwUser.isNamed.returns( false );
mwConfig.get.withArgs( 'wgMediaViewer' ).returns( true );
mwConfig.get.withArgs( 'wgMediaViewerOnClick' ).returns( false );
assert.strictEqual( isMediaViewerEnabledOnClick( mwConfig, mwUser, localStorage ), false, 'Returns false if anon user opted out in some weird way' ); // apparently someone created a browser extension to do this
assert.strictEqual( isMediaViewerEnabledOnClick( mwConfig, mwUser ), false, 'Returns false if anon user opted out in some weird way' ); // apparently someone created a browser extension to do this
mwUser.isNamed.returns( false );
mwConfig.get.withArgs( 'wgMediaViewer' ).returns( true );
mwConfig.get.withArgs( 'wgMediaViewerOnClick' ).returns( true );
localStorage.store.getItem.withArgs( 'wgMediaViewerOnClick' ).returns( null );
assert.strictEqual( isMediaViewerEnabledOnClick( mwConfig, mwUser, localStorage ), true, 'Returns true for anon with standard settings' );
mw.storage.store.getItem.withArgs( 'wgMediaViewerOnClick' ).returns( null );
assert.strictEqual( isMediaViewerEnabledOnClick( mwConfig, mwUser ), true, 'Returns true for anon with standard settings' );
mwUser.isNamed.returns( false );
mwConfig.get.withArgs( 'wgMediaViewer' ).returns( true );
mwConfig.get.withArgs( 'wgMediaViewerOnClick' ).returns( true );
localStorage.store.getItem.withArgs( 'wgMediaViewerOnClick' ).returns( '0' );
assert.strictEqual( isMediaViewerEnabledOnClick( mwConfig, mwUser, localStorage ), false, 'Returns true for anon opted out via localSettings' );
mw.storage.store.getItem.withArgs( 'wgMediaViewerOnClick' ).returns( '0' );
assert.strictEqual( isMediaViewerEnabledOnClick( mwConfig, mwUser ), false, 'Returns true for anon opted out via localSettings' );
} );
QUnit.test( 'setMediaViewerEnabledOnClick sense check', function ( assert ) {
const localStorage = createLocalStorage( {
mw.storage = createLocalStorage( {
getItem: this.sandbox.stub(),
setItem: this.sandbox.stub(),
removeItem: this.sandbox.stub()
@ -142,7 +147,7 @@ const { createLocalStorage, getDisabledLocalStorage, getFakeLocalStorage, getUns
const mwConfig = new mw.Map();
mwConfig.set( 'wgMediaViewerEnabledByDefault', false );
const api = { saveOption: this.sandbox.stub().returns( $.Deferred().resolve() ) };
const config = new Config( {}, mwConfig, mwUser, api, localStorage );
const config = new Config( {}, mwConfig, mwUser, api );
mwUser.isNamed.returns( true );
api.saveOption.returns( $.Deferred().resolve() );
@ -151,16 +156,16 @@ const { createLocalStorage, getDisabledLocalStorage, getFakeLocalStorage, getUns
mwUser.isNamed.returns( false );
config.setMediaViewerEnabledOnClick( false );
assert.true( localStorage.store.setItem.called, 'For anons, opt-out is set in localStorage' );
assert.true( mw.storage.store.setItem.called, 'For anons, opt-out is set in localStorage' );
mwUser.isNamed.returns( false );
config.setMediaViewerEnabledOnClick( true );
assert.true( localStorage.store.removeItem.called, 'For anons, opt-in means clearing localStorage' );
assert.true( mw.storage.store.removeItem.called, 'For anons, opt-in means clearing localStorage' );
} );
QUnit.test( 'shouldShowStatusInfo', function ( assert ) {
const mwConfig = new mw.Map();
const fakeLocalStorage = getFakeLocalStorage();
mw.storage = getFakeLocalStorage();
const mwUser = { isNamed: this.sandbox.stub() };
const api = { saveOption: this.sandbox.stub().returns( $.Deferred().resolve() ) };
@ -169,7 +174,7 @@ const { createLocalStorage, getDisabledLocalStorage, getFakeLocalStorage, getUns
wgMediaViewerOnClick: true,
wgMediaViewerEnabledByDefault: true
} );
const config = new Config( {}, mwConfig, mwUser, api, fakeLocalStorage );
let config = new Config( {}, mwConfig, mwUser, api );
mwUser.isNamed.returns( true );
assert.strictEqual( config.shouldShowStatusInfo(), false, 'Status info is not shown by default' );
@ -187,14 +192,16 @@ const { createLocalStorage, getDisabledLocalStorage, getFakeLocalStorage, getUns
assert.strictEqual( config.shouldShowStatusInfo(), false, 'Further status changes have no effect #2' );
// make sure disabling calls maybeEnableStatusInfo() for logged-in as well
config.localStorage = getFakeLocalStorage();
mw.storage = getFakeLocalStorage();
config = new Config( {}, mwConfig, mwUser, api );
mwUser.isNamed.returns( false );
assert.strictEqual( config.shouldShowStatusInfo(), false, 'Status info is not shown by default for logged-in users' );
config.setMediaViewerEnabledOnClick( false );
assert.strictEqual( config.shouldShowStatusInfo(), true, 'Status info is shown after MMV is disabled the first time for logged-in users' );
// make sure popup is not shown immediately on disabled-by-default sites, but still works otherwise
config.localStorage = getFakeLocalStorage();
mw.storage = getFakeLocalStorage();
config = new Config( {}, mwConfig, mwUser, api );
mwConfig.set( 'wgMediaViewerEnabledByDefault', false );
assert.strictEqual( config.shouldShowStatusInfo(), false, 'Status info is not shown by default #2' );
config.setMediaViewerEnabledOnClick( true );

View file

@ -8,8 +8,7 @@ QUnit.test( '.empty()', ( assert ) => {
const panel = new MetadataPanel(
$qf,
$( '<div>' ).appendTo( $qf ),
mw.storage,
new Config( {}, mw.config, mw.user, new mw.Api(), mw.storage )
new Config( {}, mw.config, mw.user, new mw.Api() )
);
panel.empty();
@ -39,8 +38,7 @@ QUnit.test( '.setLocationData()', ( assert ) => {
const panel = new MetadataPanel(
$qf,
$( '<div>' ).appendTo( $qf ),
mw.storage,
new Config( {}, mw.config, mw.user, new mw.Api(), mw.storage )
new Config( {}, mw.config, mw.user, new mw.Api() )
);
const fileName = 'Foobar.jpg';
let latitude = 12.3456789;
@ -107,8 +105,7 @@ QUnit.test( '.setImageInfo()', function ( assert ) {
const panel = new MetadataPanel(
$qf,
$( '<div>' ).appendTo( $qf ),
mw.storage,
new Config( {}, mw.config, mw.user, new mw.Api(), mw.storage )
new Config( {}, mw.config, mw.user, new mw.Api() )
);
const title = 'Foo bar';
const image = {
@ -178,8 +175,7 @@ QUnit.skip( 'Setting permission information works as expected', ( assert ) => {
const panel = new MetadataPanel(
$qf,
$( '<div>' ).appendTo( $qf ),
mw.storage,
new Config( {}, mw.config, mw.user, new mw.Api(), mw.storage )
new Config( {}, mw.config, mw.user, new mw.Api() )
);
// make sure license is visible as it contains the permission
@ -193,8 +189,7 @@ QUnit.test( 'Date formatting', ( assert ) => {
const panel = new MetadataPanel(
$qf,
$( '<div>' ).appendTo( $qf ),
mw.storage,
new Config( {}, mw.config, mw.user, new mw.Api(), mw.storage )
new Config( {}, mw.config, mw.user, new mw.Api() )
);
const date1 = 'Garbage';
const result = panel.formatDate( date1 );
@ -207,7 +202,10 @@ QUnit.test( 'About links', function ( assert ) {
this.sandbox.stub( mw.user, 'isAnon' );
// eslint-disable-next-line no-new
new MetadataPanel( $qf.empty(), $( '<div>' ).appendTo( $qf ), mw.storage, new Config( {}, mw.config, mw.user, new mw.Api(), mw.storage ) );
new MetadataPanel(
$qf.empty(), $( '<div>' ).appendTo( $qf ),
new Config( {}, mw.config, mw.user, new mw.Api() )
);
assert.strictEqual( $qf.find( '.mw-mmv-about-link' ).length, 1, 'About link is created.' );
} );

View file

@ -17,18 +17,22 @@
const { createLocalStorage, getFakeLocalStorage, getUnsupportedLocalStorage } = require( '../mmv.testhelpers.js' );
const { MetadataPanelScroller } = require( 'mmv' );
const storage = mw.storage;
( function () {
QUnit.module( 'mmv.ui.metadataPanelScroller', QUnit.newMwEnvironment( {
beforeEach: function () {
this.clock = this.sandbox.useFakeTimers();
},
afterEach: function () {
mw.storage = storage;
}
} ) );
QUnit.test( 'empty()', ( assert ) => {
const $qf = $( '#qunit-fixture' );
const localStorage = getFakeLocalStorage();
const scroller = new MetadataPanelScroller( $qf, $( '<div>' ).appendTo( $qf ), localStorage );
mw.storage = getFakeLocalStorage();
const scroller = new MetadataPanelScroller( $qf, $( '<div>' ).appendTo( $qf ) );
scroller.empty();
assert.strictEqual( scroller.$container.hasClass( 'invite' ), false, 'We successfully reset the invite' );
@ -37,7 +41,7 @@ const { MetadataPanelScroller } = require( 'mmv' );
QUnit.test( 'Metadata div is only animated once', ( assert ) => {
const $qf = $( '#qunit-fixture' );
let displayCount = null; // pretend it doesn't exist at first
const localStorage = createLocalStorage( {
mw.storage = createLocalStorage( {
// We simulate localStorage to avoid test side-effects
getItem: function () {
return displayCount;
@ -49,7 +53,7 @@ const { MetadataPanelScroller } = require( 'mmv' );
displayCount = null;
}
} );
const scroller = new MetadataPanelScroller( $qf, $( '<div>' ).appendTo( $qf ), localStorage );
const scroller = new MetadataPanelScroller( $qf, $( '<div>' ).appendTo( $qf ) );
scroller.attach();
@ -81,8 +85,8 @@ const { MetadataPanelScroller } = require( 'mmv' );
QUnit.test( 'No localStorage', function ( assert ) {
const $qf = $( '#qunit-fixture' );
const localStorage = getUnsupportedLocalStorage();
const scroller = new MetadataPanelScroller( $qf, $( '<div>' ).appendTo( $qf ), localStorage );
mw.storage = getUnsupportedLocalStorage();
const scroller = new MetadataPanelScroller( $qf, $( '<div>' ).appendTo( $qf ) );
this.sandbox.stub( $.fn, 'scrollTop', () => 10 );
@ -93,12 +97,12 @@ const { MetadataPanelScroller } = require( 'mmv' );
QUnit.test( 'localStorage is full', function ( assert ) {
const $qf = $( '#qunit-fixture' );
const localStorage = createLocalStorage( {
mw.storage = createLocalStorage( {
getItem: this.sandbox.stub().returns( null ),
setItem: this.sandbox.stub().throwsException( 'I am full' ),
removeItem: this.sandbox.stub()
} );
const scroller = new MetadataPanelScroller( $qf, $( '<div>' ).appendTo( $qf ), localStorage );
const scroller = new MetadataPanelScroller( $qf, $( '<div>' ).appendTo( $qf ) );
this.sandbox.stub( $.fn, 'scrollTop', () => 10 );
@ -110,7 +114,7 @@ const { MetadataPanelScroller } = require( 'mmv' );
scroller.scroll();
assert.true( localStorage.store.setItem.calledOnce, 'localStorage only written once' );
assert.true( mw.storage.store.setItem.calledOnce, 'localStorage only written once' );
scroller.unattach();
} );
@ -149,17 +153,17 @@ const { MetadataPanelScroller } = require( 'mmv' );
const $qf = $( '#qunit-fixture' );
const $container = $( '<div>' ).css( 'height', 100 ).appendTo( $qf );
const $aboveFold = $( '<div>' ).css( 'height', 50 ).appendTo( $container );
const fakeLocalStorage = createLocalStorage( {
mw.storage = createLocalStorage( {
getItem: this.sandbox.stub().returns( null ),
setItem: function () {},
removeItem: function () {}
} );
const scroller = new MetadataPanelScroller( $container, $aboveFold, fakeLocalStorage );
const scroller = new MetadataPanelScroller( $container, $aboveFold );
const keydown = $.Event( 'keydown' );
stubScrollFunctions( this.sandbox, scroller );
this.sandbox.stub( fakeLocalStorage.store, 'setItem' );
this.sandbox.stub( mw.storage.store, 'setItem' );
// First phase of the test: up and down arrows
@ -169,12 +173,12 @@ const { MetadataPanelScroller } = require( 'mmv' );
assert.strictEqual( $window.scrollTop(), 0, 'scrollTop should be set to 0' );
assert.strictEqual( fakeLocalStorage.store.setItem.called, false, 'The metadata hasn\'t been open yet, no entry in localStorage' );
assert.strictEqual( mw.storage.store.setItem.called, false, 'The metadata hasn\'t been open yet, no entry in localStorage' );
keydown.which = 38; // Up arrow
scroller.keydown( keydown );
assert.strictEqual( fakeLocalStorage.store.setItem.calledWithExactly( 'mmv.hasOpenedMetadata', '1' ), true, 'localStorage knows that the metadata has been open' );
assert.strictEqual( mw.storage.store.setItem.calledWithExactly( 'mmv.hasOpenedMetadata', '1' ), true, 'localStorage knows that the metadata has been open' );
keydown.which = 40; // Down arrow
scroller.keydown( keydown );