Example #1
0
const handleResponse = (url: string, data: Object): Promise<Object> => {
    const tailorData = localStorage.get('gu.tailor') || {};
    const hour = 1000 * 60 * 60;

    tailorData[url] = data;

    localStorage.set('gu.tailor', tailorData, { expires: Date.now() + hour });

    return Promise.resolve(data);
};
Example #2
0
const canShow = (): Promise<boolean> => {
    if (userCanDismissAlerts()) {
        knownAlertIDs = local.get(knownAlertIDsStorageKey) || {};

        return fetchBreakingNews()
            .then(parseResponse)
            .then(getRelevantAlerts)
            .then(pruneKnownAlertIDs)
            .then(filterAlertsByDismissed)
            .then(filterAlertsByAge)
            .then(pickNewest)
            .then(alert => {
                if (alert) {
                    alertToShow = alert;
                    return true;
                }
                return false;
            })
            .catch(ex => {
                reportError(ex, {
                    feature: 'breaking-news',
                });
                return false;
            });
    }

    return Promise.resolve(false);
};
Example #3
0
const fetchData = (
    type: string,
    bypassStorage: boolean,
    queryParams?: Object
): Promise<Object> => {
    const url = getURL(type, queryParams);

    // exit if no valid url end point, or tailor switch is off
    if (!url || !config.switches.useTailorEndpoints) {
        return Promise.resolve({});
    }

    const tailorData = bypassStorage ? null : localStorage.get('gu.tailor');

    // if data in local storage, resolve with this
    if (tailorData && tailorData[url]) {
        return Promise.resolve(tailorData[url]);
    }

    return fetchJson(url)
        .then(data => handleResponse(url, data))
        .catch(err => {
            handleError(url, err);
            return Promise.resolve({});
        });
};
Example #4
0
export const shouldAutoSigninInUser = (): boolean => {
    const signedInUser = !!getCookieByName(cookieName);
    const checkFacebook = !!local.get(fbCheckKey);
    return (
        !signedInUser && !checkFacebook && !hasUserSignedOutInTheLast24Hours()
    );
};
const logView = (testId: string): void => {
    viewLog.push({
        date: new Date().getTime(),
        testId,
    });

    local.set(viewKey, viewLog.slice(-maxLogEntries));
};
Example #6
0
        test('participations that have been removed/renamed should be removed', () => {
            const dummyTest = genAbTest('DummyTestNew');

            local.set(
                participationsKey,
                '{ "value": { "DummyTest": { "variant": "foo" } } }'
            );
            segment([dummyTest]);
            cleanParticipations([dummyTest]);

            expect(getParticipations()).toEqual({});
        });
Example #7
0
        test('expired tests should be cleaned from participations', () => {
            const dummyTest = genAbTest('DummyTest');

            local.set(
                participationsKey,
                '{ "value": { "DummyTest": { "variant": "foo" } } }'
            );
            dummyTest.expiry = '1999-01-01';
            segment([dummyTest]);
            cleanParticipations([dummyTest]);

            expect(getParticipations()).toEqual({});
        });
Example #8
0
const getSummary = (): Object => {
    if (!summaryCache) {
        summaryCache = local.get(storageKeySummary);

        if (
            !isObject(summaryCache) ||
            !isObject(summaryCache.tags) ||
            typeof summaryCache.periodEnd !== 'number'
        ) {
            summaryCache = {
                periodEnd: today,
                tags: {},
                showInMegaNav: true,
            };
        }
    }
    return summaryCache;
};
const getVisitedValue = (): string => {
    const visitCount: number = local.get('gu.alreadyVisited') || 0;

    if (visitCount <= 5) {
        return visitCount.toString();
    } else if (visitCount >= 6 && visitCount <= 9) {
        return '6-9';
    } else if (visitCount >= 10 && visitCount <= 15) {
        return '10-15';
    } else if (visitCount >= 16 && visitCount <= 19) {
        return '16-19';
    } else if (visitCount >= 20 && visitCount <= 29) {
        return '20-29';
    } else if (visitCount >= 30) {
        return '30plus';
    }

    return visitCount.toString();
};
 it('over thirty, includes it in the bucket "30plus"', () => {
     local.set('gu.alreadyVisited', 300);
     expect(buildPageTargeting().fr).toEqual('30plus');
 });
 it('passes a value of 0 if the value is not stored', () => {
     local.remove('gu.alreadyVisited');
     expect(buildPageTargeting().fr).toEqual('0');
 });
 it('can pass a value of five or less', () => {
     local.set('gu.alreadyVisited', 5);
     expect(buildPageTargeting().fr).toEqual('5');
 });
 it('between five and thirty, includes it in a bucket in the form "x-y"', () => {
     local.set('gu.alreadyVisited', 18);
     expect(buildPageTargeting().fr).toEqual('16-19');
 });
