it('should allow setting of preferences via the address bar', () => { const prefix = 'gu.prefs.'; const hash = { a: 1, b: false, c: 'str', switchOn: 'd', switchOff: 'e', }; const hashAsAnchor = Object.keys(hash) .map(h => `${prefix + h}=${String(hash[h])}`) .join('&'); // string tests setting of prefs, switches of int, string, booleans const qs = { hash: `#${hashAsAnchor}` }; // jsdom didn't fully implement Number.isNaN :facepalm: /* eslint-disable no-restricted-properties */ // $FlowFixMe Number.isNaN = window.isNaN; /* eslint-enable no-restricted-properties */ userPrefs.setPrefs(qs); expect(userPrefs.get('a')).toBe(1); // int expect(userPrefs.get('b')).toBe(false); // bool expect(userPrefs.get('c')).toBe('str'); // string expect(userPrefs.isOn('d')).toBeTruthy(); expect(userPrefs.isOff('e')).toBeTruthy(); });
readPrefs(id: string): void { // update user prefs const prefs = userPrefs.get(prefName); if (prefs && prefs[id]) { this.setState('hidden'); } }
const addScrollHandler = (): void => { let scrollRunning: boolean = false; const onScroll = (): void => { if (!scrollRunning) { scrollRunning = true; fastdom.read(() => { mediator.emitEvent('window:throttledScroll'); scrollRunning = false; }); } }; // #? is still still needed? addEventListener( window, 'scroll', userPrefs.get('use-idle-callback') && 'requestIdleCallback' in window ? () => { window.requestIdleCallback(onScroll); } : onScroll, { passive: true } ); };
remember(): void { if (this.isRemembered()) { return; } const messageStates = userPrefs.get(this.prefs) || []; messageStates.push(this.id); userPrefs.set(this.prefs, uniq(messageStates)); }
fastdom.defer(1, function () { expect(userPrefs.get(storageId)).toEqual(expectedValue); // now close container simulateClick(); fastdom.defer(1, function () { expect(userPrefs.get(storageId)).toEqual({}); done(); }); });
const canShow: () => Promise<boolean> = () => { const bannerCanBeLoadedAgainAfter = userPrefs.get( bannerCanBeLoadedAgainAfterKey ); return Promise.resolve( updateLink !== null && isUserLoggedIn() && !( bannerCanBeLoadedAgainAfter && new Date(bannerCanBeLoadedAgainAfter) > new Date() ) ); };
updatePref(id: string): void { // update user prefs let prefs = userPrefs.get(prefName); const prefValue = id; if (this.state === 'displayed') { delete prefs[prefValue]; } else { if (!prefs) { prefs = {}; } prefs[prefValue] = 'closed'; } userPrefs.set(prefName, prefs); }
this.on('user:loaded', () => { this.initState(); this.renderCommentBar(); if (this.user) { if (this.comments) { this.comments.addUser(this.user); } const userPageSize = userPrefs.get('discussion.pagesize'); let pageSize = defaultPagesize; if (typeof userPageSize === 'number') { pageSize = userPageSize; } else if (userPageSize === 'All') { pageSize = config.get('switches.discussionAllPageSize') ? 'All' : 100; } this.initPageSizeDropdown(pageSize); if ( this.comments && config.get('switches.discussionPageSize') && isBreakpoint({ min: 'tablet' }) ) { this.comments.options.pagesize = pageSize; } if (this.user && this.user.isStaff) { this.removeState('not-staff'); this.setState('is-staff'); } } // Only truncate the loaded comments on this initial fetch, // and when no comment ID or #comments location is present. const shouldTruncate = !commentId && window.location.hash !== '#comments'; this.loadComments({ comment: commentId, shouldTruncate, }).catch(() => this.logError('Comments')); });
it('should remove data from userprefs and getDefaultLocation if user removes data', () => { config.page = { weatherapiurl: 'foo', edition: 'bar', }; const cityPreference = { store: 'remove', id: 'qux', city: 'doo', }; Weather.saveDeleteLocalStorage(cityPreference); expect(userPrefs.get('weather-location')).toBeUndefined(); expect(fetchJsonMock.mock.calls[0][0]).toEqual('foo.json'); });
const removeAndRemember = ( e: Event, { iframe, analytics }: { iframe: HTMLElement, analytics: Analytics } ): void => { const currentListPrefs = userPrefs.get(`email-sign-up-${analytics.formType}`) || []; currentListPrefs.push(`${analytics.listName}`); userPrefs.set( `email-sign-up-${analytics.formType}`, uniq(currentListPrefs) ); $(iframe).remove(); trackNonClickInteraction( `rtrt | email form inline | ${analytics.formType} | ${ analytics.listName } | ${analytics.signedIn} | form hidden` ); };
return getBannerParams().then(params => { if ( canShowBannerSync( params.minArticlesBeforeShowingBanner, params.userCohort ) ) { const userLastClosedBannerAt = userPrefs.get(lastClosedAtKey); if (!userLastClosedBannerAt) { // show the banner if we can't get a value for this return Promise.resolve(true); } return hasBannerBeenRedeployedSinceClosed( userLastClosedBannerAt, getReaderRevenueRegion(geolocationGetSync()) ); } return Promise.resolve(false); });
it('should set data in userprefs and fetchWeatherData if user searches', () => { config.page = { weatherapiurl: 'foo', edition: 'bar', }; const cityPreference = { store: 'set', id: 'qux', city: 'doo', }; Weather.saveDeleteLocalStorage(cityPreference); expect(userPrefs.get('weather-location')).toEqual({ id: 'qux', city: 'doo', }); expect(fetchJsonMock.mock.calls[0][0]).toEqual( 'foo/qux.json?_edition=bar' ); });
const shouldMakeTimestampsRelative = (): boolean => userPrefs.get(PREF_RELATIVE_TIMESTAMPS) !== null ? userPrefs.get(PREF_RELATIVE_TIMESTAMPS) : true;
it('should remove a user preference under a given key', () => { userPrefs.remove('key'); expect(userPrefs.get('key')).toBeNull(); });
initMainComments(): void { const commentId = this.getCommentIdFromHash(); const order = userPrefs.get('discussion.order') || (this.getDiscussionClosed() ? 'oldest' : 'newest'); const threading = userPrefs.get('discussion.threading') || 'collapsed'; const defaultPagesize = isBreakpoint({ min: 'tablet' }) ? 25 : 10; this.comments = new Comments({ discussionId: this.getDiscussionId(), order, pagesize: defaultPagesize, threading, }); if (this.comments) { this.comments.attachTo(qwery('.js-discussion-main-comments')[0]); } if (this.comments) { this.comments.on('untruncate-thread', () => this.removeTruncation() ); } this.on('click,', '.js-discussion-author-link', () => this.removeTruncation() ); this.on( 'click', '.js-discussion-change-page, .js-discussion-show-button', () => { mediator.emit('discussion:comments:get-more-replies'); this.removeTruncation(); } ); if (this.comments) { this.comments.on('rendered', (paginationHtml: string) => { const newPagination = bonzo.create(paginationHtml); const toolbarEl = qwery('.js-discussion-toolbar', this.elem)[0]; const container = $( '.js-discussion-pagination', toolbarEl ).empty(); // When the pagesize is 'All', do not show any pagination. if (this.comments && !this.comments.isAllPageSizeActive()) { container.html(newPagination); } }); } this.setState('loading'); this.on('user:loaded', () => { this.initState(); this.renderCommentBar(); if (this.user) { if (this.comments) { this.comments.addUser(this.user); } const userPageSize = userPrefs.get('discussion.pagesize'); let pageSize = defaultPagesize; if (typeof userPageSize === 'number') { pageSize = userPageSize; } else if (userPageSize === 'All') { pageSize = config.get('switches.discussionAllPageSize') ? 'All' : 100; } this.initPageSizeDropdown(pageSize); if ( this.comments && config.get('switches.discussionPageSize') && isBreakpoint({ min: 'tablet' }) ) { this.comments.options.pagesize = pageSize; } if (this.user && this.user.isStaff) { this.removeState('not-staff'); this.setState('is-staff'); } } // Only truncate the loaded comments on this initial fetch, // and when no comment ID or #comments location is present. const shouldTruncate = !commentId && window.location.hash !== '#comments'; this.loadComments({ comment: commentId, shouldTruncate, }).catch(() => this.logError('Comments')); }); this.getUser(); }
initToolbar(): void { const $orderLabel = $('.js-comment-order'); const $threadingLabel = $('.js-comment-threading'); $threadingLabel.text(this.comments && this.comments.options.threading); $orderLabel.text(this.comments && this.comments.options.order); this.on( 'click', '.js-comment-order-dropdown .popup__action', (e: Event) => { bean.fire( qwery('.js-comment-order-dropdown [data-toggle]')[0], 'click' ); if (this.comments) { // $FlowFixMe this.comments.options.order = bonzo(e.currentTarget).data( 'order' ); } $orderLabel.text(this.comments && this.comments.options.order); userPrefs.set( 'discussion.order', this.comments && this.comments.options.order ); this.loadComments({ page: 1 }); } ); this.on( 'click', '.js-comment-threading-dropdown .popup__action', (e: Event) => { bean.fire( qwery('.js-comment-threading-dropdown [data-toggle]')[0], 'click' ); if (this.comments) { // $FlowFixMe this.comments.options.threading = bonzo( e.currentTarget ).data('threading'); } $threadingLabel.text( this.comments && this.comments.options.threading ); userPrefs.set( 'discussion.threading', this.comments && this.comments.options.threading ); this.loadComments(); } ); if (config.get('page.section') === 'crosswords') { const $timestampsLabel = $('.js-timestamps'); const updateLabelText = (prefValue?: boolean) => { $timestampsLabel.text(prefValue ? 'Relative' : 'Absolute'); }; updateLabelText(); const PREF_RELATIVE_TIMESTAMPS = 'discussion.enableRelativeTimestamps'; // Default to true const prefValue = userPrefs.get(PREF_RELATIVE_TIMESTAMPS) !== null ? userPrefs.get(PREF_RELATIVE_TIMESTAMPS) : true; updateLabelText(prefValue); this.on( 'click', '.js-timestamps-dropdown .popup__action', (e: Event) => { const format = bonzo(e.currentTarget).data('timestamp'); bean.fire( qwery('.js-timestamps-dropdown [data-toggle]')[0], 'click' ); updateLabelText(format === 'relative'); userPrefs.set( PREF_RELATIVE_TIMESTAMPS, format === 'relative' ); this.loadComments(); } ); } }
const hasUserAcknowledgedBanner = (id: string): boolean => { const messageStates = userPrefs.get('messages'); return messageStates && messageStates.includes(id); };
isRemembered(): boolean { const messageStates = userPrefs.get(this.prefs) || []; return messageStates.includes(this.id); }
fastdom.defer(1, function () { expect(userPrefs.get(storageId)).toEqual({}); done(); });
const getStoredValue = (key: string): boolean => userPrefs.get(`${KEY_PREFIX}.${key}`) !== false;
const userHasRemoved = (id: string, formType: string): boolean => { const currentListPrefs = userPrefs.get(`email-sign-up-${formType}`); return !!currentListPrefs && currentListPrefs.includes(id); };
it('should retrieve a user preference under a given key', () => { expect(userPrefs.get('key')).toBe('value'); });