<commit_before>// ==UserScript==
// @name        backpack.tf Premium Recent Sales Finder
// @namespace   http://steamcommunity.com/profiles/76561198080179568/
// @author      Julia
// @description Adds coloring to history pages indicating recent sales and direct link to user's outpost page
// @include     /^https?:\/\/(.*\.)?backpack\.tf(\:\d+)?\/item\/.*/
// @include     /^https?:\/\/(.*\.)?backpack\.tf(\:\d+)?\/profiles\/\d{17}\/?$/
// @version     4.0
// @grant       none
// @run-at      document-end
// @updateURL   https://github.com/juliarose/backpack.tf-premium-sales-finder/raw/master/backpacktf-premium-sales-finder.meta.js
// @downloadURL https://github.com/juliarose/backpack.tf-premium-sales-finder/raw/master/backpacktf-premium-sales-finder.user.js
// ==/UserScript==

(function(){
    'use strict';

    // all of the code that runs when the page is loaded is here
    function ready() {
        [
            // item history pages
            {
                pattern: /^https?:\/\/(.*\.)?backpack\.tf(\:\d+)?\/item\/./,
                fn: getHistory
            },
            // inventory pages
            {
                pattern: /^https?:\/\/(.*\.)?backpack\.tf\/profiles\/\d{17}\#\!\/compare\/\d{10}\/\d{10}\/nearest/,
                fn: getInventory
            }
        ].find((mode) => {
            // will call function when something matches, then stop
            return mode.pattern.test(location.href) && (mode.fn() || true);
        });
    }

    /**
     * Super basic omitEmpty function
     * @param {Object} obj - Object to omit values from
     * @returns {Object} Object with null, undefined, or empty string values omitted
     */
    function omitEmpty(obj) {
        // create clone so we do not modify original object
        let result = Object.assign({}, obj);

        for (let k in result) {
            if (result[k] === null || result[k] === undefined || result[k] === '') {
                delete result[k];
            }
        }

        return result;
    }

    /**
     * Convert date to unix timestamp
     * @param {Object} date - Date object
     * @returns {Number} Unix timestamp
     */
    function toX(date) {
        return Math.round(date.getTime() / 1000);
    }

    // called on history pages
    function getHistory() {
        // jquery elements
        const PAGE = {
            $history: $('.history-sheet table.table'),
            $item: $('.item'),
            $panelExtras: $('.panel-extras'),
            $username: $('.username')
        };

        // add bot.tf listing snapshots link to page
        function addBotTFLink() {
            // only if an item exists on page
            if (PAGE.$item.length === 0) return;

            let data = PAGE.$item.data();
            let params = omitEmpty({
                def: data.defindex,
                q: data.quality,
                ef: data.effect_name,
                craft: data.craftable ? 1 : 0,
                aus: data.australium ? 1 : 0,
                ks: data.ks_tier || 0
            });
            let queryString = Object.keys(params).map(key => `key=${encodeURIComponent(params[key])}`).join('&');
            let url = 'https://bot.tf/stats/listings?' + queryString;
            let $pullRight = PAGE.$panelExtras.find('.pull-right');
            let $btnGroup = $('
');
            let $link = $(`<a class="btn btn-panel" href="${url}"><i class="fa fa-search"></i> Bot.tf</a>`);

            if ($pullRight.length === 0) {
                $pullRight = $('
');
                PAGE.$panelExtras.append($pullRight);
            }

            $btnGroup.append($link);
            $pullRight.prepend($btnGroup);
        }

        // add contents to the page
        function addTableLinks() {
            /**
             * Get columns from history table
             * @returns {Object} An object containing details for each column labeled by header text e.g. { 'ID': { index: 0, $header: $column } }
             */
            function getColumns() {
                let columns = {}; // column elements

                PAGE.$history.find('thead tr th').each((index, el) => {
                    let $column = $(el);
                    let text = $column.text().trim();

                    // assign column based on column heading text
                    columns[text] = {
                        // add index so we know the order of each column
                        index: $column.index(),
                        $header: $column
                    };
                });

                return columns;
            }

            /**
             * Get a value from a URL according to pattern
             * @param {String} url - URL
             * @param {Object} pattern - Pattern to match. The 1st match group should be the value we are trying to get
             * @returns {(String|null)} Matched value, or null if the pattern does not match
             */
            function getValueFromURL(url, pattern) {
                let match = (url || '').match(pattern);

                return match && match[1];
            }

            /**
             * Add contents for a row
             * @param {Number} index - Index of row
             * @param {Object} el - DOM element of row
             * @returns {undefined}
             */
            function addRowContents(index, el) {
                // add links for row
                function addLinks() {
                    let itemname = PAGE.$item.attr('data-name');
                    let addSteamLink = sessionSteamId &&
                        // do not show if current owner, unless there is no item name (moved elsewhere)
                        // logged in user and steamid of row must match
                        ((prevSteamId || !itemname) && sessionSteamId == userSteamId) ||
                        // if previous row steamid is the same as logged in user
                        (sessionSteamId == prevSteamId);

                    addLink.column(getURL.compare(prevSteamId, lastSeenDate), 'Compare', 'Buyer', 'User');
                    addLink.column(getURL.compare(userSteamId, lastSeenDate), 'Compare', 'Seller', 'User');

                    // add steam link if all conditions are met
                    if (addSteamLink) {
                        addLink.inline(getURL.inventoryHistory(lastSeenDate), '', 'User');
                    }
                }

                // adds highlighting to row
                function addHighlighting() {
                    let days = dayDifference(lastSeenDate, new Date());

                    // add coloring depending on how long ago the hat was last sold
                    if (days <= 60) {
                        $row.addClass('success');
                    } else if (days <= 90) {
                        $row.addClass('warning');
                    } else if (days <= 120) {
                        $row.addClass('danger');
                    }
                }

                /** Get rows for each column by column name
                 * @param {Object} $row = jQuery object for row
                 * @returns {Object} Row columns mapped by column e.g. { 'ID': $td, 'User': $td }
                 */
                function getRowColumns($row) {
                    let $tds = $row.find('td');
                    let rowColumns = {};

                    for (let name in columns) {
                        rowColumns[name] = $tds.eq(columns[name].index);
                    }

                    return rowColumns;
                }

                function getLastSeenDate() {
                    let timestamp = getValueFromURL(rowColumns['Last seen'].find('a').attr('href'), /time=(\d+)$/);

                    return timestamp && new Date(parseInt(timestamp) * 1000);
                }

                /**
                 * Get difference in days between two dates
                 * @param {Object} date1 - First date
                 * @param {Object} date2 - Second date
                 * @returns {Number} Difference
                 */
                function dayDifference(date1, date2) {
                    return Math.round(Math.abs((date1.getTime() - date2.getTime()) / (24 * 60 * 60 * 1000)));
                }

                let addLink = (function () {
                    /**
                     * Creates a jQuery link
                     * @param {String} href - URL
                     * @param {String} contents - HTML contents of link
                     * @returns {Object} jQuery object of link
                     */
                    function getLink(href, contents) {
                        return $('').html(contents).attr({
                            'href': href,
                            'target': '_blank'
                        });
                    }

                    /**
                     * Adds a link to "User" column
                     * @param {String} href - URL
                     * @param {String} contents - HTML contents of link
                     * @param {String} appendTo - Name of column to append to e.g. "User"
                     * @returns {undefined}
                     */
                    function inline(href, contents, appendTo) {
                        let $link = getLink(href, contents);
                        let $span = $('').css({
                            'float': 'right',
                            'margin-left': '0.6em'
                        }).append($link);

                        rowColumns[appendTo].append($span);
                    }

                    /**
                     * Adds a link as a new column, after "User" column
                     * @param {String} href - URL
                     * @param {String} contents - HTML contents of link
                     * @param {String} columnName - Name of column
                     * @param {String} insertAfter - Name of column to insert after e.g. "User"
                     * @returns {undefined}
                     */
                    function column(href, contents, columnName, insertAfter) {
                        function addHeader() {
                            let $th = $('').text(columnName);

                            $th.insertAfter(columns[insertAfter].$header);
                            // keep track of column by indexing using column name
                            columns[columnName] = {
                                $header: $th
                            };
                        }

                        let $link = getLink(href, contents);
                        // the first row does not include a link
                        let $td = $('').append(index === 0 ? '—————' : $link);

                        $td.insertAfter(rowColumns[insertAfter]);

                        // this will ensure that a heading cell is added only once for each column added
                        if (!columns[columnName]) {
                            addHeader();
                        }
                    }

                    return { inline, column };
                }());
                let getURL = (function () {
                    /**
                     * Get URL of your steam history at date
                     * @param {Object} date - Date of history point
                     * @returns {String} Inventory history URL
                     */
                    function inventoryHistory(date) {
                        let itemname = PAGE.$item.attr('data-name');

                        return [
                            'http://steamcommunity.com/my/inventoryhistory/?after_time=',
                            toX(date),
                            '&prev=1',
                            // for adding a filter with history bastard - https://naknak.net/tf2/historybastard/historybastard.user.js
                            (itemname ? '#filter-' + itemname : '')
                        ].join('');
                    }

                    /**
                     * Get URL of compare link on backpack.tf
                     * @param {String} steamid - SteamID of user
                     * @param {Object} date - Date of history point
                     * @returns {String} Inventory comparison URL
                     */
                    function compare(steamid, date) {
                        date.setUTCHours(0);
                        date.setUTCMinutes(0);
                        date.setUTCSeconds(0);
                        date.setUTCMilliseconds(0);

                        let x = toX(date);

                        return [
                            'https://backpack.tf/profiles/' +
                            steamid,
                            '#!',
                            '/compare/',
                            x,
                            '/',
                            x,
                            // add "/0" at the end so that we can treat this compare link in a special manner when it loads
                            '/nearest'
                        ].join('');
                    }

                    return { inventoryHistory, compare };
                }());
                let $row = $(el);
                let rowColumns = getRowColumns($row);
                let lastSeenDate = getLastSeenDate();
                let userSteamId = rowColumns['User'].find('.user-handle a').attr('data-id');

                addHighlighting();
                addLinks();

                // set prev steamid to current now that we are done with this row
                prevSteamId = userSteamId;
            }

            let columns = getColumns(); // get columns by heading text
            let sessionSteamId = getValueFromURL(PAGE.$username.find('a').attr('href'), /\/profiles\/(\d{17})$/); // current logged in user
            let prevSteamId;

            PAGE.$history.find('tbody tr').each(addRowContents); // iterate to add links for each row
        }

        return (function() {
            addBotTFLink();
            addTableLinks();
        })();
    }

    // called on inventory pages
    function getInventory() {
        // jquery elements
        const PAGE = {
            $snapshots: $('#historicalview option')
        };
        const SNAPSHOTS = PAGE.$snapshots.map((i, el) => parseInt(el.value)).get().filter(a => a);

        /**
         * Get closet snapshot time according to timestamp
         * @param {Number} timestamp - Unix timestamp
         * @param {Boolean} [before] - Whether the closest snapshot should appear before 'timestamp', otherwise 'timestamp' should appear after
         * @param {Number} [other] - Snapshot must not be the same as this value
         * @returns {(Number|null)} Closest snapshot to date
         */
        function getClosestSnapshot(timestamp, before, other) {
            const asc = (a, b) => (b - a); // sort ascending
            const desc = (a, b) => (a - b); // sort descending

            // loop until we find the first result that is at or before the timestamp if "before" is set to true, or after if before is not set
            // when "before" is set, array is sorted in descending order, or ascending if not set
            return SNAPSHOTS.sort(before ? desc : asc).find((snapshot) => {
                let isBefore = timestamp <= snapshot;
                let isAfter = timestamp >= snapshot;
                let isOther = snapshot === other;

                return (
                    before ? isBefore : isAfter
                ) && !isOther; // snapshot must also not be the same as "other"
            }) || (before ? Math.min : Math.max)(...SNAPSHOTS);
            // default value is first or last snapshot if one did not meet conditions
            // will probably only default to this if the time is closest to the first or last snapshot or with one-snapshot inventories
        }

        // update the location so that each timestamp is at the closest time according to recorded inventory snapshots
        function changeLocation() {
            let pattern = /(\d{10})\/(\d{10})\/nearest$/;
            let timestamps = location.href.match(pattern).slice(1).map(a => parseInt(a)); // should always match
            let from = getClosestSnapshot(timestamps[0], true); // must be at or before the first date
            let to = getClosestSnapshot(timestamps[1], false, from); // must be at or before the second date, and not the same date as 'from'

            // finally update location.href using new timestamps
            location.href = location.href.replace(pattern, [from, to].join('/'));
        }

        return (function() {
            changeLocation();
        })();
    }

    ready();
})();
<commit_msg>4.0.1<commit_after>// ==UserScript==
// @name        backpack.tf Premium Recent Sales Finder
// @namespace   http://steamcommunity.com/profiles/76561198080179568/
// @author      Julia
// @description Adds coloring to history pages indicating recent sales and direct link to user's outpost page
// @include     /^https?:\/\/(.*\.)?backpack\.tf(\:\d+)?\/item\/.*/
// @include     /^https?:\/\/(.*\.)?backpack\.tf(\:\d+)?\/profiles\/\d{17}\/?$/
// @version     4.0.1
// @grant       none
// @run-at      document-end
// @updateURL   https://github.com/juliarose/backpack.tf-premium-sales-finder/raw/master/backpacktf-premium-sales-finder.meta.js
// @downloadURL https://github.com/juliarose/backpack.tf-premium-sales-finder/raw/master/backpacktf-premium-sales-finder.user.js
// ==/UserScript==

(function(){
    'use strict';

    // all of the code that runs when the page is loaded is here
    function ready() {
        [
            // item history pages
            {
                pattern: /^https?:\/\/(.*\.)?backpack\.tf(\:\d+)?\/item\/./,
                fn: getHistory
            },
            // inventory pages
            {
                pattern: /^https?:\/\/(.*\.)?backpack\.tf\/profiles\/\d{17}\#\!\/compare\/\d{10}\/\d{10}\/nearest/,
                fn: getInventory
            }
        ].find((mode) => {
            // will call function when something matches, then stop
            return mode.pattern.test(location.href) && (mode.fn() || true);
        });
    }

    /**
     * Super basic omitEmpty function
     * @param {Object} obj - Object to omit values from
     * @returns {Object} Object with null, undefined, or empty string values omitted
     */
    function omitEmpty(obj) {
        // create clone so we do not modify original object
        let result = Object.assign({}, obj);

        for (let k in result) {
            if (result[k] === null || result[k] === undefined || result[k] === '') {
                delete result[k];
            }
        }

        return result;
    }

    /**
     * Convert date to unix timestamp
     * @param {Object} date - Date object
     * @returns {Number} Unix timestamp
     */
    function toX(date) {
        return Math.round(date.getTime() / 1000);
    }

    // called on history pages
    function getHistory() {
        // jquery elements
        const PAGE = {
            $history: $('.history-sheet table.table'),
            $item: $('.item'),
            $panelExtras: $('.panel-extras'),
            $username: $('.username')
        };

        // add bot.tf listing snapshots link to page
        function addBotTFLink() {
            // only if an item exists on page
            if (PAGE.$item.length === 0) return;

            let data = PAGE.$item.data();
            let params = omitEmpty({
                def: data.defindex,
                q: data.quality,
                ef: data.effect_name,
                craft: data.craftable ? 1 : 0,
                aus: data.australium ? 1 : 0,
                ks: data.ks_tier || 0
            });
            let queryString = Object.keys(params).map(key => `key=${encodeURIComponent(params[key])}`).join('&');
            let url = 'https://bot.tf/stats/listings?' + queryString;
            let $pullRight = PAGE.$panelExtras.find('.pull-right');
            let $btnGroup = $('
');
            let $link = $(`<a class="btn btn-panel" href="${url}"><i class="fa fa-search"></i> Bot.tf</a>`);

            if ($pullRight.length === 0) {
                $pullRight = $('
');
                PAGE.$panelExtras.append($pullRight);
            }

            $btnGroup.append($link);
            $pullRight.prepend($btnGroup);
        }

        // add contents to the page
        function addTableLinks() {
            /**
             * Get columns from history table
             * @returns {Object} An object containing details for each column labeled by header text e.g. { 'ID': { index: 0, $header: $column } }
             */
            function getColumns() {
                let columns = {}; // column elements

                PAGE.$history.find('thead tr th').each((index, el) => {
                    let $column = $(el);
                    let text = $column.text().trim();

                    // assign column based on column heading text
                    columns[text] = {
                        // add index so we know the order of each column
                        index: $column.index(),
                        $header: $column
                    };
                });

                return columns;
            }

            /**
             * Get a value from a URL according to pattern
             * @param {String} url - URL
             * @param {Object} pattern - Pattern to match. The 1st match group should be the value we are trying to get
             * @returns {(String|null)} Matched value, or null if the pattern does not match
             */
            function getValueFromURL(url, pattern) {
                let match = (url || '').match(pattern);

                return match && match[1];
            }

            /**
             * Add contents for a row
             * @param {Number} index - Index of row
             * @param {Object} el - DOM element of row
             * @returns {undefined}
             */
            function addRowContents(index, el) {
                // add links for row
                function addLinks() {
                    let itemname = PAGE.$item.attr('data-name');
                    let addSteamLink = sessionSteamId &&
                        // do not show if current owner, unless there is no item name (moved elsewhere)
                        // logged in user and steamid of row must match
                        ((prevSteamId || !itemname) && sessionSteamId == userSteamId) ||
                        // if previous row steamid is the same as logged in user
                        (sessionSteamId == prevSteamId);

                    addLink.column(getURL.compare(prevSteamId, lastSeenDate), 'Compare', 'Buyer', 'User');
                    addLink.column(getURL.compare(userSteamId, lastSeenDate), 'Compare', 'Seller', 'User');

                    // add steam link if all conditions are met
                    if (addSteamLink) {
                        addLink.inline(getURL.inventoryHistory(lastSeenDate), '', 'User');
                    }
                }

                // adds highlighting to row
                function addHighlighting() {
                    let days = dayDifference(lastSeenDate, new Date());

                    // add coloring depending on how long ago the hat was last sold
                    if (days <= 60) {
                        $row.addClass('success');
                    } else if (days <= 90) {
                        $row.addClass('warning');
                    } else if (days <= 120) {
                        $row.addClass('danger');
                    }
                }

                /** Get rows for each column by column name
                 * @param {Object} $row = jQuery object for row
                 * @returns {Object} Row columns mapped by column e.g. { 'ID': $td, 'User': $td }
                 */
                function getRowColumns($row) {
                    let $tds = $row.find('td');
                    let rowColumns = {};

                    for (let name in columns) {
                        rowColumns[name] = $tds.eq(columns[name].index);
                    }

                    return rowColumns;
                }

                function getLastSeenDate() {
                    let timestamp = getValueFromURL(rowColumns['Last seen'].find('a').attr('href'), /time=(\d+)$/);

                    return timestamp && new Date(parseInt(timestamp) * 1000);
                }

                /**
                 * Get difference in days between two dates
                 * @param {Object} date1 - First date
                 * @param {Object} date2 - Second date
                 * @returns {Number} Difference
                 */
                function dayDifference(date1, date2) {
                    return Math.round(Math.abs((date1.getTime() - date2.getTime()) / (24 * 60 * 60 * 1000)));
                }

                let addLink = (function () {
                    /**
                     * Creates a jQuery link
                     * @param {String} href - URL
                     * @param {String} contents - HTML contents of link
                     * @returns {Object} jQuery object of link
                     */
                    function getLink(href, contents) {
                        return $('').html(contents).attr({
                            'href': href,
                            'target': '_blank'
                        });
                    }

                    /**
                     * Adds a link to "User" column
                     * @param {String} href - URL
                     * @param {String} contents - HTML contents of link
                     * @param {String} appendTo - Name of column to append to e.g. "User"
                     * @returns {undefined}
                     */
                    function inline(href, contents, appendTo) {
                        let $link = getLink(href, contents);
                        let $span = $('').css({
                            'float': 'right',
                            'margin-left': '0.6em'
                        }).append($link);

                        rowColumns[appendTo].append($span);
                    }

                    /**
                     * Adds a link as a new column, after "User" column
                     * @param {String} href - URL
                     * @param {String} contents - HTML contents of link
                     * @param {String} columnName - Name of column
                     * @param {String} insertAfter - Name of column to insert after e.g. "User"
                     * @returns {undefined}
                     */
                    function column(href, contents, columnName, insertAfter) {
                        function addHeader() {
                            let $th = $('').text(columnName);

                            $th.insertAfter(columns[insertAfter].$header);
                            // keep track of column by indexing using column name
                            columns[columnName] = {
                                $header: $th
                            };
                        }

                        let $link = getLink(href, contents);
                        // the first row does not include a link
                        let $td = $('').append(index === 0 ? '—————' : $link);

                        $td.insertAfter(rowColumns[insertAfter]);

                        // this will ensure that a heading cell is added only once for each column added
                        if (!columns[columnName]) {
                            addHeader();
                        }
                    }

                    return { inline, column };
                }());
                let getURL = (function () {
                    /**
                     * Get URL of your steam history at date
                     * @param {Object} date - Date of history point
                     * @returns {String} Inventory history URL
                     */
                    function inventoryHistory(date) {
                        let itemname = PAGE.$item.attr('data-name');

                        return [
                            'http://steamcommunity.com/my/inventoryhistory/?after_time=',
                            toX(date),
                            '&prev=1',
                            // for adding a filter with history bastard - https://naknak.net/tf2/historybastard/historybastard.user.js
                            (itemname ? '#filter-' + itemname : '')
                        ].join('');
                    }

                    /**
                     * Get URL of compare link on backpack.tf
                     * @param {String} steamid - SteamID of user
                     * @param {Object} date - Date of history point
                     * @returns {String} Inventory comparison URL
                     */
                    function compare(steamid, date) {
                        date.setUTCHours(0);
                        date.setUTCMinutes(0);
                        date.setUTCSeconds(0);
                        date.setUTCMilliseconds(0);

                        let x = toX(date);

                        return [
                            'https://backpack.tf/profiles/' +
                            steamid,
                            '#!',
                            '/compare/',
                            x,
                            '/',
                            x,
                            // add "/0" at the end so that we can treat this compare link in a special manner when it loads
                            '/nearest'
                        ].join('');
                    }

                    return { inventoryHistory, compare };
                }());
                let $row = $(el);
                let rowColumns = getRowColumns($row);
                let lastSeenDate = getLastSeenDate();
                let userSteamId = rowColumns['User'].find('.user-handle a').attr('data-id');

                addHighlighting();
                addLinks();

                // set prev steamid to current now that we are done with this row
                prevSteamId = userSteamId;
            }

            let columns = getColumns(); // get columns by heading text
            let sessionSteamId = getValueFromURL(PAGE.$username.find('a').attr('href'), /\/profiles\/(\d{17})$/); // current logged in user
            let prevSteamId;

            PAGE.$history.find('tbody tr').each(addRowContents); // iterate to add links for each row
        }

        return (function() {
            addBotTFLink();
            addTableLinks();
        })();
    }

    // called on inventory pages
    function getInventory() {
        // jquery elements
        const PAGE = {
            $snapshots: $('#historicalview option')
        };
        const SNAPSHOTS = PAGE.$snapshots.map((i, el) => parseInt(el.value)).get().filter(a => a);

        /**
         * Get closet snapshot time according to timestamp
         * @param {Number} timestamp - Unix timestamp
         * @param {Boolean} [before] - Whether the closest snapshot should appear before 'timestamp', otherwise 'timestamp' should appear after
         * @param {Number} [other] - Snapshot must not be the same as this value
         * @returns {(Number|null)} Closest snapshot to date
         */
        function getClosestSnapshot(timestamp, before, other) {
            const asc = (a, b) => (b - a); // sort ascending
            const desc = (a, b) => (a - b); // sort descending

            // loop until we find the first result that is at or before the timestamp if "before" is set to true, or after if before is not set
            // when "before" is set, array is sorted in descending order, or ascending if not set
            return SNAPSHOTS.sort(before ? desc : asc).find((snapshot) => {
                let isBefore = timestamp <= snapshot;
                let isAfter = timestamp >= snapshot;
                let isOther = snapshot === other;

                return (
                    before ? isBefore : isAfter
                ) && !isOther; // snapshot must also not be the same as "other"
            }) || (before ? Math.min : Math.max)(...SNAPSHOTS);
            // default value is first or last snapshot if one did not meet conditions
            // will probably only default to this if the time is closest to the first or last snapshot or with one-snapshot inventories
        }

        // update the location so that each timestamp is at the closest time according to recorded inventory snapshots
        function changeLocation() {
            let pattern = /(\d{10})\/(\d{10})\/nearest$/;
            let timestamps = location.href.match(pattern).slice(1).map(a => parseInt(a)); // should always match
            let from = getClosestSnapshot(timestamps[0], true); // must be at or before the first date
            let to = getClosestSnapshot(timestamps[1], false, from); // must be at or before the second date, and not the same date as 'from'

            // finally update location.href using new timestamps
            location.href = location.href.replace(pattern, [from, to].join('/'));
        }

        return (function() {
            changeLocation();
        })();
    }

    ready();
})();
<|endoftext|>


<commit_before>/**
 * Copyright 2013-2018 the original author or authors from the JHipster project.
 *
 * This file is part of the JHipster project, see https://www.jhipster.tech/
 * for more information.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
const _ = require('lodash');
const constants = require('../generator-constants');

/* Constants use throughout */
const CLIENT_TEST_SRC_DIR = constants.CLIENT_TEST_SRC_DIR;
const ANGULAR_DIR = constants.ANGULAR_DIR;
const REACT_DIR = constants.ANGULAR_DIR;

const CLIENT_NG2_TEMPLATES_DIR = 'angular';
const CLIENT_REACT_TEMPLATES_DIR = 'react';

/**
* The default is to use a file path string. It implies use of the template method.
* For any other config an object { file:.., method:.., template:.. } can be used
*/

const angularFiles = {
    client: [
        {
            path: ANGULAR_DIR,
            templates: [
                {
                    file: 'entities/entity-management.component.html',
                    method: 'processHtml',
                    template: true,
                    renameTo: generator => `entities/${generator.entityFolderName}/${generator.entityFileName}.component.html`
                },
                {
                    file: 'entities/entity-management-detail.component.html',
                    method: 'processHtml',
                    template: true,
                    renameTo: generator => `entities/${generator.entityFolderName}/${generator.entityFileName}-detail.component.html`
                },
                {
                    file: 'entities/entity-management-dialog.component.html',
                    method: 'processHtml',
                    template: true,
                    renameTo: generator => `entities/${generator.entityFolderName}/${generator.entityFileName}-dialog.component.html`
                },
                {
                    file: 'entities/entity-management-delete-dialog.component.html',
                    method: 'processHtml',
                    template: true,
                    renameTo: generator => `entities/${generator.entityFolderName}/${generator.entityFileName}-delete-dialog.component.html`
                },
                {
                    file: 'entities/index.ts',
                    renameTo: generator => `entities/${generator.entityFolderName}/index.ts`
                },
                {
                    file: 'entities/entity-management.module.ts',
                    renameTo: generator => `entities/${generator.entityFolderName}/${generator.entityFileName}.module.ts`
                },
                {
                    file: 'entities/entity-management.route.ts',
                    renameTo: generator => `entities/${generator.entityFolderName}/${generator.entityFileName}.route.ts`
                },
                {
                    file: 'entities/entity.model.ts',
                    // using entityModelFileName so that there is no conflict when genertaing microservice entities
                    renameTo: generator => `shared/model/${generator.entityModelFileName}.model.ts`
                },
                {
                    file: 'entities/entity-management.component.ts',
                    renameTo: generator => `entities/${generator.entityFolderName}/${generator.entityFileName}.component.ts`
                },
                {
                    file: 'entities/entity-management-dialog.component.ts',
                    renameTo: generator => `entities/${generator.entityFolderName}/${generator.entityFileName}-dialog.component.ts`
                },
                {
                    file: 'entities/entity-management-delete-dialog.component.ts',
                    renameTo: generator => `entities/${generator.entityFolderName}/${generator.entityFileName}-delete-dialog.component.ts`
                },
                {
                    file: 'entities/entity-management-detail.component.ts',
                    renameTo: generator => `entities/${generator.entityFolderName}/${generator.entityFileName}-detail.component.ts`
                },
                {
                    file: 'entities/entity.service.ts',
                    renameTo: generator => `entities/${generator.entityFolderName}/${generator.entityServiceFileName}.service.ts`
                },
                {
                    file: 'entities/entity-popup.service.ts',
                    renameTo: generator => `entities/${generator.entityFolderName}/${generator.entityServiceFileName}-popup.service.ts`
                }

            ]
        }
    ],
    test: [
        {
            path: CLIENT_TEST_SRC_DIR,
            templates: [
                {
                    file: 'spec/app/entities/entity-management-detail.component.spec.ts',
                    renameTo: generator => `spec/app/entities/${generator.entityFolderName}/${generator.entityFileName}-detail.component.spec.ts`
                },
                {
                    file: 'spec/app/entities/entity-management-dialog.component.spec.ts',
                    renameTo: generator => `spec/app/entities/${generator.entityFolderName}/${generator.entityFileName}-dialog.component.spec.ts`
                },
                {
                    file: 'spec/app/entities/entity-management-delete-dialog.component.spec.ts',
                    renameTo: generator => `spec/app/entities/${generator.entityFolderName}/${generator.entityFileName}-delete-dialog.component.spec.ts`
                },
                {
                    file: 'spec/app/entities/entity-management.component.spec.ts',
                    renameTo: generator => `spec/app/entities/${generator.entityFolderName}/${generator.entityFileName}.component.spec.ts`
                },
                {
                    file: 'spec/app/entities/entity-management.service.spec.ts',
                    renameTo: generator => `spec/app/entities/${generator.entityFolderName}/${generator.entityFileName}.service.spec.ts`
                }
            ]
        },
        {
            condition: generator => generator.protractorTests,
            path: CLIENT_TEST_SRC_DIR,
            templates: [{
                file: 'e2e/entities/entity-page-object.ts',
                renameTo: generator => `e2e/entities/${generator.entityFolderName}/${generator.entityFileName}.page-object.ts`
            }, {
                file: 'e2e/entities/entity.spec.ts',
                renameTo: generator => `e2e/entities/${generator.entityFolderName}/${generator.entityFileName}.spec.ts`
            }]
        }
    ]
};

const reactFiles = {
    client: [
        {
            path: REACT_DIR,
            templates: [
                {
                    file: 'entities/entity-delete-dialog.tsx',
                    renameTo: generator => `entities/${generator.entityFolderName}/${generator.entityFileName}-delete-dialog.tsx`
                },
                {
                    file: 'entities/entity-detail.tsx',
                    renameTo: generator => `entities/${generator.entityFolderName}/${generator.entityFileName}-detail.tsx`
                },
                {
                    file: 'entities/entity-dialog.tsx',
                    renameTo: generator => `entities/${generator.entityFolderName}/${generator.entityFileName}-dialog.tsx`
                },
                {
                    file: 'entities/entity.tsx',
                    renameTo: generator => `entities/${generator.entityFolderName}/${generator.entityFileName}.tsx`
                },
                {
                    file: 'entities/entity.reducer.ts',
                    renameTo: generator => `entities/${generator.entityFolderName}/${generator.entityFileName}.reducer.ts`
                },
                {
                    file: 'entities/entity.model.ts',
                    renameTo: generator => `shared/model/${generator.entityModelFileName}.model.ts`
                },
                {
                    file: 'entities/index.tsx',
                    renameTo: generator => `entities/${generator.entityFolderName}/index.tsx`
                }
            ]
        }
    ],
    test: [
        {
            path: CLIENT_TEST_SRC_DIR,
            templates: [
                {
                    file: 'spec/app/entities/entity-reducer.spec.ts',
                    renameTo: generator => `spec/app/entities/${generator.entityFolderName}/${generator.entityFileName}-reducer.spec.ts`
                }
            ]
        }
    ]
};

module.exports = {
    writeFiles,
    angularFiles,
    reactFiles
};

function writeFiles() {
    return {

        writeClientFiles() {
            if (this.skipClient) return;

            if (this.clientFramework === 'angularX') {
                // write client side files for angular 2.x +
                this.writeFilesToDisk(angularFiles, this, false, CLIENT_NG2_TEMPLATES_DIR);
                this.addEntityToModule(this.entityInstance, this.entityClass, this.entityAngularName, this.entityFolderName, this.entityFileName, this.enableTranslation, this.clientFramework, this.microserviceName);

            } else {
                // write client side files for react
                this.writeFilesToDisk(reactFiles, this, false, CLIENT_REACT_TEMPLATES_DIR);
                this.addEntityToModule(this.entityInstance, this.entityClass, this.entityAngularName, this.entityFolderName, this.entityFileName, this.enableTranslation, this.clientFramework);

            }

            if (this.applicationType === 'gateway' && !_.isUndefined(this.microserviceName)) {
                this.addEntityToWebpack(this.microserviceName, this.clientFramework);
            }

            this.addEntityToMenu(this.entityStateName, this.enableTranslation, this.clientFramework, this.entityTranslationKeyMenu);
        }
    };
}
<commit_msg>Fix lint<commit_after>/**
 * Copyright 2013-2018 the original author or authors from the JHipster project.
 *
 * This file is part of the JHipster project, see https://www.jhipster.tech/
 * for more information.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
const _ = require('lodash');
const constants = require('../generator-constants');

/* Constants use throughout */
const CLIENT_TEST_SRC_DIR = constants.CLIENT_TEST_SRC_DIR;
const ANGULAR_DIR = constants.ANGULAR_DIR;
const REACT_DIR = constants.ANGULAR_DIR;

const CLIENT_NG2_TEMPLATES_DIR = 'angular';
const CLIENT_REACT_TEMPLATES_DIR = 'react';

/**
* The default is to use a file path string. It implies use of the template method.
* For any other config an object { file:.., method:.., template:.. } can be used
*/

const angularFiles = {
    client: [
        {
            path: ANGULAR_DIR,
            templates: [
                {
                    file: 'entities/entity-management.component.html',
                    method: 'processHtml',
                    template: true,
                    renameTo: generator => `entities/${generator.entityFolderName}/${generator.entityFileName}.component.html`
                },
                {
                    file: 'entities/entity-management-detail.component.html',
                    method: 'processHtml',
                    template: true,
                    renameTo: generator => `entities/${generator.entityFolderName}/${generator.entityFileName}-detail.component.html`
                },
                {
                    file: 'entities/entity-management-dialog.component.html',
                    method: 'processHtml',
                    template: true,
                    renameTo: generator => `entities/${generator.entityFolderName}/${generator.entityFileName}-dialog.component.html`
                },
                {
                    file: 'entities/entity-management-delete-dialog.component.html',
                    method: 'processHtml',
                    template: true,
                    renameTo: generator => `entities/${generator.entityFolderName}/${generator.entityFileName}-delete-dialog.component.html`
                },
                {
                    file: 'entities/index.ts',
                    renameTo: generator => `entities/${generator.entityFolderName}/index.ts`
                },
                {
                    file: 'entities/entity-management.module.ts',
                    renameTo: generator => `entities/${generator.entityFolderName}/${generator.entityFileName}.module.ts`
                },
                {
                    file: 'entities/entity-management.route.ts',
                    renameTo: generator => `entities/${generator.entityFolderName}/${generator.entityFileName}.route.ts`
                },
                {
                    file: 'entities/entity.model.ts',
                    // using entityModelFileName so that there is no conflict when genertaing microservice entities
                    renameTo: generator => `shared/model/${generator.entityModelFileName}.model.ts`
                },
                {
                    file: 'entities/entity-management.component.ts',
                    renameTo: generator => `entities/${generator.entityFolderName}/${generator.entityFileName}.component.ts`
                },
                {
                    file: 'entities/entity-management-dialog.component.ts',
                    renameTo: generator => `entities/${generator.entityFolderName}/${generator.entityFileName}-dialog.component.ts`
                },
                {
                    file: 'entities/entity-management-delete-dialog.component.ts',
                    renameTo: generator => `entities/${generator.entityFolderName}/${generator.entityFileName}-delete-dialog.component.ts`
                },
                {
                    file: 'entities/entity-management-detail.component.ts',
                    renameTo: generator => `entities/${generator.entityFolderName}/${generator.entityFileName}-detail.component.ts`
                },
                {
                    file: 'entities/entity.service.ts',
                    renameTo: generator => `entities/${generator.entityFolderName}/${generator.entityServiceFileName}.service.ts`
                },
                {
                    file: 'entities/entity-popup.service.ts',
                    renameTo: generator => `entities/${generator.entityFolderName}/${generator.entityServiceFileName}-popup.service.ts`
                }

            ]
        }
    ],
    test: [
        {
            path: CLIENT_TEST_SRC_DIR,
            templates: [
                {
                    file: 'spec/app/entities/entity-management-detail.component.spec.ts',
                    renameTo: generator => `spec/app/entities/${generator.entityFolderName}/${generator.entityFileName}-detail.component.spec.ts`
                },
                {
                    file: 'spec/app/entities/entity-management-dialog.component.spec.ts',
                    renameTo: generator => `spec/app/entities/${generator.entityFolderName}/${generator.entityFileName}-dialog.component.spec.ts`
                },
                {
                    file: 'spec/app/entities/entity-management-delete-dialog.component.spec.ts',
                    renameTo: generator => `spec/app/entities/${generator.entityFolderName}/${generator.entityFileName}-delete-dialog.component.spec.ts`
                },
                {
                    file: 'spec/app/entities/entity-management.component.spec.ts',
                    renameTo: generator => `spec/app/entities/${generator.entityFolderName}/${generator.entityFileName}.component.spec.ts`
                },
                {
                    file: 'spec/app/entities/entity-management.service.spec.ts',
                    renameTo: generator => `spec/app/entities/${generator.entityFolderName}/${generator.entityFileName}.service.spec.ts`
                }
            ]
        },
        {
            condition: generator => generator.protractorTests,
            path: CLIENT_TEST_SRC_DIR,
            templates: [{
                file: 'e2e/entities/entity-page-object.ts',
                renameTo: generator => `e2e/entities/${generator.entityFolderName}/${generator.entityFileName}.page-object.ts`
            }, {
                file: 'e2e/entities/entity.spec.ts',
                renameTo: generator => `e2e/entities/${generator.entityFolderName}/${generator.entityFileName}.spec.ts`
            }]
        }
    ]
};

const reactFiles = {
    client: [
        {
            path: REACT_DIR,
            templates: [
                {
                    file: 'entities/entity-delete-dialog.tsx',
                    renameTo: generator => `entities/${generator.entityFolderName}/${generator.entityFileName}-delete-dialog.tsx`
                },
                {
                    file: 'entities/entity-detail.tsx',
                    renameTo: generator => `entities/${generator.entityFolderName}/${generator.entityFileName}-detail.tsx`
                },
                {
                    file: 'entities/entity-dialog.tsx',
                    renameTo: generator => `entities/${generator.entityFolderName}/${generator.entityFileName}-dialog.tsx`
                },
                {
                    file: 'entities/entity.tsx',
                    renameTo: generator => `entities/${generator.entityFolderName}/${generator.entityFileName}.tsx`
                },
                {
                    file: 'entities/entity.reducer.ts',
                    renameTo: generator => `entities/${generator.entityFolderName}/${generator.entityFileName}.reducer.ts`
                },
                {
                    file: 'entities/entity.model.ts',
                    renameTo: generator => `shared/model/${generator.entityModelFileName}.model.ts`
                },
                {
                    file: 'entities/index.tsx',
                    renameTo: generator => `entities/${generator.entityFolderName}/index.tsx`
                }
            ]
        }
    ],
    test: [
        {
            path: CLIENT_TEST_SRC_DIR,
            templates: [
                {
                    file: 'spec/app/entities/entity-reducer.spec.ts',
                    renameTo: generator => `spec/app/entities/${generator.entityFolderName}/${generator.entityFileName}-reducer.spec.ts`
                }
            ]
        }
    ]
};

module.exports = {
    writeFiles,
    angularFiles,
    reactFiles
};

function writeFiles() {
    return {

        writeClientFiles() {
            if (this.skipClient) return;

            if (this.clientFramework === 'angularX') {
                // write client side files for angular 2.x +
                this.writeFilesToDisk(angularFiles, this, false, CLIENT_NG2_TEMPLATES_DIR);
                this.addEntityToModule(this.entityInstance, this.entityClass, this.entityAngularName, this.entityFolderName, this.entityFileName, this.enableTranslation, this.clientFramework, this.microserviceName);
            } else {
                // write client side files for react
                this.writeFilesToDisk(reactFiles, this, false, CLIENT_REACT_TEMPLATES_DIR);
                this.addEntityToModule(this.entityInstance, this.entityClass, this.entityAngularName, this.entityFolderName, this.entityFileName, this.enableTranslation, this.clientFramework);
            }
            if (this.applicationType === 'gateway' && !_.isUndefined(this.microserviceName)) {
                this.addEntityToWebpack(this.microserviceName, this.clientFramework);
            }
            this.addEntityToMenu(this.entityStateName, this.enableTranslation, this.clientFramework, this.entityTranslationKeyMenu);
        }
    };
}
<|endoftext|>


<commit_before>'use strict'

const tap = require('tap')
const getPostlisteArkivdeler = require('../lib/journals/getPostlisteArkivdeler')

tap.test('Requires options to be specified', function (test) {
  const options = false
  const expectedErrorMessage = 'Missing required input: options object'
  getPostlisteArkivdeler(options, function (error, data) {
    tap.equal(error.message, expectedErrorMessage, expectedErrorMessage)
    test.done()
  })
})

tap.test('Requires options.host to be specified', function (test) {
  const options = {
    host: false
  }
  const expectedErrorMessage = 'Missing required input: options.host'
  getPostlisteArkivdeler(options, function (error, data) {
    tap.equal(error.message, expectedErrorMessage, expectedErrorMessage)
    test.done()
  })
})

tap.test('Requires options.fraDato to be specified', function (test) {
  const options = {
    host: true,
    fraDato: false
  }
  const expectedErrorMessage = 'Missing required input: options.fraDato'
  getPostlisteArkivdeler(options, function (error, data) {
    tap.equal(error.message, expectedErrorMessage, expectedErrorMessage)
    test.done()
  })
})

tap.test('Requires options.tilDato to be specified', function (test) {
  const options = {
    host: true,
    fraDato: true,
    tilDato: false
  }
  const expectedErrorMessage = 'Missing required input: options.tilDato'
  getPostlisteArkivdeler(options, function (error, data) {
    tap.equal(error.message, expectedErrorMessage, expectedErrorMessage)
    test.done()
  })
})
<commit_msg>Replace test.done with test.end (patch)<commit_after>'use strict'

const tap = require('tap')
const getPostlisteArkivdeler = require('../lib/journals/getPostlisteArkivdeler')

tap.test('Requires options to be specified', function (test) {
  const options = false
  const expectedErrorMessage = 'Missing required input: options object'
  getPostlisteArkivdeler(options, function (error, data) {
    tap.equal(error.message, expectedErrorMessage, expectedErrorMessage)
    test.end()
  })
})

tap.test('Requires options.host to be specified', function (test) {
  const options = {
    host: false
  }
  const expectedErrorMessage = 'Missing required input: options.host'
  getPostlisteArkivdeler(options, function (error, data) {
    tap.equal(error.message, expectedErrorMessage, expectedErrorMessage)
    test.end()
  })
})

tap.test('Requires options.fraDato to be specified', function (test) {
  const options = {
    host: true,
    fraDato: false
  }
  const expectedErrorMessage = 'Missing required input: options.fraDato'
  getPostlisteArkivdeler(options, function (error, data) {
    tap.equal(error.message, expectedErrorMessage, expectedErrorMessage)
    test.end()
  })
})

tap.test('Requires options.tilDato to be specified', function (test) {
  const options = {
    host: true,
    fraDato: true,
    tilDato: false
  }
  const expectedErrorMessage = 'Missing required input: options.tilDato'
  getPostlisteArkivdeler(options, function (error, data) {
    tap.equal(error.message, expectedErrorMessage, expectedErrorMessage)
    test.end()
  })
})
<|endoftext|>


<commit_before>"use strict";

(function (global) {
    var globalXDomainRequest = global.XDomainRequest;

    var fakeXdrSetUp = function () {
        this.fakeXdr = sinon.useFakeXDomainRequest();
    };

    var fakeXdrTearDown = function() {
        if (typeof this.fakeXhr.restore == "function") {
            this.fakeXdr.restore();
        }
    };
    buster.testCase("sinon.FakeXDomainRequest", {
        "is constructor": function () {
            assert.isFunction(sinon.FakeXDomainRequest);
            assert.same(sinon.FakeXDomainRequest.prototype.constructor, sinon.FakeXDomainRequest);
        },
        "implements readyState constants": function () {
            assert.same(sinon.FakeXDomainRequest.UNSENT, 0);
            assert.same(sinon.FakeXDomainRequest.OPENED, 1);
            assert.same(sinon.FakeXDomainRequest.LOADING, 3);
            assert.same(sinon.FakeXDomainRequest.DONE, 4);
        },
        "calls onCreate if listener is set": function () {
            var onCreate = sinon.spy();
            sinon.FakeXDomainRequest.onCreate = onCreate;

            var xhr = new sinon.FakeXDomainRequest();

            assert(onCreate.called);
        },
        "passes new object to onCreate if set": function () {
            var onCreate = sinon.spy();
            sinon.FakeXDomainRequest.onCreate = onCreate;

            var xhr = new sinon.FakeXDomainRequest();

            assert.same(onCreate.getCall(0).args[0], xhr);
        },

        "open": {
            setUp: function () {
                this.xdr = new sinon.FakeXDomainRequest();
            },
            "is method": function () {
                assert.isFunction(this.xdr.open);
            },
            "sets properties on object": function () {
                this.xdr.open("GET", "/my/url");

                assert.equals(this.xdr.method, "GET");
                assert.equals(this.xdr.url, "/my/url");
            },
            "sets responseText to null": function () {
                this.xdr.open("GET", "/my/url");

                assert.isNull(this.xdr.responseText);
            },
            "sets send flag to false": function () {
                this.xdr.open("GET", "/my/url");

                assert.isFalse(this.xdr.sendFlag);
            },
            "sets readyState to OPENED": function () {
                this.xdr.open("GET", "/my/url");

                assert.same(this.xdr.readyState, sinon.FakeXDomainRequest.OPENED);
            },
            "sets requestHeaders to blank object": function () {
                this.xdr.open("GET", "/my/url");

                assert.isObject(this.xdr.requestHeaders);
                assert.equals(this.xdr.requestHeaders, {});
            },

        },

        "send": {
            setUp: function () {
                this.xdr = new sinon.FakeXDomainRequest();
            },

            "throws if request is not open": function () {
                var xdr = new sinon.FakeXDomainRequest();

                assert.exception(function () {
                    xdr.send();
                });
            },
            "throws if send flag is true": function () {
                var xdr = this.xdr;
                xdr.open("GET", "/");
                xdr.sendFlag = true;

                assert.exception(function () {
                    xdr.send();
                });
            },
            "sets GET body to null": function () {
                this.xdr.open("GET", "/");
                this.xdr.send("Data");

                assert.isNull(this.xdr.requestBody);
            },

            "sets HEAD body to null": function () {
                this.xdr.open("HEAD", "/");
                this.xdr.send("Data");

                assert.isNull(this.xdr.requestBody);
            },
            "sets mime to text/plain for all methods": function () {
                var methods = ["GET", "HEAD", "POST"];
                for (var method in methods) {
                    this.xdr.open(method, "/");
                    this.xdr.send("Data");

                    assert.equals(this.xdr.requestHeaders["Content-Type"], "text/plain;charset=utf-8");
                }
            },
            "sets request body to string data": function () {
                this.xdr.open("POST", "/");
                this.xdr.send("Data");

                assert.equals(this.xdr.requestBody, "Data");
            },
            "sets error flag to false": function () {
                this.xdr.open("POST", "/");
                this.xdr.send("Data");

                assert.isFalse(this.xdr.errorFlag);
            },

            "sets send flag to true": function () {
                this.xdr.open("POST", "/");
                this.xdr.send("Data");

                assert.isTrue(this.xdr.sendFlag);
            },
            "calls readyStateChange": function () {
                this.xdr.open("POST", "/", false);
                this.xdr.send("Data");

                assert.equals(this.xdr.readyState, sinon.FakeXDomainRequest.OPENED);
            },
        },

        "setResponseBody": {
            setUp: function () {
                this.xdr = new sinon.FakeXDomainRequest();
                this.xdr.open("GET", "/");
                this.xdr.send();
            },
            "invokes readyStateChange handler with LOADING state": function () {
                var spy = sinon.spy();
                this.xdr.readyStateChange = spy;

                this.xdr.setResponseBody("Some text goes in here ok?");

                assert(spy.calledWith(sinon.FakeXDomainRequest.LOADING));
            },
            "invokes onreadystatechange handler for each 10 byte chunk": function () {
                var spy = sinon.spy();
                this.xdr.readyStateChange = spy;
                this.xdr.chunkSize = 10;

                this.xdr.setResponseBody("Some text goes in here ok?");

                assert.equals(spy.callCount, 4);
            },
            "invokes onreadystatechange handler for each x byte chunk": function () {
                var spy = sinon.spy();
                this.xdr.readyStateChange = spy;
                this.xdr.chunkSize = 20;

                this.xdr.setResponseBody("Some text goes in here ok?");

                assert.equals(spy.callCount, 3);
            },
            "invokes onreadystatechange handler with partial data": function () {
                var pieces = [];

                var spy = sinon.spy(function () {
                    pieces.push(this.responseText);
                });

                this.xdr.readyStateChange = spy;
                this.xdr.chunkSize = 9;

                this.xdr.setResponseBody("Some text goes in here ok?");

                assert.equals(pieces[1], "Some text");
            },
            "calls readyStateChange with DONE state": function () {
                var spy = sinon.spy();
                this.xdr.readyStateChange = spy;

                this.xdr.setResponseBody("Some text goes in here ok?");

                assert(spy.calledWith(sinon.FakeXDomainRequest.DONE));
            },
            "throws if not open": function () {
                var xdr = new sinon.FakeXDomainRequest();

                assert.exception(function () {
                    xdr.setResponseBody("");
                });
            },
            "throws if body was already sent": function () {
                var xdr = new sinon.FakeXDomainRequest();
                xdr.open("GET", "/");
                xdr.send();
                xdr.setResponseBody("");

                assert.exception(function () {
                    xdr.setResponseBody("");
                });
            },
            "throws if body is not a string": function () {
                var xdr = new sinon.FakeXDomainRequest();
                xdr.open("GET", "/");
                xdr.send();

                assert.exception(function () {
                    xdr.setResponseBody({});
                }, "InvalidBodyException");
            }
        },

        "respond": {
            setUp: function () {
                this.xdr = new sinon.FakeXDomainRequest();
                this.xdr.open("GET", "/");
                var spy = this.spy = sinon.spy();
                this.xdr.onload = spy.call(this);
                this.xdr.send();
            },
            "fire onload event": function () {
                this.onload = this.spy;
                this.xdr.respond(200, {}, "");
                assert.equals(this.spy.callCount, 1);
            },
            "fire onload event with this set to the XHR object": function (done) {
                var xdr = new sinon.FakeXDomainRequest();
                xdr.open("GET", "/");

                xdr.onload = function() {
                    assert.same(this, xdr);
                    done();
                };

                xdr.send();
                xdr.respond(200, {}, "");
            },
            "calls readystate handler with readyState DONE once": function () {
                this.xdr.respond(200, {}, "");

                assert.equals(this.spy.callCount, 1);
            },
            "defaults to status 200, no headers, and blank body": function () {
                this.xdr.respond();

                assert.equals(this.xdr.status, 200);
                assert.equals(this.xdr.responseText, "");
            },
            "sets status": function () {
                this.xdr.respond(201);

                assert.equals(this.xdr.status, 201);
            },
        },

        "abort": {
            setUp: function () {
                this.xdr = new sinon.FakeXDomainRequest();
            },
            "sets aborted flag to true": function () {
                this.xdr.aborted = true;

                this.xdr.abort();

                assert.isTrue(this.xdr.aborted);
            },
            "sets responseText to null": function () {
                this.xdr.responseText = "Partial data";

                this.xdr.abort();

                assert.isNull(this.xdr.responseText);
            },
            "sets errorFlag to true": function () {
                this.xdr.errorFlag = true;

                this.xdr.abort();

                assert.isTrue(this.xdr.errorFlag);
            },
            "fire onerror event": function () {
                var spy = sinon.spy();
                this.xdr.onerror = spy;

                this.xdr.open("GET", "/");
                this.xdr.send();
                this.xdr.abort();

                assert.equals(spy.callCount, 1);
            },
            "sets state to DONE if sent before": function () {
                this.xdr.open("GET", "/");
                this.xdr.send();

                this.xdr.readyStateChange = sinon.spy();

                this.xdr.abort();

                assert(this.xdr.readyStateChange.calledWith(sinon.FakeXDomainRequest.DONE));
            },
            "sets send flag to false if sent before": function () {
                this.xdr.open("GET", "/");
                this.xdr.send();

                this.xdr.abort();

                assert.isFalse(this.xdr.sendFlag);
            },
            "does not dispatch readystatechange event if readyState is unsent": function () {
                this.xdr.readyStateChange = sinon.stub();

                this.xdr.abort();

                assert.isFalse(this.xdr.readyStateChange.called);
            },
            "does not dispatch readystatechange event if readyState is opened but not sent": function () {
                this.xdr.open("GET", "/");
                this.xdr.readyStateChange = sinon.stub();

                this.xdr.abort();

                assert.isFalse(this.xdr.readyStateChange.called);
            }
        },

    });

})(this);
<commit_msg>Update test names s/onreadystatechange/readyStateCHange<commit_after>"use strict";

(function (global) {
    var globalXDomainRequest = global.XDomainRequest;

    var fakeXdrSetUp = function () {
        this.fakeXdr = sinon.useFakeXDomainRequest();
    };

    var fakeXdrTearDown = function() {
        if (typeof this.fakeXhr.restore == "function") {
            this.fakeXdr.restore();
        }
    };
    buster.testCase("sinon.FakeXDomainRequest", {
        "is constructor": function () {
            assert.isFunction(sinon.FakeXDomainRequest);
            assert.same(sinon.FakeXDomainRequest.prototype.constructor, sinon.FakeXDomainRequest);
        },
        "implements readyState constants": function () {
            assert.same(sinon.FakeXDomainRequest.UNSENT, 0);
            assert.same(sinon.FakeXDomainRequest.OPENED, 1);
            assert.same(sinon.FakeXDomainRequest.LOADING, 3);
            assert.same(sinon.FakeXDomainRequest.DONE, 4);
        },
        "calls onCreate if listener is set": function () {
            var onCreate = sinon.spy();
            sinon.FakeXDomainRequest.onCreate = onCreate;

            var xhr = new sinon.FakeXDomainRequest();

            assert(onCreate.called);
        },
        "passes new object to onCreate if set": function () {
            var onCreate = sinon.spy();
            sinon.FakeXDomainRequest.onCreate = onCreate;

            var xhr = new sinon.FakeXDomainRequest();

            assert.same(onCreate.getCall(0).args[0], xhr);
        },

        "open": {
            setUp: function () {
                this.xdr = new sinon.FakeXDomainRequest();
            },
            "is method": function () {
                assert.isFunction(this.xdr.open);
            },
            "sets properties on object": function () {
                this.xdr.open("GET", "/my/url");

                assert.equals(this.xdr.method, "GET");
                assert.equals(this.xdr.url, "/my/url");
            },
            "sets responseText to null": function () {
                this.xdr.open("GET", "/my/url");

                assert.isNull(this.xdr.responseText);
            },
            "sets send flag to false": function () {
                this.xdr.open("GET", "/my/url");

                assert.isFalse(this.xdr.sendFlag);
            },
            "sets readyState to OPENED": function () {
                this.xdr.open("GET", "/my/url");

                assert.same(this.xdr.readyState, sinon.FakeXDomainRequest.OPENED);
            },
            "sets requestHeaders to blank object": function () {
                this.xdr.open("GET", "/my/url");

                assert.isObject(this.xdr.requestHeaders);
                assert.equals(this.xdr.requestHeaders, {});
            },

        },

        "send": {
            setUp: function () {
                this.xdr = new sinon.FakeXDomainRequest();
            },

            "throws if request is not open": function () {
                var xdr = new sinon.FakeXDomainRequest();

                assert.exception(function () {
                    xdr.send();
                });
            },
            "throws if send flag is true": function () {
                var xdr = this.xdr;
                xdr.open("GET", "/");
                xdr.sendFlag = true;

                assert.exception(function () {
                    xdr.send();
                });
            },
            "sets GET body to null": function () {
                this.xdr.open("GET", "/");
                this.xdr.send("Data");

                assert.isNull(this.xdr.requestBody);
            },

            "sets HEAD body to null": function () {
                this.xdr.open("HEAD", "/");
                this.xdr.send("Data");

                assert.isNull(this.xdr.requestBody);
            },
            "sets mime to text/plain for all methods": function () {
                var methods = ["GET", "HEAD", "POST"];
                for (var method in methods) {
                    this.xdr.open(method, "/");
                    this.xdr.send("Data");

                    assert.equals(this.xdr.requestHeaders["Content-Type"], "text/plain;charset=utf-8");
                }
            },
            "sets request body to string data": function () {
                this.xdr.open("POST", "/");
                this.xdr.send("Data");

                assert.equals(this.xdr.requestBody, "Data");
            },
            "sets error flag to false": function () {
                this.xdr.open("POST", "/");
                this.xdr.send("Data");

                assert.isFalse(this.xdr.errorFlag);
            },

            "sets send flag to true": function () {
                this.xdr.open("POST", "/");
                this.xdr.send("Data");

                assert.isTrue(this.xdr.sendFlag);
            },
            "calls readyStateChange": function () {
                this.xdr.open("POST", "/", false);
                var spy = sinon.spy();
                this.xdr.readyStateChange = spy;

                this.xdr.send("Data");

                assert.equals(this.xdr.readyState, sinon.FakeXDomainRequest.OPENED);
                assert.isTrue(spy.called);
            },
        },

        "setResponseBody": {
            setUp: function () {
                this.xdr = new sinon.FakeXDomainRequest();
                this.xdr.open("GET", "/");
                this.xdr.send();
            },
            "invokes readyStateChange handler with LOADING state": function () {
                var spy = sinon.spy();
                this.xdr.readyStateChange = spy;

                this.xdr.setResponseBody("Some text goes in here ok?");

                assert(spy.calledWith(sinon.FakeXDomainRequest.LOADING));
            },
            "fire onprogress event": function() {
                var spy = sinon.spy();
                this.xdr.onprogress = spy;

                this.xdr.setResponseBody("Some text goes in here ok?");

                assert.isTrue(spy.called);
            },
            "invokes readyStateChange handler for each 10 byte chunk": function () {
                var spy = sinon.spy();
                this.xdr.readyStateChange = spy;
                this.xdr.chunkSize = 10;

                this.xdr.setResponseBody("Some text goes in here ok?");

                assert.equals(spy.callCount, 4);
            },
            "invokes readyStateChange handler for each x byte chunk": function () {
                var spy = sinon.spy();
                this.xdr.readyStateChange = spy;
                this.xdr.chunkSize = 20;

                this.xdr.setResponseBody("Some text goes in here ok?");

                assert.equals(spy.callCount, 3);
            },
            "invokes readyStateChange handler with partial data": function () {
                var pieces = [];

                var spy = sinon.spy(function () {
                    pieces.push(this.responseText);
                });

                this.xdr.readyStateChange = spy;
                this.xdr.chunkSize = 9;

                this.xdr.setResponseBody("Some text goes in here ok?");

                assert.equals(pieces[1], "Some text");
            },
            "calls readyStateChange with DONE state": function () {
                var spy = sinon.spy();
                this.xdr.readyStateChange = spy;

                this.xdr.setResponseBody("Some text goes in here ok?");

                assert(spy.calledWith(sinon.FakeXDomainRequest.DONE));
            },
            "throws if not open": function () {
                var xdr = new sinon.FakeXDomainRequest();

                assert.exception(function () {
                    xdr.setResponseBody("");
                });
            },
            "throws if body was already sent": function () {
                var xdr = new sinon.FakeXDomainRequest();
                xdr.open("GET", "/");
                xdr.send();
                xdr.setResponseBody("");

                assert.exception(function () {
                    xdr.setResponseBody("");
                });
            },
            "throws if body is not a string": function () {
                var xdr = new sinon.FakeXDomainRequest();
                xdr.open("GET", "/");
                xdr.send();

                assert.exception(function () {
                    xdr.setResponseBody({});
                }, "InvalidBodyException");
            }
        },

        "respond": {
            setUp: function () {
                this.xdr = new sinon.FakeXDomainRequest();
                this.xdr.open("GET", "/");
                var spy = this.spy = sinon.spy();
                this.xdr.onload = spy.call(this);
                this.xdr.send();
            },
            "fire onload event": function () {
                this.onload = this.spy;
                this.xdr.respond(200, {}, "");
                assert.equals(this.spy.callCount, 1);
            },
            "fire onload event with this set to the XHR object": function (done) {
                var xdr = new sinon.FakeXDomainRequest();
                xdr.open("GET", "/");

                xdr.onload = function() {
                    assert.same(this, xdr);
                    done();
                };

                xdr.send();
                xdr.respond(200, {}, "");
            },
            "calls readystate handler with readyState DONE once": function () {
                this.xdr.respond(200, {}, "");

                assert.equals(this.spy.callCount, 1);
            },
            "defaults to status 200, no headers, and blank body": function () {
                this.xdr.respond();

                assert.equals(this.xdr.status, 200);
                assert.equals(this.xdr.responseText, "");
            },
            "sets status": function () {
                this.xdr.respond(201);

                assert.equals(this.xdr.status, 201);
            },
        },

        "abort": {
            setUp: function () {
                this.xdr = new sinon.FakeXDomainRequest();
            },
            "sets aborted flag to true": function () {
                this.xdr.aborted = true;

                this.xdr.abort();

                assert.isTrue(this.xdr.aborted);
            },
            "sets responseText to null": function () {
                this.xdr.responseText = "Partial data";

                this.xdr.abort();

                assert.isNull(this.xdr.responseText);
            },
            "sets errorFlag to true": function () {
                this.xdr.errorFlag = true;

                this.xdr.abort();

                assert.isTrue(this.xdr.errorFlag);
            },
            "fire onerror event": function () {
                var spy = sinon.spy();
                this.xdr.onerror = spy;

                this.xdr.open("GET", "/");
                this.xdr.send();
                this.xdr.abort();

                assert.equals(spy.callCount, 1);
            },
            "sets state to DONE if sent before": function () {
                this.xdr.open("GET", "/");
                this.xdr.send();

                this.xdr.readyStateChange = sinon.spy();

                this.xdr.abort();

                assert(this.xdr.readyStateChange.calledWith(sinon.FakeXDomainRequest.DONE));
            },
            "sets send flag to false if sent before": function () {
                this.xdr.open("GET", "/");
                this.xdr.send();

                this.xdr.abort();

                assert.isFalse(this.xdr.sendFlag);
            },
            "does not dispatch readystatechange event if readyState is unsent": function () {
                this.xdr.readyStateChange = sinon.stub();

                this.xdr.abort();

                assert.isFalse(this.xdr.readyStateChange.called);
            },
            "does not dispatch readystatechange event if readyState is opened but not sent": function () {
                this.xdr.open("GET", "/");
                this.xdr.readyStateChange = sinon.stub();

                this.xdr.abort();

                assert.isFalse(this.xdr.readyStateChange.called);
            }
        },

    });

})(this);
<|endoftext|>


<commit_before>'use strict';

describe('in-viewport: viewport-enter directive', function() {

    var $compile,
        $rootScope,
        $scope,

        viewportMockController;

    beforeEach(module('in-viewport'));

    beforeEach(inject(function (_$compile_, _$rootScope_, viewportDirective) {
        $compile        = _$compile_;
        $rootScope      = _$rootScope_;
        $scope          = $rootScope.$new();

        viewportDirective[0].controller = function () {
            this.items = [];
            this.add = function (event, element, callback) {
                this.items.push({
                    event: event,
                    element: element,
                    callback: callback
                });
            };
            this.updateDelayed = function () {};
            this.setViewportFn = function () {};

            viewportMockController = this;
            spyOn(viewportMockController, 'add').and.callThrough();
        };
    }));

    it('should empty attribute', function () {
        var element = angular.element('

'),
            elementScope;

        expect(function () {
            $compile(element)($scope);
            elementScope = element.scope();
            $scope.$digest();
        }).not.toThrow();

        expect(viewportMockController.add.calls.count()).toBe(0);
    });

    it('should require a viewport parent', function () {
        var element = angular.element('
'),
            elementScope;

        expect(function () {
            $compile(element)($scope);
        }).toThrow();
    });

    it('should add a listener to the viewport controller', function () {
        var element = angular.element('

'),
            elementScope;

        expect(function () {
            $compile(element)($scope);
            elementScope = element.scope();
            $scope.$digest();
        }).not.toThrow();

        expect(viewportMockController.add.calls.count()).toBe(1);
    });

    it('should add a listener to the viewport controller', function () {
        var element = angular.element('

'),
            elementScope;

        $compile(element)($scope);
        elementScope = element.scope();
        $scope.$digest();

        viewportMockController.items[0].callback();
        $scope.$digest();

        expect(elementScope.visible).toBeTruthy();
    });

});<commit_msg>spec for leaving<commit_after>'use strict';

describe('in-viewport: viewport-enter directive', function() {

    var $compile,
        $rootScope,
        $scope,

        viewportMockController;

    beforeEach(module('in-viewport'));

    beforeEach(inject(function (_$compile_, _$rootScope_, viewportDirective) {
        $compile        = _$compile_;
        $rootScope      = _$rootScope_;
        $scope          = $rootScope.$new();

        viewportDirective[0].controller = function () {
            this.items = [];
            this.add = function (event, element, callback) {
                this.items.push({
                    event: event,
                    element: element,
                    callback: callback
                });
            };
            this.updateDelayed = function () {};
            this.setViewportFn = function () {};

            viewportMockController = this;
            spyOn(viewportMockController, 'add').and.callThrough();
        };
    }));

    it('should empty attribute', function () {
        var element = angular.element('

'),
            elementScope;

        expect(function () {
            $compile(element)($scope);
            elementScope = element.scope();
            $scope.$digest();
        }).not.toThrow();

        expect(viewportMockController.add.calls.count()).toBe(0);
    });

    it('should require a viewport parent', function () {
        var element = angular.element('
'),
            elementScope;

        expect(function () {
            $compile(element)($scope);
        }).toThrow();
    });

    it('should add a listener to the viewport controller', function () {
        var element = angular.element('

'),
            elementScope;

        expect(function () {
            $compile(element)($scope);
            elementScope = element.scope();
            $scope.$digest();
        }).not.toThrow();

        expect(viewportMockController.add.calls.count()).toBe(1);
    });

    it('should add a listener to the viewport controller', function () {
        var element = angular.element('

'),
            elementScope;

        $compile(element)($scope);
        elementScope = element.scope();
        $scope.$digest();

        viewportMockController.items[0].callback();
        $scope.$digest();

        expect(elementScope.visible).toBeTruthy();
    });

    describe('given the callback is triggered', function() {
        var element, elementScope, callback;

        describe('given the element has a leave property', function() {

            describe('given the element\'s leave callback has not been registered yet', function () {
                beforeEach(function() {
                    element = angular.element('

');
                    $compile(element)($scope);
                    elementScope = element.scope();
                    $scope.$digest();
                    viewportMockController.items[0].callback();
                });

                it('should add a listener to the viewport controller', function () {
                    expect(viewportMockController.add.calls.count()).toBe(2);
                    expect(viewportMockController.items[1].event).toBe('leave');
                });
            });

            describe('given the element\'s leave callback has been registered', function() {
                beforeEach(function() {
                    element = angular.element('

');
                    $compile(element)($scope);
                    elementScope = element.scope();
                    $scope.$digest();
                    viewportMockController.items[0].callback();
                });

                it('should not add a listener to the viewport controller', function () {
                    expect(viewportMockController.add.calls.count()).toBe(1);
                });
            });
        });
    });
});
<|endoftext|>


<commit_before>import React from 'react'
import { Segment } from 'stardust'

describe('Segments', () => {
  it('should render children', () => {
    const [segmentOne, segmentTwo] = deprecatedRender(
      <Segment.Segments>
        <Segment>Top</Segment>
        <Segment>Bottom</Segment>
      </Segment.Segments>
    ).scryClass('sd-segment')

    segmentOne
      .textContent
      .should.equal('Top')
    segmentTwo
      .textContent
      .should.equal('Bottom')
  })

  it('renders expected number of children', () => {
    deprecatedRender(
      <Segment.Segments>
        <Segment>Top</Segment>
        <Segment>Middle</Segment>
        <Segment>Bottom</Segment>
      </Segment.Segments>
    )
      .scryClass('sd-segment')
      .should.have.a.lengthOf(3)
  })
})
<commit_msg>test(Segments): add common<commit_after>import Segments from 'src/elements/Segment/SegmentSegments'
import * as common from 'test/specs/commonTests'

describe('Segments', () => {
  common.isConformant(Segments)
  common.hasUIClassName(Segments)
  common.rendersChildren(Segments)
})
<|endoftext|>