Example #14
0
const bootStandard = (): void => {
    markTime('standard start');

    catchErrorsWithContext([
        [
            'ga-user-timing-standard-start',
            () => {
                trackPerformance(
                    'Javascript Load',
                    'standardStart',
                    'Standard start parse time'
                );
            },
        ],
    ]);

    /*
        Add global pooled event listeners
        CAUTION: those are *passive*, which means calls to event.preventDefault
        will be ignored

        Adds a global window:throttledScroll event to mediator, which throttles
        scroll events until there's a spare animationFrame.
        Callbacks of all listeners to window:throttledScroll are run in a
        fastdom.read, meaning they can all perform DOM reads for free
        (after the first one that needs layout triggers it).
        However, this means it's VITAL that all writes in callbacks are
        delegated to fastdom.
    */
    addErrorHandler();
    addScrollHandler();
    addResizeHandler();

    // Set adtest query if url param declares it
    setAdTestCookie();

    // If we turn off the ad-free trial, immediately remove the cookie
    if (!config.get('switches.adFreeSubscriptionTrial')) {
        removeCookie('GU_AF1');
    }

    // set a short-lived cookie to trigger server-side ad-freeness
    // if the user is genuinely ad-free, this one will be overwritten
    // in user-features
    if (window.location.hash.match(/[#&]noadsaf(&.*)?$/)) {
        const daysToLive = 1;
        const isCrossSubDomain = true;
        const forcedAdFreeValidSeconds = 30;
        const forcedAdFreeExpiryTime = new Date();
        forcedAdFreeExpiryTime.setTime(
            forcedAdFreeExpiryTime.getTime() + forcedAdFreeValidSeconds * 1000
        );
        addCookie(
            'GU_AF1',
            forcedAdFreeExpiryTime.getTime().toString(),
            daysToLive,
            isCrossSubDomain
        );
    }

    // set local storage: gu.alreadyVisited
    if (window.guardian.isEnhanced) {
        const key = 'gu.alreadyVisited';
        const alreadyVisited = storage.get(key) || 0;
        storage.set(key, alreadyVisited + 1);
    }

    if (config.get('switches.blockIas') && navigator.serviceWorker) {
        navigator.serviceWorker.ready.then(swreg => {
            const sw = swreg.active;
            const ias = window.location.hash.includes('noias');
            sw.postMessage({ ias });
        });
    }

    // initilaise the email/outbrain check mediator
    initCheckMediator();

    ophan.setEventEmitter(mediator);

    /*  Membership access
        Items with either of the following fields require Membership access
        - membershipAccess=members-only
        - membershipAccess=paid-members-only
        Authenticating requires CORS and withCredentials. If we don't cut the
        mustard then pass through.
    */
    if (config.get('page.requiresMembershipAccess')) {
        handleMembershipAccess();
    }

    identityInit();

    newHeaderInit();

    initAtoms();

    showHiringMessage();

    markTime('standard end');

    catchErrorsWithContext([
        [
            'ga-user-timing-standard-end',
            () => {
                trackPerformance(
                    'Javascript Load',
                    'standardEnd',
                    'Standard end parse time'
                );
            },
        ],
    ]);
};
Example #15
0
const saveSummary = (summary: Object): void => {
    summaryCache = summary;
    local.set(storageKeySummary, summary);
};
Example #16
0
 deprecatedKeys.forEach(key => localStorage.remove(key));
Example #17
0
const storeKnownAlertIDs = (): void => {
    local.set(knownAlertIDsStorageKey, knownAlertIDs);
};
const getVisitCount = (): number => local.get('gu.alreadyVisited') || 0;
const clearViewLog = (): void => {
    local.remove(viewKey);
};
Example #20
0
const reset = (): void => {
    historyCache = undefined;
    summaryCache = undefined;
    local.remove(storageKeyHistory);
    local.remove(storageKeySummary);
};
Example #21
0
const saveHistory = (history: Array<Array<any>>): void => {
    historyCache = history;
    local.set(storageKeyHistory, history);
};
Example #22
0
const retrieve = (n: string): string => {
    const k: string = `kx${n}`;

    return local.getRaw(k) || getCookie(`${k}=([^;]*)`) || '';
};
    beforeEach(() => {
        config.page = {
            authorIds: 'profile/gabrielle-chan',
            blogIds: 'a/blog',
            contentType: 'Video',
            edition: 'US',
            keywordIds:
                'uk-news/prince-charles-letters,uk/uk,uk/prince-charles',
            pageId: 'football/series/footballweekly',
            publication: 'The Observer',
            seriesId: 'film/series/filmweekly',
            source: 'ITN',
            sponsorshipType: 'advertisement-features',
            tones: 'News',
            videoDuration: 63,
            sharedAdTargeting: {
                bl: ['blog'],
                br: 'p',
                co: ['gabrielle-chan'],
                ct: 'video',
                edition: 'us',
                k: ['prince-charles-letters', 'uk/uk', 'prince-charles'],
                ob: 't',
                p: 'ng',
                se: ['filmweekly'],
                su: ['5'],
                tn: ['news'],
                url: '/football/series/footballweekly',
            },
            isSensitive: false,
        };

        config.ophan = {
            pageViewId: 'presetOphanPageViewId',
        };

        commercialFeatures.adFree = false;

        // Reset mocking to default values.
        getAdConsentState.mockReturnValue(null);
        getCookie.mockReturnValue('ng101');

        getBreakpoint.mockReturnValue('mobile');
        getReferrer.mockReturnValue('');

        isUserLoggedIn.mockReturnValue(true);

        getUserSegments.mockReturnValue(['seg1', 'seg2']);

        getParticipations.mockReturnValue({
            MtMaster: {
                variant: 'variantName',
            },
        });
        getKruxSegments.mockReturnValue(['E012712', 'E012390', 'E012478']);

        local.set('gu.alreadyVisited', 0);

        getSync.mockReturnValue('US');

        expect.hasAssertions();
    });
Example #24
0
const getRecentSearch = (): ?string => local.get(SEARCH_STORAGE_KEY);
// @flow
import { local } from 'lib/storage';

const viewKey = 'gu.contributions.views';
const viewLog = local.get(viewKey) || [];

const maxLogEntries = 50;

/**
 * Log that the user has seen an Epic test so we can limit how many times they see it.
 * The number of entries is limited to the number in maxLogEntries.
 *
 * @param testId
 */
const logView = (testId: string): void => {
    viewLog.push({
        date: new Date().getTime(),
        testId,
    });

    local.set(viewKey, viewLog.slice(-maxLogEntries));
};

const viewsInPreviousDays = (days: number, testId: ?string): number => {
    const ms = days * 1000 * 60 * 60 * 24;
    const now = new Date().getTime();

    return viewLog.filter(
        view => (testId ? view.testId === testId : true) && view.date > now - ms
    ).length;
};
Example #26
0
const clearRecentSearch = (): void => local.remove(SEARCH_STORAGE_KEY);
Example #27
0
const userCanDismissAlerts = (): ?boolean => local.isAvailable();
Example #28
0
const saveSearchTerm = (term: string) => local.set(SEARCH_STORAGE_KEY, term);
Example #29
0
 bean.on($('.js-experiments-clear-ab')[0], 'click', () => {
     storage.set('gu.experiments.ab', JSON.stringify([]));
     selectRadios();
 });
Example #30
0
const getHistory = (): Array<Array<any>> => {
    historyCache = historyCache || local.get(storageKeyHistory) || [];
    return historyCache;
};