<commit_before>function change_comments() {
  insert_emoticons('.comment-body');
}

function change_readme() {
  insert_emoticons('#readme');
}

function change_wiki() {
  console.log("Changing wiki");
  insert_emoticons('#markdown-body');
}

$('.js-comment-container').on('load change', change_comments);

$('#readme').on('load change', change_readme);

$('form .timeline-comment textarea[placeholder="Leave a comment"]').on('change input', function() {
    markdown_decoder('form .timeline-comment textarea[placeholder="Leave a comment"]');
});

$('#markdown-body').on('DOMNodeInserted DOMNodeRemoved change load', change_wiki);
$(document).on('ready', function() {
  console.log("Ready");
  change_comments();
  change_readme();
  change_wiki();
});
console.log('Github');
<commit_msg>Added support for commits<commit_after>function change_comments() {
  insert_emoticons('.comment-body');
}

function change_readme() {
  insert_emoticons('#readme');
}

function change_wiki() {
  console.log("Changing wiki");
  insert_emoticons('#markdown-body');
}

function change_commits() {
    insert_emoticons('table.files a .message')
}

$('.js-comment-container').on('load change', change_comments);

$('#readme').on('load change', change_readme);

$('form .timeline-comment textarea[placeholder="Leave a comment"]').on('change input', function() {
    markdown_decoder('form .timeline-comment textarea[placeholder="Leave a comment"]');
});

$('#markdown-body').on('DOMNodeInserted DOMNodeRemoved change load', change_wiki);

$('table.files').on('DOMNodeInserted DOMNodeRemoved change load', change_commits);

$(document).on('ready', function() {
  console.log("Ready");
  change_comments();
  change_commits();
  change_readme();
  change_wiki();
});

console.log('Github');
<|endoftext|>


<commit_before>import React from 'react';
import ReactDOM from 'react-dom';
import { add, remove } from 'eventlistener';
import debounce from 'lodash/debounce';
import throttle from 'lodash.throttle';

import parentScroll from './utils/parentScroll';
import inViewport from './utils/inViewport';

export class Lazy extends React.Component {

  static propTypes = {
    children: React.PropTypes.node.isRequired,
    className: React.PropTypes.string,
    debounce: React.PropTypes.bool,
    offset: React.PropTypes.number,
    offsetBottom: React.PropTypes.number,
    offsetHorizontal: React.PropTypes.number,
    offsetLeft: React.PropTypes.number,
    offsetRight: React.PropTypes.number,
    offsetTop: React.PropTypes.number,
    offsetVertical: React.PropTypes.number,
    placeholder: React.PropTypes.node,
    style: React.PropTypes.object,
    threshold: React.PropTypes.number,
    throttle: React.PropTypes.number,
    onContentVisible: React.PropTypes.func,
  };

  static defaultProps = {
    debounce: false,
    offset: 0,
    offsetBottom: 0,
    offsetHorizontal: 0,
    offsetLeft: 0,
    offsetRight: 0,
    offsetTop: 0,
    offsetVertical: 0,
    throttle: 250,
  };

  constructor(props) {
    super(props);

    this.lazyLoadHandler = this.lazyLoadHandler.bind(this);

    if (props.throttle > 0) {
      if (props.debounce) {
        this.lazyLoadHandler = debounce(this.lazyLoadHandler, props.throttle);
      } else {
        this.lazyLoadHandler = throttle(this.lazyLoadHandler, props.throttle);
      }
    }

    this.state = { visible: false };
  }

  componentDidMount() {
    const eventNode = this.getEventNode();

    this.lazyLoadHandler();

    if (this.lazyLoadHandler.flush) {
      this.lazyLoadHandler.flush();
    }

    add(window, 'resize', this.lazyLoadHandler);
    add(eventNode, 'scroll', this.lazyLoadHandler);
  }

  componentWillReceiveProps() {
    if (!this.state.visible) {
      this.lazyLoadHandler();
    }
  }

  shouldComponentUpdate(_nextProps, nextState) {
    return nextState.visible;
  }

  componentWillUnmount() {
    if (this.lazyLoadHandler.cancel) {
      this.lazyLoadHandler.cancel();
    }

    this.detachListeners();
  }

  getEventNode() {
    return parentScroll(ReactDOM.findDOMNode(this));
  }

  getOffset() {
    const {
      offset, offsetVertical, offsetHorizontal,
      offsetTop, offsetBottom, offsetLeft, offsetRight, threshold,
    } = this.props;

    const realOffsetAll = threshold || offset;
    const realOffsetVertical = offsetVertical || realOffsetAll;
    const realOffsetHorizontal = offsetHorizontal || realOffsetAll;

    return {
      top: offsetTop || realOffsetVertical,
      bottom: offsetBottom || realOffsetVertical,
      left: offsetLeft || realOffsetHorizontal,
      right: offsetRight || realOffsetHorizontal,
    };
  }

  lazyLoadHandler() {
    const offset = this.getOffset();
    const node = ReactDOM.findDOMNode(this);
    const eventNode = this.getEventNode();

    if (inViewport(node, eventNode, offset)) {
      const { onContentVisible } = this.props;

      this.setState({ visible: true });
      this.detachListeners();

      if (onContentVisible) {
        onContentVisible();
      }
    }
  }

  detachListeners() {
    const eventNode = this.getEventNode();

    remove(window, 'resize', this.lazyLoadHandler);
    remove(eventNode, 'scroll', this.lazyLoadHandler);
  }

  render() {
    const { children, className, style } = this.props;
    const { visible } = this.state;
    const elClasses = [
      'LazyLoad',
      ...((className || '').split(/\s+/).filter(v => v)),
    ].join(' ');
    return visible ? children : (
      this.props.placeholder ||

    );
  }
}
<commit_msg>fix a library import error<commit_after>import React from 'react';
import ReactDOM from 'react-dom';
import { add, remove } from 'eventlistener';
import debounce from 'lodash/debounce';
import throttle from 'lodash/throttle';

import parentScroll from './utils/parentScroll';
import inViewport from './utils/inViewport';

export class Lazy extends React.Component {

  static propTypes = {
    children: React.PropTypes.node.isRequired,
    className: React.PropTypes.string,
    debounce: React.PropTypes.bool,
    offset: React.PropTypes.number,
    offsetBottom: React.PropTypes.number,
    offsetHorizontal: React.PropTypes.number,
    offsetLeft: React.PropTypes.number,
    offsetRight: React.PropTypes.number,
    offsetTop: React.PropTypes.number,
    offsetVertical: React.PropTypes.number,
    placeholder: React.PropTypes.node,
    style: React.PropTypes.object,
    threshold: React.PropTypes.number,
    throttle: React.PropTypes.number,
    onContentVisible: React.PropTypes.func,
  };

  static defaultProps = {
    debounce: false,
    offset: 0,
    offsetBottom: 0,
    offsetHorizontal: 0,
    offsetLeft: 0,
    offsetRight: 0,
    offsetTop: 0,
    offsetVertical: 0,
    throttle: 250,
  };

  constructor(props) {
    super(props);

    this.lazyLoadHandler = this.lazyLoadHandler.bind(this);

    if (props.throttle > 0) {
      if (props.debounce) {
        this.lazyLoadHandler = debounce(this.lazyLoadHandler, props.throttle);
      } else {
        this.lazyLoadHandler = throttle(this.lazyLoadHandler, props.throttle);
      }
    }

    this.state = { visible: false };
  }

  componentDidMount() {
    const eventNode = this.getEventNode();

    this.lazyLoadHandler();

    if (this.lazyLoadHandler.flush) {
      this.lazyLoadHandler.flush();
    }

    add(window, 'resize', this.lazyLoadHandler);
    add(eventNode, 'scroll', this.lazyLoadHandler);
  }

  componentWillReceiveProps() {
    if (!this.state.visible) {
      this.lazyLoadHandler();
    }
  }

  shouldComponentUpdate(_nextProps, nextState) {
    return nextState.visible;
  }

  componentWillUnmount() {
    if (this.lazyLoadHandler.cancel) {
      this.lazyLoadHandler.cancel();
    }

    this.detachListeners();
  }

  getEventNode() {
    return parentScroll(ReactDOM.findDOMNode(this));
  }

  getOffset() {
    const {
      offset, offsetVertical, offsetHorizontal,
      offsetTop, offsetBottom, offsetLeft, offsetRight, threshold,
    } = this.props;

    const realOffsetAll = threshold || offset;
    const realOffsetVertical = offsetVertical || realOffsetAll;
    const realOffsetHorizontal = offsetHorizontal || realOffsetAll;

    return {
      top: offsetTop || realOffsetVertical,
      bottom: offsetBottom || realOffsetVertical,
      left: offsetLeft || realOffsetHorizontal,
      right: offsetRight || realOffsetHorizontal,
    };
  }

  lazyLoadHandler() {
    const offset = this.getOffset();
    const node = ReactDOM.findDOMNode(this);
    const eventNode = this.getEventNode();

    if (inViewport(node, eventNode, offset)) {
      const { onContentVisible } = this.props;

      this.setState({ visible: true });
      this.detachListeners();

      if (onContentVisible) {
        onContentVisible();
      }
    }
  }

  detachListeners() {
    const eventNode = this.getEventNode();

    remove(window, 'resize', this.lazyLoadHandler);
    remove(eventNode, 'scroll', this.lazyLoadHandler);
  }

  render() {
    const { children, className, style } = this.props;
    const { visible } = this.state;
    const elClasses = [
      'LazyLoad',
      ...((className || '').split(/\s+/).filter(v => v)),
    ].join(' ');
    return visible ? children : (
      this.props.placeholder ||

    );
  }
}
<|endoftext|>


<commit_before>const Point = require('./Point');

/**
 * Create a line object represnting a set of two points in 2D space.
 *
 * Line objects can be constructed by passing in either 4 numbers (startX, startY, endX, endY) - or
 * two {@link Point} objects representing `start` and `end` respectively
 *
 * @class Line
 */
class Line {
    /**
     * Construct a Line using two {@link Point} objects
     * .
     * @param {Point} start An instance of {@link Point} containing X and Y co-ordinates
     * @param {Point} end   An instance of {@link Point} containing X and Y co-ordinates
     * @memberof Line
     */
    /**
     * Construct a Line using 4 {@link number}s
     *
     * @param {number} startX Starting position on the X axis
     * @param {number} startY Starting position on the Y axis
     * @param {number} endX   Ending position on the X axis
     * @param {number} endY   Ending position on the Y acis
     * @memberof Line
     */
    constructor (){
        if (arguments.length === 4) {
            this.start = {};
            this.end   = {};
            [this.start.x, this.start.y, this.end.x, this.end.y] = arguments;
        } else if(arguments.length === 2) {
            [this.start, this.end] = arguments;
        } else {
            throw Error('Please pass either two Point objects, or 4 integers to the constructor');
        }
    }

    /**
     * Get the line length
     *
     * @returns {number}
     *
     * @memberof Line
     */
    getLength() {
        return Math.sqrt(
            Math.pow(this.start.x - this.end.x, 2) + Math.pow(this.start.y - this.end.y, 2)
        );
    }
}

/** @ignore */
module.exports = Line;<commit_msg>Missing Docblock<commit_after>const Point = require('./Point');

/**
 * Create a line object represnting a set of two points in 2D space.
 *
 * Line objects can be constructed by passing in either 4 numbers (startX, startY, endX, endY) - or
 * two {@link Point} objects representing `start` and `end` respectively
 *
 * @class Line
 */
class Line {
    /**
     * Construct a Line using two {@link Point} objects
     * .
     * @param {Point} start An instance of {@link Point} containing X and Y co-ordinates
     * @param {Point} end   An instance of {@link Point} containing X and Y co-ordinates
     * @memberof Line
     */
    /**
     * Construct a Line using 4 {@link number}s
     *
     * @param {number} startX Starting position on the X axis
     * @param {number} startY Starting position on the Y axis
     * @param {number} endX   Ending position on the X axis
     * @param {number} endY   Ending position on the Y acis
     * @memberof Line
     */
    constructor (){
        if (arguments.length === 4) {
            /**
             * @type {object}
            */
            this.start = {};
            /**
             * @type {object}
            */
            this.end   = {};
            [this.start.x, this.start.y, this.end.x, this.end.y] = arguments;
        } else if(arguments.length === 2) {
            [this.start, this.end] = arguments;
        } else {
            throw Error('Please pass either two Point objects, or 4 integers to the constructor');
        }
    }

    /**
     * Get the line length
     *
     * @returns {number}
     *
     * @memberof Line
     */
    getLength() {
        return Math.sqrt(
            Math.pow(this.start.x - this.end.x, 2) + Math.pow(this.start.y - this.end.y, 2)
        );
    }
}

/** @ignore */
module.exports = Line;<|endoftext|>


<commit_before>import HttpResponse from "./HttpResponse";
import QueryString from "./QueryString";
import {UrlParser} from "./UrlParser";

/**
 * API for performing HTTP requests.

 * @example
Make a POST request

 * const request = new HttpRequest('http://example.com/api/users/');
 * request.post('Hello world')
 *     .then((response) => {
 *         // Success - response is a HttpResponse object.
 *         console.log(response.toString());
 *         if(response.isSuccess()) {
 *             console.log('Success: ', response.body);
 *         } else if (response.isRedirect) {
 *             console.log('Hmm strange, we got a redirect instead of a 2xx response.');
 *         }
 *     })
 *     .catch((error) => {
 *         // Error - response is an HttpError object.
 *         console.error(error.toString());
 *         if(error.response.isRedirect()) {
 *             // Yes - redirect is treated as an error by default.
 *             // you can change this by supplying an extra argument
 *             // to HttpResponse()
 *             console.log('We got a 3xx response!', error.response.body);
 *         } else if(error.response.isClientError()) {
 *             console.log('We got a 4xx response!', error.response.body);
 *         } else if (error.response.isServerError()) {
 *             console.log('We got a 5xx response!', error.response.body);
 *         } else if (error.response.isConnectionRefused()) {
 *             console.log('Connection refused.');
 *         }
 *     });
 *
 * @example
Make a GET request with a querystring

 * const request = new HttpRequest('http://example.com/api/users/');
 * request.urlParser.queryString.set('search', 'doe');
 * request.get()
 *     .then((response) => {
 *         console.log('Success!', response.toString());
 *     })
 *     .catch((error) => {
 *         console.error('Error:', error.toString());
 *     });
 */
export default class HttpRequest {
    /**
     * @param {string} url The URL to request.
     *      If this is supplied, it is passed to
     *      {@link HttpRequest#setUrl}
     */
    constructor(url) {
        this._treatRedirectResponseAsError = true;
        this.request = new XMLHttpRequest();
        this._urlParser = null;
        if(typeof url !== 'undefined') {
            this.setUrl(url);
        }
    }

    /**
     * Get the parsed URL of the request.
     *
     * @returns {UrlParser} The UrlParser for the parsed URL.
     */
    get urlParser() {
        return this._urlParser;
    }

    /**
     * Set the URL of the request.
     *
     * @param {String} url The URL.
     */
    setUrl(url) {
        this._urlParser = new UrlParser(url);
    }

    /**
     * Set how we treat 3xx responses.
     *
     * By default they are treated as errors, but you can change
     * this behavior by calling this function.
     *
     * @param {bool} treatRedirectResponseAsError Treat 3xx responses as
     *      errors?
     *
     * @example
Do not treat 3xx responses as error

     * const request = HttpRequest('http://example.com/api/');
     * request.setTreatRedirectResponseAsError(false);
     */
    setTreatRedirectResponseAsError(treatRedirectResponseAsError) {
        this._treatRedirectResponseAsError = treatRedirectResponseAsError;
    }

    /**
     * Send the request.
     *
     * @param method The HTTP method. I.e.: "get", "post", ...
     * @param data Request body data. This is sent through
     *      {@link HttpRequest#makeRequestBody} before it
     *      is sent.*
     * @return A Promise.
     *
     *      The resolve function argument is an
     *      an object of whatever {@link HttpRequest#makeResponse}
     *      returns.
     *
     *      The reject function argument is a
     *      {@link HttpResponseError} object created using
     *      {@link HttpResponse#toError}.
     */
    send(method, data) {
        method = method.toUpperCase();
        if(this._urlParser === null) {
            throw new TypeError('Can not call send() without an url.');
        }
        return new Promise((resolve, reject) => {
            this.request.open(method, this.urlParser.buildUrl(), true);
            this.setDefaultRequestHeaders(method);
            this.request.onload  = () => this._onComplete(resolve, reject);
            this.request.onerror = () => this._onComplete(resolve, reject);
            this.request.send(this.makeRequestBody(data));
        });
    }

    /**
     * Shortcut for ``send("get", data)``.
     *
     * @see {@link HttpRequest#send}
     */
    get(data) {
        return this.send('get', data);
    }

    /**
     * Shortcut for ``send("head", data)``.
     *
     * @see {@link HttpRequest#send}
     */
    head(data) {
        return this.send('head', data);
    }

    /**
     * Shortcut for ``send("post", data)``.
     *
     * @see {@link HttpRequest#send}
     */
    post(data) {
        return this.send('post', data);
    }

    /**
     * Shortcut for ``send("put", data)``.
     *
     * @see {@link HttpRequest#send}
     */
    put(data) {
        return this.send('put', data);
    }

    /**
     * Shortcut for ``send("patch", data)``.
     *
     * @see {@link HttpRequest#send}
     */
    patch(data) {
        return this.send('patch', data);
    }

    /**
     * Shortcut for ``send("delete", data)``.
     *
     * Named httpdelete to avoid crash with builtin keyword ``delete``.
     *
     * @see {@link HttpRequest#send}
     */
    httpdelete(data) {
        return this.send('delete', data);
    }

    /**
     * Make request body from the provided data.
     *
     * By default this just returns the provided data,
     * but subclasses can override this to perform automatic
     * conversion.
     *
     * Must return a string.
     */
    makeRequestBody(data) {
        return data;
    }

    /**
     * Creates a {@link HttpResponse}.
     * @returns {HttpResponse}
     */
    makeResponse() {
        return new HttpResponse(this.request);
    }

    /**
     * Set a request header.
     *
     * @param header The header name. E.g.: ``"Content-type"``.
     * @param value The header value.
     */
    setRequestHeader(header, value) {
        this.request.setRequestHeader(header, value);
    }

    /**
     * Set default request headers.
     *
     * Does nothing by default, but subclasses can override this.
     *
     * @param method The HTTP request method (GET, POST, PUT, ...).
     *      Will always be uppercase.
     */
    setDefaultRequestHeaders(method) {}

    _onComplete(resolve, reject) {
        let response = this.makeResponse();
        let isSuccess = false;
        if(this._treatRedirectResponseAsError) {
            isSuccess = response.isSuccess();
        } else {
            isSuccess = response.isSuccess() || response.isRedirect();
        }
        if(isSuccess) {
            resolve(response);
        } else {
            reject(response.toError());
        }
    }
}
<commit_msg>jsbase...HttpRequest: Doc fixes.<commit_after>import HttpResponse from "./HttpResponse";
import {UrlParser} from "./UrlParser";

/**
 * API for performing HTTP requests.
 *
 * @example
Make a POST request

 * const request = new HttpRequest('http://example.com/api/users/');
 * request.post('Hello world')
 *     .then((response) => {
 *         // Success - response is a HttpResponse object.
 *         console.log(response.toString());
 *         if(response.isSuccess()) {
 *             console.log('Success: ', response.body);
 *         } else if (response.isRedirect) {
 *             console.log('Hmm strange, we got a redirect instead of a 2xx response.');
 *         }
 *     })
 *     .catch((error) => {
 *         // Error - response is an HttpResponse object.
 *         console.error(error.toString());
 *         if(error.response.isRedirect()) {
 *             // Yes - redirect is treated as an error by default.
 *             // you can change this by supplying an extra argument
 *             // to HttpResponse()
 *             console.log('We got a 3xx response!', error.response.body);
 *         } else if(error.response.isClientError()) {
 *             console.log('We got a 4xx response!', error.response.body);
 *         } else if (error.response.isServerError()) {
 *             console.log('We got a 5xx response!', error.response.body);
 *         } else if (error.response.isConnectionRefused()) {
 *             console.log('Connection refused.');
 *         }
 *         throw error.toError();  // You can throw the error response as an exception
 *     });
 *
 * @example
Make a GET request with a querystring

 * const request = new HttpRequest('http://example.com/api/users/');
 * request.urlParser.queryString.set('search', 'doe');
 * request.get()
 *     .then((response) => {
 *         console.log('Success!', response.toString());
 *     })
 *     .catch((error) => {
 *         console.error('Error:', error.toString());
 *     });
 */
export default class HttpRequest {
    /**
     * @param {string} url The URL to request.
     *      If this is supplied, it is passed to
     *      {@link HttpRequest#setUrl}
     */
    constructor(url) {
        this._treatRedirectResponseAsError = true;
        this.request = new XMLHttpRequest();
        this._urlParser = null;
        if(typeof url !== 'undefined') {
            this.setUrl(url);
        }
    }

    /**
     * Get the parsed URL of the request.
     *
     * @returns {UrlParser} The UrlParser for the parsed URL.
     */
    get urlParser() {
        return this._urlParser;
    }

    /**
     * Set the URL of the request.
     *
     * @param {String} url The URL.
     */
    setUrl(url) {
        this._urlParser = new UrlParser(url);
    }

    /**
     * Set how we treat 3xx responses.
     *
     * By default they are treated as errors, but you can change
     * this behavior by calling this function.
     *
     * @param {bool} treatRedirectResponseAsError Treat 3xx responses as
     *      errors?
     *
     * @example
Do not treat 3xx responses as error

     * const request = HttpRequest('http://example.com/api/');
     * request.setTreatRedirectResponseAsError(false);
     */
    setTreatRedirectResponseAsError(treatRedirectResponseAsError) {
        this._treatRedirectResponseAsError = treatRedirectResponseAsError;
    }

    /**
     * Send the request.
     *
     * @param method The HTTP method. I.e.: "get", "post", ...
     * @param data Request body data. This is sent through
     *      {@link HttpRequest#makeRequestBody} before it
     *      is sent.*
     * @return A Promise.
     *
     *      The resolve function argument is an
     *      an object of whatever {@link HttpRequest#makeResponse}
     *      returns.
     *
     *      The reject function argument is a
     *      {@link HttpResponseError} object created using
     *      {@link HttpResponse#toError}.
     */
    send(method, data) {
        method = method.toUpperCase();
        if(this._urlParser === null) {
            throw new TypeError('Can not call send() without an url.');
        }
        return new Promise((resolve, reject) => {
            this.request.open(method, this.urlParser.buildUrl(), true);
            this.setDefaultRequestHeaders(method);
            this.request.onload  = () => this._onComplete(resolve, reject);
            this.request.onerror = () => this._onComplete(resolve, reject);
            this.request.send(this.makeRequestBody(data));
        });
    }

    /**
     * Shortcut for ``send("get", data)``.
     *
     * @see {@link HttpRequest#send}
     */
    get(data) {
        return this.send('get', data);
    }

    /**
     * Shortcut for ``send("head", data)``.
     *
     * @see {@link HttpRequest#send}
     */
    head(data) {
        return this.send('head', data);
    }

    /**
     * Shortcut for ``send("post", data)``.
     *
     * @see {@link HttpRequest#send}
     */
    post(data) {
        return this.send('post', data);
    }

    /**
     * Shortcut for ``send("put", data)``.
     *
     * @see {@link HttpRequest#send}
     */
    put(data) {
        return this.send('put', data);
    }

    /**
     * Shortcut for ``send("patch", data)``.
     *
     * @see {@link HttpRequest#send}
     */
    patch(data) {
        return this.send('patch', data);
    }

    /**
     * Shortcut for ``send("delete", data)``.
     *
     * Named httpdelete to avoid crash with builtin keyword ``delete``.
     *
     * @see {@link HttpRequest#send}
     */
    httpdelete(data) {
        return this.send('delete', data);
    }

    /**
     * Make request body from the provided data.
     *
     * By default this just returns the provided data,
     * but subclasses can override this to perform automatic
     * conversion.
     *
     * Must return a string.
     */
    makeRequestBody(data) {
        return data;
    }

    /**
     * Creates a {@link HttpResponse}.
     * @returns {HttpResponse}
     */
    makeResponse() {
        return new HttpResponse(this.request);
    }

    /**
     * Set a request header.
     *
     * @param header The header name. E.g.: ``"Content-type"``.
     * @param value The header value.
     */
    setRequestHeader(header, value) {
        this.request.setRequestHeader(header, value);
    }

    /**
     * Set default request headers.
     *
     * Does nothing by default, but subclasses can override this.
     *
     * @param method The HTTP request method (GET, POST, PUT, ...).
     *      Will always be uppercase.
     */
    setDefaultRequestHeaders(method) {}

    _onComplete(resolve, reject) {
        let response = this.makeResponse();
        let isSuccess = false;
        if(this._treatRedirectResponseAsError) {
            isSuccess = response.isSuccess();
        } else {
            isSuccess = response.isSuccess() || response.isRedirect();
        }
        if(isSuccess) {
            resolve(response);
        } else {
            reject(response.toError());
        }
    }
}
<|endoftext|>


<commit_before>import React from 'react';
import ReactDOM from 'react-dom';
import { AppContainer } from 'react-hot-loader';
import { Provider } from 'react-redux';
import App from './containers/App';
import configureStore from './stores';

const store = configureStore();

ReactDOM.render(
  <Provider store={store}>
    <AppContainer>
      <App />
    </AppContainer>
  </Provider>,
  document.getElementById('app')
);

if (module.hot) {
  module.hot.accept('./components/App', () => {
    const NextApp = require('./containers/App').default; // eslint-disable-line global-require

    ReactDOM.render(
      <Provider store={store}>
        <AppContainer>
          <NextApp />
        </AppContainer>
      </Provider>,
      document.getElementById('app')
    );
  });
}
<commit_msg>Fixed path for hot reloading the container.<commit_after>import React from 'react';
import ReactDOM from 'react-dom';
import { AppContainer } from 'react-hot-loader';
import { Provider } from 'react-redux';
import App from './containers/App';
import configureStore from './stores';

const store = configureStore();

ReactDOM.render(
  <AppContainer>
    <Provider store={store}>
      <App />
    </Provider>
  </AppContainer>,
  document.getElementById('app')
);

if (module.hot) {
  module.hot.accept('./containers/App', () => {
    const NextApp = require('./containers/App').default; // eslint-disable-line global-require

    ReactDOM.render(
      <AppContainer>
        <Provider store={store}>
          <NextApp />
        </Provider>
      </AppContainer>,
      document.getElementById('app')
    );
  });
}
<|endoftext|>


<commit_before>/*
LET'S VIEW THESE IN THE TEXT
p.148 	Decision making
p.149 	Evaluating conditionals & conditional statements
p.150 	Comparison operators: evaluating conditions
p.152 	Structuring comparison operators
p.156 	Logical operators
*/

// p.160 	‘If’ statements
// p.162 	‘If...else’ statements

// IF statements can stand alone with no ELSE
if (3 > 5) {
  console.log('WTF');
}

// IF statements can have a single else
if ('something is true') {
  // do this;
  // do that;
  // keep doing things;
} else {
  // do some other stuff;
  // and continue doing other stuff;
}

// Then there is IF and ELSE IF and ELSE...
// ... where there can be unlimited ELSE IFs

if ('something is true') {
  // do this;
  // do that;
  // keep doing things;
} else if ('this other thing is true') {
  // do some other stuff;
  // and continue doing other stuff;
} else {
  // do this thing to catch leftovers;
}

// Watch out for the most common error in IF statements...
// ... the false positive, often because of...
// ... using the assignment operator =, instead of ===

// p.164 	‘Switch’ statements
// This is a minefield of opinions

// LET'S VIEW THESE IN THE TEXT
// p.167 	Truthy & falsy values
// p.168 	Checking equality & existence
// p.169 	Short circuit values

// p.170 	Loops & loop counters
// p.172 	Looping
// p.174 	Key loop concepts (‘break’, ‘continue’)
// p.175 	Using ‘for’ loops

var samsPets = ['Buddy', 'Alistair', 'Trillian', 'Demi', 'Parker'];
//
// for (var i = 0; i <  samsPets.length; i++) {
//   console.log(samsPets[i]);
// }

// p.176 	Using ‘while’ loops
// var nadia = 0;
// while (nadia !== 26) {
//   var nadia = parseInt(prompt('How old is Nadia?'));
// }
// console.log('Nadia is awesome');

// var counter = 0;
// while(counter < samsPets.length) {
//   console.log(samsPets[counter]);
//   counter += 1;
// }

// p.177 	Using ‘do...while’ loops */
<commit_msg>fix delete<commit_after><|endoftext|>


<commit_before>var saslc = require('./lib/binding_sasl');
var sys = require('sys');

process.mixin( exports, saslc );
exports.createServerSession = function(realm, callback) {
    var serv = new saslc.ServerSession( realm, callback );
    serv.mechanisms = serv._mechanisms().split(' ');
    // POP empty element
    serv.mechanisms.pop();
    return serv;
}
<commit_msg>Replaced sys.inherits with Object.create<commit_after>var saslc = require('./lib/binding_sasl');
var sys = require('sys');

exports.prototype = Object.create( saslc );
exports.createServerSession = function(realm, callback) {
    var serv = new saslc.ServerSession( realm, callback );
    serv.mechanisms = serv._mechanisms().split(' ');
    // POP empty element
    serv.mechanisms.pop();
    return serv;
}
<|endoftext|>


<commit_before>var localStorage=true;
var remoteStorage=false;
var IndexedDbSupport=true;

function setBasicConfig(localStorageState,remoteStorageState,noteDefaultId){
	var localStorage=localStorageState;
	var remoteStorage=remoteStorageState;
	var noteId=noteDefaultId;
}

function checkSupport(){
	if("indexedDB" in window) {
		console.log("IndexedDbSupport is Present in the Browser")
	}
	else
	{
		console.log("IndexedDbSupport is Absent in the Browser");
		alert("IndexedDbSupport is Absent in the Browser");
		IndexedDbSupport=false;
	}
}

var notes4All = {};
window.indexedDB = window.indexedDB || window.webkitIndexedDB ||
window.mozIndexedDB;

if ('webkitIndexedDB' in window) {
	window.IDBTransaction = window.webkitIDBTransaction;
	window.IDBKeyRange = window.webkitIDBKeyRange;
}

notes4All.indexedDB = {};
notes4All.indexedDB.db = null;

notes4All.indexedDB.onerror = function(e) {
	console.log(e);
};

notes4All.indexedDB.open = function() {
	var version = 1;
	var request = indexedDB.open("todos", version);

      // We can only create Object stores in a versionchange transaction.
      request.onupgradeneeded = function(e) {
      	var db = e.target.result;

        // A versionchange transaction is started automatically.
        e.target.transaction.onerror = notes4All.indexedDB.onerror;

        if(db.objectStoreNames.contains("todo")) {
        	db.deleteObjectStore("todo");
        }

        var store = db.createObjectStore("todo",
        	{keyPath: "timeStamp"});
    };

    request.onsuccess = function(e) {
    	notes4All.indexedDB.db = e.target.result;
    	notes4All.indexedDB.getAllTodoItems();
    };

    request.onerror = notes4All.indexedDB.onerror;
};

notes4All.indexedDB.addTodo = function(todoText) {
	var db = notes4All.indexedDB.db;
	var trans = db.transaction(["todo"], "readwrite");
	var store = trans.objectStore("todo");

	var data = {
		"text": todoText,
		"timeStamp": new Date().getTime()
	};

	var request = store.put(data);

	trans.oncomplete = function(e) {
		notes4All.indexedDB.getAllTodoItems();
	};

	request.onerror = function(e) {
		console.log("Error Adding: ", e);
	};
};

notes4All.indexedDB.deleteTodo = function(id) {
	var db = notes4All.indexedDB.db;
	var trans = db.transaction(["todo"], "readwrite");
	var store = trans.objectStore("todo");

	var request = store.delete(id);

	trans.oncomplete = function(e) {
		notes4All.indexedDB.getAllTodoItems();
	};

	request.onerror = function(e) {
		console.log("Error Adding: ", e);
	};
};

notes4All.indexedDB.getAllTodoItems = function() {
	var todos = document.getElementById("todoItems");
	todos.innerHTML = "";

	var db = notes4All.indexedDB.db;
	var trans = db.transaction(["todo"], "readwrite");
	var store = trans.objectStore("todo");

      // Get everything in the store;
      var keyRange = IDBKeyRange.lowerBound(0);
      var cursorRequest = store.openCursor(keyRange);

      cursorRequest.onsuccess = function(e) {
      	var result = e.target.result;
      	if(!!result == false)
      		return;

      	renderTodo(result.value);
      	result.continue();
      };

      cursorRequest.onerror = notes4All.indexedDB.onerror;
  };

  function renderTodo(row) {
  	var todos = document.getElementById("todoItems");
  	var li = document.createElement("li");
  	var a = document.createElement("a");
  	var t = document.createTextNode(row.text);

  	a.addEventListener("click", function() {
  		notes4All.indexedDB.deleteTodo(row.timeStamp);
  	}, false);

  	a.href = "#";
  	a.textContent = " [Delete]";
  	li.appendChild(t);
  	li.appendChild(a);
  	todos.appendChild(li);
  }

  function addTodo() {
  	var todo = document.getElementById("todo");
  	notes4All.indexedDB.addTodo(todo.value);
  	todo.value = "";
  }

  function init() {
  	notes4All.indexedDB.open();
  }
  setBasicConfig()
  checkSupport()
  if(IndexedDbSupport)
  	window.addEventListener("DOMContentLoaded", init, false);
<commit_msg> Documented and Renamed to js/storage.js<commit_after><|endoftext|>


<commit_before>/**
 * WordPress dependencies
 */
import {
	activatePlugin,
	deactivatePlugin,
	visitAdminPage,
	createURL,
} from '@wordpress/e2e-test-utils';

/**
 * Internal dependencies
 */
import {
	activateAmpAndSetMode,
	allowedAmpModes,
	deactivateUtilityPlugins,
	resetSiteKit,
	useRequestInterception,
	setSearchConsoleProperty,
	setupAnalytics,
	setAMPMode,
} from '../../../utils';

async function proceedToTagManagerSetup() {
	await visitAdminPage( 'admin.php', 'page=googlesitekit-settings' );
	await page.waitForSelector( '.mdc-tab-bar' );
	await expect( page ).toClick( '.mdc-tab', { text: /connect more services/i } );
	await page.waitForSelector( '.googlesitekit-settings-connect-module--tagmanager' );

	await Promise.all( [
		page.waitForSelector( '.googlesitekit-setup-module__action .mdc-button' ),
		expect( page ).toClick( '.googlesitekit-cta-link', { text: /set up tag manager/i } ),
	] );
}

describe( 'Tag Manager module setup', () => {
	beforeAll( async () => {
		await page.setRequestInterception( true );
		useRequestInterception( ( request ) => {
			if ( request.url().match( 'google-site-kit/v1/data/' ) ) {
				request.respond( {
					status: 200,
				} );
			} else {
				request.continue();
			}
		} );
	} );

	beforeEach( async () => {
		await activatePlugin( 'e2e-tests-auth-plugin' );
		await activatePlugin( 'e2e-tests-site-verification-plugin' );
		await activatePlugin( 'e2e-tests-oauth-callback-plugin' );
		await setSearchConsoleProperty();
		await setupAnalytics();
	} );

	afterEach( async () => {
		await deactivateUtilityPlugins();
		await resetSiteKit();
	} );

	it( 'displays account creation form when user has no Tag Manager account', async () => {
		await activatePlugin( 'e2e-tests-module-setup-tagmanager-api-mock-no-account' );
		await proceedToTagManagerSetup();

		// Intercept the call to window.open and call our API to simulate a created account.
		await page.evaluate( () => {
			window.open = () => {
				window._e2eApiFetch( {
					path: 'google-site-kit/v1/e2e/setup/tagmanager/account-created',
					method: 'post',
				} );
			};
		} );

		// Clicking Create Account button will switch API mock plugins on the server to the one that has accounts.
		await Promise.all( [
			page.waitForResponse( ( res ) => res.url().match( 'google-site-kit/v1/e2e/setup/tagmanager/account-created' ) ),
			expect( page ).toClick( '.mdc-button', { text: /Create an account/i } ),
		] );

		await Promise.all( [
			page.waitForResponse( ( req ) => req.url().match( 'tagmanager/data/accounts' ) ),
			expect( page ).toClick( '.googlesitekit-cta-link', { text: /Re-fetch My Account/i } ),
		] );
		await page.waitForSelector( '.googlesitekit-setup-module__inputs' );

		// Ensure account and container selections are cleared.
		await expect( page ).toMatchElement( '.googlesitekit-tagmanager__select-account .mdc-select__selected-text', { text: '' } );
		await expect( page ).toMatchElement( '.googlesitekit-tagmanager__select-container .mdc-select__selected-text', { text: '' } );

		// Choose an account.
		await expect( page ).toClick( '.googlesitekit-tagmanager__select-account' );
		await expect( page ).toClick( '.mdc-menu-surface--open .mdc-list-item', { text: /test account a/i } );

		// Ensure "Set up a new container" option is present in container select.
		await expect( page ).toClick( '.googlesitekit-tagmanager__select-container' );
		await expect( page ).toMatchElement( '.mdc-menu-surface--open .mdc-list-item', { text: /set up a new container/i } );
		await expect( page ).toClick( '.mdc-menu-surface--open .mdc-list-item', { text: /test container x/i } );

		await page.waitFor( 1000 );
		await expect( page ).toClick( 'button', { text: /confirm \& continue/i } );

		await page.waitForSelector( '.googlesitekit-publisher-win--win-success' );
		await expect( page ).toMatchElement( '.googlesitekit-publisher-win__title', { text: /Congrats on completing the setup for Tag Manager!/i } );

		// Ensure expected tag is placed.
		await Promise.all( [
			page.goto( createURL( '/' ) ),
			page.waitForNavigation(),
		] );
		await expect( page ).toMatchElement( 'script[src^="https://www.googletagmanager.com/gtm.js?id=GTM-ABCXYZ"]' );
	} );

	it( 'displays available accounts and containers for the chosen account', async () => {
		await activatePlugin( 'e2e-tests-module-setup-tagmanager-api-mock' );
		await proceedToTagManagerSetup();

		// Ensure only web container select is shown.
		await expect( page ).toMatchElement( '.googlesitekit-tagmanager__select-container--web' );
		await expect( page ).not.toMatchElement( '.googlesitekit-tagmanager__select-container--amp' );

		// Ensure account and container are selected by default.
		await expect( page ).toMatchElement( '.googlesitekit-tagmanager__select-account .mdc-select__selected-text', { text: /test account a/i } );
		await expect( page ).toMatchElement( '.googlesitekit-tagmanager__select-container .mdc-select__selected-text', { text: /test container x/i } );

		// Ensure choosing a different account loads the proper values.
		await expect( page ).toClick( '.googlesitekit-tagmanager__select-account' );
		await Promise.all( [
			page.waitForResponse( ( res ) => res.url().match( 'modules/tagmanager/data' ) ),
			expect( page ).toClick( '.mdc-menu-surface--open .mdc-list-item', { text: /test account b/i } ),
		] );

		// Ensure account is selected.
		await expect( page ).toMatchElement( '.googlesitekit-tagmanager__select-account .mdc-select__selected-text', { text: /test account b/i } );

		// Select a container.
		await expect( page ).toClick( '.googlesitekit-tagmanager__select-container' );
		// Ensure no AMP containers are shown as options.
		// expect(...).not.toMatchElement with textContent matching does not work as expected.
		await expect(
			await page.$$eval( '.mdc-menu-surface--open .mdc-list-item', ( nodes ) => !! nodes.find( ( e ) => e.textContent.match( /test amp container/i ) ) )
		).toStrictEqual( false );
		await expect( page ).toClick( '.mdc-menu-surface--open .mdc-list-item', { text: /test container y/i } );

		await page.waitFor( 1000 );
		await expect( page ).toClick( 'button', { text: /confirm \& continue/i } );

		await page.waitForSelector( '.googlesitekit-publisher-win--win-success' );
		await expect( page ).toMatchElement( '.googlesitekit-publisher-win__title', { text: /Congrats on completing the setup for Tag Manager!/i } );

		// Ensure expected tag is placed.
		await Promise.all( [
			page.goto( createURL( '/' ) ),
			page.waitForNavigation(),
		] );
		await expect( page ).toMatchElement( 'script[src^="https://www.googletagmanager.com/gtm.js?id=GTM-BCDWXY"]' );
	} );

	it( 'displays instructions for account creation when "Set up a new account" option is selected', async () => {
		await activatePlugin( 'e2e-tests-module-setup-tagmanager-api-mock' );
		await proceedToTagManagerSetup();

		// Ensure "setup a new account" is an available choice.
		await expect( page ).toClick( '.googlesitekit-tagmanager__select-account' );
		await expect( page ).toMatchElement( '.mdc-menu-surface--open .mdc-list-item', { text: /set up a new account/i } );

		// Choose set up a new account.
		await expect( page ).toClick( '.mdc-menu-surface--open .mdc-list-item', { text: /set up a new account/i } );

		// Ensure instructions are present.
		await expect( page ).toMatchElement( '.googlesitekit-setup-module--tag-manager p', { text: /to create a new account/i } );

		// Ensure buttons are present.
		await expect( page ).toMatchElement( '.googlesitekit-setup-module--tag-manager .mdc-button', { text: /create an account/i } );
		await expect( page ).toMatchElement( '.googlesitekit-setup-module--tag-manager .googlesitekit-cta-link', { text: /re-fetch my account/i } );
	} );

	describe.each(
		Object.keys( allowedAmpModes )
	)( 'AMP mode %s', ( mode ) => {
		beforeEach( async () => {
			await activatePlugin( 'amp' );
			await activatePlugin( 'e2e-tests-module-setup-tagmanager-api-mock' );
			await proceedToTagManagerSetup();
		} );
		afterEach( async () => {
			await deactivatePlugin( 'amp' );
		} );
		it( 'renders the correct drop downs in the setup screen', async () => {
			await setAMPMode( mode );

			// Ensure that the correct dropdowns are displayed.
			if ( 'standard' !== mode ) {
				await expect( page ).toMatchElement( '.googlesitekit-tagmanager__select-container--web' );
			}
			await expect( page ).toMatchElement( '.googlesitekit-tagmanager__select-container--amp' );
		} );
	} );
	describe( 'Homepage AMP', () => {
		beforeEach( async () => {
			await setupAnalytics();
			await activateAmpAndSetMode( 'standard' );
		} );
		afterEach( async () => {
			await deactivatePlugin( 'amp' );
		} );
		it( 'validates for logged-in users', async () => {
			await expect( '/' ).toHaveValidAMP( { loggedIn: true } );
		} );
		it( 'validates for non-logged-in users', async () => {
			await expect( '/' ).toHaveValidAMP();
		} );
	} );
} );
<commit_msg>Set the AMP mode before going to the Tag Manger setup page.<commit_after>/**
 * WordPress dependencies
 */
import {
	activatePlugin,
	deactivatePlugin,
	visitAdminPage,
	createURL,
} from '@wordpress/e2e-test-utils';

/**
 * Internal dependencies
 */
import {
	activateAmpAndSetMode,
	allowedAmpModes,
	deactivateUtilityPlugins,
	resetSiteKit,
	useRequestInterception,
	setSearchConsoleProperty,
	setupAnalytics,
	setAMPMode,
} from '../../../utils';

async function proceedToTagManagerSetup() {
	await visitAdminPage( 'admin.php', 'page=googlesitekit-settings' );
	await page.waitForSelector( '.mdc-tab-bar' );
	await expect( page ).toClick( '.mdc-tab', { text: /connect more services/i } );
	await page.waitForSelector( '.googlesitekit-settings-connect-module--tagmanager' );

	await Promise.all( [
		page.waitForSelector( '.googlesitekit-setup-module__action .mdc-button' ),
		expect( page ).toClick( '.googlesitekit-cta-link', { text: /set up tag manager/i } ),
	] );
}

describe( 'Tag Manager module setup', () => {
	beforeAll( async () => {
		await page.setRequestInterception( true );
		useRequestInterception( ( request ) => {
			if ( request.url().match( 'google-site-kit/v1/data/' ) ) {
				request.respond( {
					status: 200,
				} );
			} else {
				request.continue();
			}
		} );
	} );

	beforeEach( async () => {
		await activatePlugin( 'e2e-tests-auth-plugin' );
		await activatePlugin( 'e2e-tests-site-verification-plugin' );
		await activatePlugin( 'e2e-tests-oauth-callback-plugin' );
		await setSearchConsoleProperty();
		await setupAnalytics();
	} );

	afterEach( async () => {
		await deactivateUtilityPlugins();
		await resetSiteKit();
	} );

	it( 'displays account creation form when user has no Tag Manager account', async () => {
		await activatePlugin( 'e2e-tests-module-setup-tagmanager-api-mock-no-account' );
		await proceedToTagManagerSetup();

		// Intercept the call to window.open and call our API to simulate a created account.
		await page.evaluate( () => {
			window.open = () => {
				window._e2eApiFetch( {
					path: 'google-site-kit/v1/e2e/setup/tagmanager/account-created',
					method: 'post',
				} );
			};
		} );

		// Clicking Create Account button will switch API mock plugins on the server to the one that has accounts.
		await Promise.all( [
			page.waitForResponse( ( res ) => res.url().match( 'google-site-kit/v1/e2e/setup/tagmanager/account-created' ) ),
			expect( page ).toClick( '.mdc-button', { text: /Create an account/i } ),
		] );

		await Promise.all( [
			page.waitForResponse( ( req ) => req.url().match( 'tagmanager/data/accounts' ) ),
			expect( page ).toClick( '.googlesitekit-cta-link', { text: /Re-fetch My Account/i } ),
		] );
		await page.waitForSelector( '.googlesitekit-setup-module__inputs' );

		// Ensure account and container selections are cleared.
		await expect( page ).toMatchElement( '.googlesitekit-tagmanager__select-account .mdc-select__selected-text', { text: '' } );
		await expect( page ).toMatchElement( '.googlesitekit-tagmanager__select-container .mdc-select__selected-text', { text: '' } );

		// Choose an account.
		await expect( page ).toClick( '.googlesitekit-tagmanager__select-account' );
		await expect( page ).toClick( '.mdc-menu-surface--open .mdc-list-item', { text: /test account a/i } );

		// Ensure "Set up a new container" option is present in container select.
		await expect( page ).toClick( '.googlesitekit-tagmanager__select-container' );
		await expect( page ).toMatchElement( '.mdc-menu-surface--open .mdc-list-item', { text: /set up a new container/i } );
		await expect( page ).toClick( '.mdc-menu-surface--open .mdc-list-item', { text: /test container x/i } );

		await page.waitFor( 1000 );
		await expect( page ).toClick( 'button', { text: /confirm \& continue/i } );

		await page.waitForSelector( '.googlesitekit-publisher-win--win-success' );
		await expect( page ).toMatchElement( '.googlesitekit-publisher-win__title', { text: /Congrats on completing the setup for Tag Manager!/i } );

		// Ensure expected tag is placed.
		await Promise.all( [
			page.goto( createURL( '/' ) ),
			page.waitForNavigation(),
		] );
		await expect( page ).toMatchElement( 'script[src^="https://www.googletagmanager.com/gtm.js?id=GTM-ABCXYZ"]' );
	} );

	it( 'displays available accounts and containers for the chosen account', async () => {
		await activatePlugin( 'e2e-tests-module-setup-tagmanager-api-mock' );
		await proceedToTagManagerSetup();

		// Ensure only web container select is shown.
		await expect( page ).toMatchElement( '.googlesitekit-tagmanager__select-container--web' );
		await expect( page ).not.toMatchElement( '.googlesitekit-tagmanager__select-container--amp' );

		// Ensure account and container are selected by default.
		await expect( page ).toMatchElement( '.googlesitekit-tagmanager__select-account .mdc-select__selected-text', { text: /test account a/i } );
		await expect( page ).toMatchElement( '.googlesitekit-tagmanager__select-container .mdc-select__selected-text', { text: /test container x/i } );

		// Ensure choosing a different account loads the proper values.
		await expect( page ).toClick( '.googlesitekit-tagmanager__select-account' );
		await Promise.all( [
			page.waitForResponse( ( res ) => res.url().match( 'modules/tagmanager/data' ) ),
			expect( page ).toClick( '.mdc-menu-surface--open .mdc-list-item', { text: /test account b/i } ),
		] );

		// Ensure account is selected.
		await expect( page ).toMatchElement( '.googlesitekit-tagmanager__select-account .mdc-select__selected-text', { text: /test account b/i } );

		// Select a container.
		await expect( page ).toClick( '.googlesitekit-tagmanager__select-container' );
		// Ensure no AMP containers are shown as options.
		// expect(...).not.toMatchElement with textContent matching does not work as expected.
		await expect(
			await page.$$eval( '.mdc-menu-surface--open .mdc-list-item', ( nodes ) => !! nodes.find( ( e ) => e.textContent.match( /test amp container/i ) ) )
		).toStrictEqual( false );
		await expect( page ).toClick( '.mdc-menu-surface--open .mdc-list-item', { text: /test container y/i } );

		await page.waitFor( 1000 );
		await expect( page ).toClick( 'button', { text: /confirm \& continue/i } );

		await page.waitForSelector( '.googlesitekit-publisher-win--win-success' );
		await expect( page ).toMatchElement( '.googlesitekit-publisher-win__title', { text: /Congrats on completing the setup for Tag Manager!/i } );

		// Ensure expected tag is placed.
		await Promise.all( [
			page.goto( createURL( '/' ) ),
			page.waitForNavigation(),
		] );
		await expect( page ).toMatchElement( 'script[src^="https://www.googletagmanager.com/gtm.js?id=GTM-BCDWXY"]' );
	} );

	it( 'displays instructions for account creation when "Set up a new account" option is selected', async () => {
		await activatePlugin( 'e2e-tests-module-setup-tagmanager-api-mock' );
		await proceedToTagManagerSetup();

		// Ensure "setup a new account" is an available choice.
		await expect( page ).toClick( '.googlesitekit-tagmanager__select-account' );
		await expect( page ).toMatchElement( '.mdc-menu-surface--open .mdc-list-item', { text: /set up a new account/i } );

		// Choose set up a new account.
		await expect( page ).toClick( '.mdc-menu-surface--open .mdc-list-item', { text: /set up a new account/i } );

		// Ensure instructions are present.
		await expect( page ).toMatchElement( '.googlesitekit-setup-module--tag-manager p', { text: /to create a new account/i } );

		// Ensure buttons are present.
		await expect( page ).toMatchElement( '.googlesitekit-setup-module--tag-manager .mdc-button', { text: /create an account/i } );
		await expect( page ).toMatchElement( '.googlesitekit-setup-module--tag-manager .googlesitekit-cta-link', { text: /re-fetch my account/i } );
	} );

	describe.each(
		Object.keys( allowedAmpModes )
	)( 'AMP mode %s', ( mode ) => {
		beforeEach( async () => {
			await activatePlugin( 'amp' );
			await activatePlugin( 'e2e-tests-module-setup-tagmanager-api-mock' );
		} );
		afterEach( async () => {
			await deactivatePlugin( 'amp' );
		} );
		it( 'renders the correct drop downs in the setup screen', async () => {
			await setAMPMode( mode );
			await proceedToTagManagerSetup();

			// Ensure that the correct dropdowns are displayed.
			if ( 'standard' !== mode ) {
				await expect( page ).toMatchElement( '.googlesitekit-tagmanager__select-container--web' );
			}
			await expect( page ).toMatchElement( '.googlesitekit-tagmanager__select-container--amp' );
		} );
	} );
	describe( 'Homepage AMP', () => {
		beforeEach( async () => {
			await activateAmpAndSetMode( 'standard' );
		} );
		afterEach( async () => {
			await deactivatePlugin( 'amp' );
		} );
		it( 'validates for logged-in users', async () => {
			await expect( '/' ).toHaveValidAMP( { loggedIn: true } );
		} );
		it( 'validates for non-logged-in users', async () => {
			await expect( '/' ).toHaveValidAMP();
		} );
	} );
} );
<|endoftext|>


<commit_before>const assert = require('assert');
const async = require('async');
const schedule = require('node-schedule');

const QueueProcessor = require('../../../extensions/replication' +
                               '/queueProcessor/QueueProcessor');
const TimeMachine = require('../utils/timeMachine');
const ZKStateHelper = require('../utils/pauseResumeUtils/zkStateHelper');
const MockAPI = require('../utils/pauseResumeUtils/mockAPI');

// Configs
const config = require('../../config.json');
const {
    zookeeperNamespace,
    zkStatePath,
} = require('../../../extensions/replication/constants');
const redisConfig = {
    host: config.redis.host,
    port: config.redis.port,
};
const zkConfig = config.zookeeper;
const kafkaConfig = config.kafka;
const repConfig = config.extensions.replication;
const sourceConfig = {
    auth: { type: 'skip' },
};
const destConfig = {
    auth: { type: 'skip', vault: 'skip' },
    bootstrapList: repConfig.destination.bootstrapList,
};
const mConfig = config.metrics;

// Constants
const ZK_TEST_CRR_STATE_PATH = `${zookeeperNamespace}${zkStatePath}`;

// Future Date to be used in tests
const futureDate = new Date();
futureDate.setHours(futureDate.getHours() + 5);

function isConsumerActive(consumer) {
    return consumer.getServiceStatus();
}

describe('CRR Pause/Resume status updates', function d() {
    this.timeout(10000);
    let zkHelper;
    let mockAPI;
    const firstSite = destConfig.bootstrapList[0].site;
    const secondSite = destConfig.bootstrapList[1].site;
    let qpSite1;
    let qpSite2;
    let consumer1;
    let consumer2;

    before(done => {
        mockAPI = new MockAPI(repConfig);
        zkHelper = new ZKStateHelper(config.zookeeper, ZK_TEST_CRR_STATE_PATH,
            firstSite, secondSite, futureDate);
        zkHelper.init(err => {
            if (err) {
                return done(err);
            }
            const zkClient = zkHelper.getClient();

            // qpSite1 (first site) is not paused
            qpSite1 = new QueueProcessor(zkConfig, zkClient,
                kafkaConfig, sourceConfig, destConfig, repConfig,
                redisConfig, mConfig, {}, {}, firstSite);
            qpSite1.start();

            // qpSite2 (second site) is paused and has a scheduled resume
            qpSite2 = new QueueProcessor(zkConfig, zkClient,
               kafkaConfig, sourceConfig, destConfig, repConfig,
               redisConfig, mConfig, {}, {}, secondSite);
            qpSite2.start({ paused: true });
            qpSite2.scheduleResume(futureDate);

            // wait for clients/jobs to set
            return async.whilst(() => (
                !consumer1 && !consumer2 && !qpSite2.scheduledResume
            ), cb => setTimeout(() => {
                consumer1 = qpSite1._consumer;
                consumer2 = qpSite2._consumer;
                return cb();
            }, 1000), done);
        });
    });

    afterEach(done => {
        consumer1.resume();
        consumer2.pause();
        async.whilst(() => qpSite1.scheduledResume !== null ||
            !qpSite2.scheduledResume,
        cb => setTimeout(() => {
            qpSite1._deleteScheduledResumeService();
            qpSite2.scheduleResume(futureDate);
            cb();
        }, 1000), err => {
            assert.ifError(err);
            zkHelper.reset(done);
        });
    });

    after(() => {
        zkHelper.close();
    });

    it('should pause an active location', done => {
        let zkPauseState;
        // send fake api request
        mockAPI.pauseService(firstSite);

        return async.doWhilst(cb => setTimeout(() => {
            zkHelper.get(firstSite, (err, data) => {
                if (err) {
                    return cb(err);
                }
                zkPauseState = data.paused;
                return cb();
            });
        }, 1000), () => isConsumerActive(consumer1),
        err => {
            assert.ifError(err);
            // is zookeeper state shown as paused?
            assert.strictEqual(zkPauseState, true);
            // is the consumer currently subscribed to any topics?
            assert.strictEqual(isConsumerActive(consumer1), false);
            return done();
        });
    });

    it('should not change state if pausing an already paused location',
    done => {
        let zkPauseState;
        let zkScheduleState;
        // double-check initial state
        assert.strictEqual(isConsumerActive(consumer2), false);
        // send fake api request
        mockAPI.pauseService(secondSite);

        return async.doWhilst(cb => setTimeout(() => {
            zkHelper.get(secondSite, (err, data) => {
                if (err) {
                    return cb(err);
                }
                zkPauseState = data.paused;
                zkScheduleState = data.scheduledResume;
                return cb();
            });
        }, 1000), () => isConsumerActive(consumer2),
        err => {
            assert.ifError(err);
            assert.strictEqual(zkPauseState, true);
            assert.strictEqual(isConsumerActive(consumer2), false);
            assert.strictEqual(new Date(zkScheduleState).toString(),
                futureDate.toString());
            return done();
        });
    });

    it('should resume a paused location', done => {
        let zkPauseState;
        // send fake api request
        mockAPI.resumeService(secondSite);

        return async.doWhilst(cb => setTimeout(() => {
            zkHelper.get(secondSite, (err, data) => {
                if (err) {
                    return cb(err);
                }
                zkPauseState = data.paused;
                return cb();
            });
        }, 1000), () => !isConsumerActive(consumer2),
        err => {
            assert.ifError(err);
            assert.strictEqual(zkPauseState, false);
            assert.strictEqual(isConsumerActive(consumer2), true);
            return done();
        });
    });

    it('should not change state if resuming an already active location',
    done => {
        let zkPauseState;
        // double-check initial state
        assert.strictEqual(isConsumerActive(consumer1), true);
        // send fake api request
        mockAPI.resumeService(firstSite);
        return async.doWhilst(cb => setTimeout(() => {
            zkHelper.get(firstSite, (err, data) => {
                if (err) {
                    return cb(err);
                }
                zkPauseState = data.paused;
                return cb();
            });
        }, 1000), () => isConsumerActive(consumer1) !== true,
        err => {
            assert.ifError(err);
            assert.strictEqual(zkPauseState, false);
            assert.strictEqual(isConsumerActive(consumer1), true);
            return done();
        });
    });

    it('should cancel a scheduled resume for a given location', done => {
        let zkScheduleState;
        // send fake api request
        mockAPI.deleteScheduledResumeService(secondSite);

        return async.doWhilst(cb => setTimeout(() => {
            zkHelper.get(secondSite, (err, data) => {
                if (err) {
                    return cb(err);
                }
                zkScheduleState = data.scheduledResume;
                return cb();
            });
        }, 1000), () => zkScheduleState !== null,
        err => {
            assert.ifError(err);
            assert.strictEqual(zkScheduleState, null);
            return done();
        });
    });

    it('should schedule a resume', done => {
        let zkPauseState;
        let zkScheduleState;
        // since re-using firstSite, pause it first for this test
        const pauseState = JSON.stringify({ paused: true });
        zkHelper.set(firstSite, pauseState, err => {
            assert.ifError(err);
            consumer1.pause();
            // send fake api request
            mockAPI.resumeService(firstSite, futureDate);

            return async.doWhilst(cb => setTimeout(() => {
                zkHelper.get(firstSite, (err, data) => {
                    if (err) {
                        return cb(err);
                    }
                    zkPauseState = data.paused;
                    zkScheduleState = data.scheduledResume;
                    return cb();
                });
            }, 1000), () => {
                if (zkScheduleState) {
                    const zkStateDate = new Date(zkScheduleState);
                    return zkStateDate.getTime() !== futureDate.getTime();
                }
                return true;
            }, err => {
                assert.ifError(err);
                assert.strictEqual(zkPauseState, true);
                assert.strictEqual(new Date(zkScheduleState).toString(),
                    futureDate.toString());
                done();
            });
        });
    });

    [
        // new schedule time is less than current scheduled time
        {
            testCase: 'less than',
            timeChange: -1,
        },
        // new schedule time is greater than current scheduled time
        {
            testCase: 'greater than',
            timeChange: 1,
        },
    ].forEach(item => {
        it('should overwrite an existing scheduled resume on new valid ' +
        `request where new time is ${item.testCase} current scheduled time`,
        done => {
            let zkScheduleState;
            const newScheduledDate = new Date(futureDate);
            newScheduledDate.setHours(newScheduledDate.getHours() +
                item.timeChange);
            // send fake api request
            mockAPI.resumeService(secondSite, newScheduledDate);

            return async.doWhilst(cb => setTimeout(() => {
                zkHelper.get(secondSite, (err, data) => {
                    if (err) {
                        return cb(err);
                    }
                    zkScheduleState = data.scheduledResume;
                    return cb();
                });
            }, 1000), () => {
                if (zkScheduleState) {
                    const zkStateDate = new Date(zkScheduleState);
                    return zkStateDate.getTime() !== newScheduledDate.getTime();
                }
                return true;
            }, err => {
                assert.ifError(err);
                assert.strictEqual(new Date(zkScheduleState).toString(),
                    newScheduledDate.toString());
                done();
            });
        });
    });

    it('should cancel a scheduled resume when the location is manually ' +
    'resumed', done => {
        let zkScheduleState;
        let zkPauseState;
        // send fake api request
        mockAPI.resumeService(secondSite);

        return async.doWhilst(cb => setTimeout(() => {
            zkHelper.get(secondSite, (err, data) => {
                if (err) {
                    return cb(err);
                }
                zkPauseState = data.paused;
                zkScheduleState = data.scheduledResume;
                return cb();
            });
        }, 1000), () => isConsumerActive(consumer2) !== true,
        err => {
            assert.ifError(err);
            assert.strictEqual(zkPauseState, false);
            assert.strictEqual(zkScheduleState, null);
            done();
        });
    });

    it('should not schedule a resume when the location is already active',
    done => {
        // send fake api request
        mockAPI.resumeService(firstSite, futureDate);

        setTimeout(() => {
            zkHelper.get(firstSite, (err, data) => {
                assert.ifError(err);

                assert.strictEqual(data.scheduledResume, null);
                assert.strictEqual(data.paused, false);
                assert.strictEqual(isConsumerActive(consumer1), true);
                done();
            });
        }, 1000);
    });

    it('should resume a location when a scheduled resume triggers',
    done => {
        let zkPauseState;
        let zkScheduleState;
        // move time forward to trigger scheduled resume
        const timeMachine = new TimeMachine();
        timeMachine.install();
        // hack - for some reason, the scheduled job in QueueProcessor does not
        // trigger unless I schedule a job here.
        schedule.scheduleJob(new Date(), () => {});
        timeMachine.moveTimeForward(6);

        return async.doWhilst(cb => setTimeout(() => {
            zkHelper.get(secondSite, (err, data) => {
                if (err) {
                    return cb(err);
                }
                zkPauseState = data.paused;
                zkScheduleState = data.scheduledResume;
                return cb();
            });
        }, 1000), () => isConsumerActive(consumer2) !== true,
        err => {
            timeMachine.uninstall();
            assert.ifError(err);
            assert.strictEqual(zkPauseState, false);
            assert.strictEqual(isConsumerActive(consumer2), true);
            assert.strictEqual(zkScheduleState, null);
            done();
        });
    });
});
<commit_msg>Fix failing replication test<commit_after>const assert = require('assert');
const async = require('async');
const schedule = require('node-schedule');

const QueueProcessor = require('../../../extensions/replication' +
                               '/queueProcessor/QueueProcessor');
const TimeMachine = require('../utils/timeMachine');
const ZKStateHelper = require('../utils/pauseResumeUtils/zkStateHelper');
const MockAPI = require('../utils/pauseResumeUtils/mockAPI');

// Configs
const config = require('../../config.json');
const {
    zookeeperNamespace,
    zkStatePath,
} = require('../../../extensions/replication/constants');
const redisConfig = {
    host: config.redis.host,
    port: config.redis.port,
};
const zkConfig = config.zookeeper;
const kafkaConfig = config.kafka;
const repConfig = config.extensions.replication;
const sourceConfig = {
    auth: { type: 'skip' },
};
const destConfig = {
    auth: { type: 'skip', vault: 'skip' },
    bootstrapList: repConfig.destination.bootstrapList,
};
const mConfig = config.metrics;

// Constants
const ZK_TEST_CRR_STATE_PATH = `${zookeeperNamespace}${zkStatePath}`;

// Future Date to be used in tests
const futureDate = new Date();
futureDate.setHours(futureDate.getHours() + 5);

function isConsumerActive(consumer) {
    return consumer.getServiceStatus();
}

describe('CRR Pause/Resume status updates', function d() {
    this.timeout(10000);
    let zkHelper;
    let mockAPI;
    const firstSite = destConfig.bootstrapList[0].site;
    const secondSite = destConfig.bootstrapList[1].site;
    let qpSite1;
    let qpSite2;
    let consumer1;
    let consumer2;

    before(done => {
        mockAPI = new MockAPI(repConfig);
        zkHelper = new ZKStateHelper(config.zookeeper, ZK_TEST_CRR_STATE_PATH,
            firstSite, secondSite, futureDate);
        zkHelper.init(err => {
            if (err) {
                return done(err);
            }
            const zkClient = zkHelper.getClient();

            // qpSite1 (first site) is not paused
            qpSite1 = new QueueProcessor(
                'backbeat-func-test-dummy-topic', zkConfig, zkClient,
                kafkaConfig, sourceConfig, destConfig, repConfig,
                redisConfig, mConfig, {}, {}, firstSite);
            qpSite1.start();

            // qpSite2 (second site) is paused and has a scheduled resume
            qpSite2 = new QueueProcessor(
                'backbeat-func-test-dummy-topic', zkConfig, zkClient,
               kafkaConfig, sourceConfig, destConfig, repConfig,
               redisConfig, mConfig, {}, {}, secondSite);
            qpSite2.start({ paused: true });
            qpSite2.scheduleResume(futureDate);

            // wait for clients/jobs to set
            return async.whilst(() => (
                !consumer1 && !consumer2 && !qpSite2.scheduledResume
            ), cb => setTimeout(() => {
                consumer1 = qpSite1._consumer;
                consumer2 = qpSite2._consumer;
                return cb();
            }, 1000), done);
        });
    });

    afterEach(done => {
        consumer1.resume();
        consumer2.pause();
        async.whilst(() => qpSite1.scheduledResume !== null ||
            !qpSite2.scheduledResume,
        cb => setTimeout(() => {
            qpSite1._deleteScheduledResumeService();
            qpSite2.scheduleResume(futureDate);
            cb();
        }, 1000), err => {
            assert.ifError(err);
            zkHelper.reset(done);
        });
    });

    after(() => {
        zkHelper.close();
    });

    it('should pause an active location', done => {
        let zkPauseState;
        // send fake api request
        mockAPI.pauseService(firstSite);

        return async.doWhilst(cb => setTimeout(() => {
            zkHelper.get(firstSite, (err, data) => {
                if (err) {
                    return cb(err);
                }
                zkPauseState = data.paused;
                return cb();
            });
        }, 1000), () => isConsumerActive(consumer1),
        err => {
            assert.ifError(err);
            // is zookeeper state shown as paused?
            assert.strictEqual(zkPauseState, true);
            // is the consumer currently subscribed to any topics?
            assert.strictEqual(isConsumerActive(consumer1), false);
            return done();
        });
    });

    it('should not change state if pausing an already paused location',
    done => {
        let zkPauseState;
        let zkScheduleState;
        // double-check initial state
        assert.strictEqual(isConsumerActive(consumer2), false);
        // send fake api request
        mockAPI.pauseService(secondSite);

        return async.doWhilst(cb => setTimeout(() => {
            zkHelper.get(secondSite, (err, data) => {
                if (err) {
                    return cb(err);
                }
                zkPauseState = data.paused;
                zkScheduleState = data.scheduledResume;
                return cb();
            });
        }, 1000), () => isConsumerActive(consumer2),
        err => {
            assert.ifError(err);
            assert.strictEqual(zkPauseState, true);
            assert.strictEqual(isConsumerActive(consumer2), false);
            assert.strictEqual(new Date(zkScheduleState).toString(),
                futureDate.toString());
            return done();
        });
    });

    it('should resume a paused location', done => {
        let zkPauseState;
        // send fake api request
        mockAPI.resumeService(secondSite);

        return async.doWhilst(cb => setTimeout(() => {
            zkHelper.get(secondSite, (err, data) => {
                if (err) {
                    return cb(err);
                }
                zkPauseState = data.paused;
                return cb();
            });
        }, 1000), () => !isConsumerActive(consumer2),
        err => {
            assert.ifError(err);
            assert.strictEqual(zkPauseState, false);
            assert.strictEqual(isConsumerActive(consumer2), true);
            return done();
        });
    });

    it('should not change state if resuming an already active location',
    done => {
        let zkPauseState;
        // double-check initial state
        assert.strictEqual(isConsumerActive(consumer1), true);
        // send fake api request
        mockAPI.resumeService(firstSite);
        return async.doWhilst(cb => setTimeout(() => {
            zkHelper.get(firstSite, (err, data) => {
                if (err) {
                    return cb(err);
                }
                zkPauseState = data.paused;
                return cb();
            });
        }, 1000), () => isConsumerActive(consumer1) !== true,
        err => {
            assert.ifError(err);
            assert.strictEqual(zkPauseState, false);
            assert.strictEqual(isConsumerActive(consumer1), true);
            return done();
        });
    });

    it('should cancel a scheduled resume for a given location', done => {
        let zkScheduleState;
        // send fake api request
        mockAPI.deleteScheduledResumeService(secondSite);

        return async.doWhilst(cb => setTimeout(() => {
            zkHelper.get(secondSite, (err, data) => {
                if (err) {
                    return cb(err);
                }
                zkScheduleState = data.scheduledResume;
                return cb();
            });
        }, 1000), () => zkScheduleState !== null,
        err => {
            assert.ifError(err);
            assert.strictEqual(zkScheduleState, null);
            return done();
        });
    });

    it('should schedule a resume', done => {
        let zkPauseState;
        let zkScheduleState;
        // since re-using firstSite, pause it first for this test
        const pauseState = JSON.stringify({ paused: true });
        zkHelper.set(firstSite, pauseState, err => {
            assert.ifError(err);
            consumer1.pause();
            // send fake api request
            mockAPI.resumeService(firstSite, futureDate);

            return async.doWhilst(cb => setTimeout(() => {
                zkHelper.get(firstSite, (err, data) => {
                    if (err) {
                        return cb(err);
                    }
                    zkPauseState = data.paused;
                    zkScheduleState = data.scheduledResume;
                    return cb();
                });
            }, 1000), () => {
                if (zkScheduleState) {
                    const zkStateDate = new Date(zkScheduleState);
                    return zkStateDate.getTime() !== futureDate.getTime();
                }
                return true;
            }, err => {
                assert.ifError(err);
                assert.strictEqual(zkPauseState, true);
                assert.strictEqual(new Date(zkScheduleState).toString(),
                    futureDate.toString());
                done();
            });
        });
    });

    [
        // new schedule time is less than current scheduled time
        {
            testCase: 'less than',
            timeChange: -1,
        },
        // new schedule time is greater than current scheduled time
        {
            testCase: 'greater than',
            timeChange: 1,
        },
    ].forEach(item => {
        it('should overwrite an existing scheduled resume on new valid ' +
        `request where new time is ${item.testCase} current scheduled time`,
        done => {
            let zkScheduleState;
            const newScheduledDate = new Date(futureDate);
            newScheduledDate.setHours(newScheduledDate.getHours() +
                item.timeChange);
            // send fake api request
            mockAPI.resumeService(secondSite, newScheduledDate);

            return async.doWhilst(cb => setTimeout(() => {
                zkHelper.get(secondSite, (err, data) => {
                    if (err) {
                        return cb(err);
                    }
                    zkScheduleState = data.scheduledResume;
                    return cb();
                });
            }, 1000), () => {
                if (zkScheduleState) {
                    const zkStateDate = new Date(zkScheduleState);
                    return zkStateDate.getTime() !== newScheduledDate.getTime();
                }
                return true;
            }, err => {
                assert.ifError(err);
                assert.strictEqual(new Date(zkScheduleState).toString(),
                    newScheduledDate.toString());
                done();
            });
        });
    });

    it('should cancel a scheduled resume when the location is manually ' +
    'resumed', done => {
        let zkScheduleState;
        let zkPauseState;
        // send fake api request
        mockAPI.resumeService(secondSite);

        return async.doWhilst(cb => setTimeout(() => {
            zkHelper.get(secondSite, (err, data) => {
                if (err) {
                    return cb(err);
                }
                zkPauseState = data.paused;
                zkScheduleState = data.scheduledResume;
                return cb();
            });
        }, 1000), () => isConsumerActive(consumer2) !== true,
        err => {
            assert.ifError(err);
            assert.strictEqual(zkPauseState, false);
            assert.strictEqual(zkScheduleState, null);
            done();
        });
    });

    it('should not schedule a resume when the location is already active',
    done => {
        // send fake api request
        mockAPI.resumeService(firstSite, futureDate);

        setTimeout(() => {
            zkHelper.get(firstSite, (err, data) => {
                assert.ifError(err);

                assert.strictEqual(data.scheduledResume, null);
                assert.strictEqual(data.paused, false);
                assert.strictEqual(isConsumerActive(consumer1), true);
                done();
            });
        }, 1000);
    });

    it('should resume a location when a scheduled resume triggers',
    done => {
        let zkPauseState;
        let zkScheduleState;
        // move time forward to trigger scheduled resume
        const timeMachine = new TimeMachine();
        timeMachine.install();
        // hack - for some reason, the scheduled job in QueueProcessor does not
        // trigger unless I schedule a job here.
        schedule.scheduleJob(new Date(), () => {});
        timeMachine.moveTimeForward(6);

        return async.doWhilst(cb => setTimeout(() => {
            zkHelper.get(secondSite, (err, data) => {
                if (err) {
                    return cb(err);
                }
                zkPauseState = data.paused;
                zkScheduleState = data.scheduledResume;
                return cb();
            });
        }, 1000), () => isConsumerActive(consumer2) !== true,
        err => {
            timeMachine.uninstall();
            assert.ifError(err);
            assert.strictEqual(zkPauseState, false);
            assert.strictEqual(isConsumerActive(consumer2), true);
            assert.strictEqual(zkScheduleState, null);
            done();
        });
    });
});
<|endoftext|>


<commit_before>import adapter, { ajaxOptions } from '../src'
global.fetch = require('jest-fetch-mock')

adapter.apiPath = '/api'

let ret
function lastRequest () {
  const mock = global.fetch.mock
  return mock.calls[mock.calls.length - 1][0]
}

function injectDone (values) {
  global.fetch.mockResponseOnce(
    JSON.stringify(values), { status: 200 }
  )
}

function injectFail (values) {
  global.fetch.mockResponseOnce(
    JSON.stringify(values), { status: 422 }
  )
}

function testCommonOptions (method) {
  return it('deep merges the default `commonOptions` with the passed options', () => {
    adapter.commonOptions = {
      headers: {
        'some-header': 'test1'
      }
    }

    const options = {
      headers: {
        'some-other-header': 'test2'
      }
    }

    injectDone({})

    const args = method === 'del'
      ? ['/users', options]
      : ['/users', null, options]

    const request = adapter[method].apply(adapter, args)

    return request.promise.then(() => {
      expect(lastRequest().headers.get('some-header')).toEqual('test1')
      expect(lastRequest().headers.get('some-other-header')).toEqual('test2')
    })
  })
}

describe('adapter', () => {
  beforeEach(() => {
    adapter.commonOptions = {}
  })

  describe('ajaxOptions(options)', () => {
    it('allows to define custom headers', () => {
      const options = ajaxOptions({
        headers: {
          'some-header': 'test1',
          'some-other-header': 'test2'
        }
      })

      expect(options.headers.get('some-header')).toEqual('test1')
      expect(options.headers.get('some-other-header')).toEqual('test2')
    })
  })

  describe('ajax', () => {
    describe('when it fails with a malformed response', () => {
      const values = 'ERROR'

      beforeEach(() => {
        injectFail(values)
        ret = adapter.get('/users')
      })

      it('returns the error wrapper into an array', () => {
        expect(ret.abort).toBeTruthy()

        return ret.promise.catch((vals) => {
          expect(vals).toEqual({})
        })
      })
    })
  })

  describe('get', () => {
    const data = { manager_id: 2 }

    const action = () => {
      ret = adapter.get('/users', data)
    }

    testCommonOptions('get')

    describe('when it resolves', () => {
      const values = { id: 1, name: 'paco' }

      beforeEach(() => {
        injectDone(values)
        action()
      })

      it('sends a xhr request with data parameters', () => {
        expect(ret.abort).toBeTruthy()

        return ret.promise.then((vals) => {
          expect(vals).toEqual(values)
          expect(lastRequest().url).toBe('/api/users?manager_id=2')
          expect(lastRequest().method).toBe('GET')
          expect(lastRequest().headers.map['content-type']).toEqual(['application/json'])
        })
      })
    })

    describe('when it fails', () => {
      const values = '{"errors": ["foo"]}'

      beforeEach(() => {
        injectFail(values)
        action()
      })

      it('sends a xhr request with data parameters', () => {
        expect(ret.abort).toBeTruthy()

        return ret.promise.catch((vals) => {
          expect(vals).toEqual(['foo'])
        })
      })
    })
  })

  describe('post', () => {
    let data

    const action = () => {
      ret = adapter.post('/users', data)
    }

    testCommonOptions('post')

    describe('when it resolves', () => {
      const values = { id: 1, name: 'paco' }

      beforeEach(() => {
        data = { name: 'paco' }
        injectDone(values)
        action()
      })

      it('sends a xhr request with data parameters', () => {
        expect(ret.abort).toBeTruthy()

        return ret.promise.then((vals) => {
          expect(vals).toEqual(values)
          expect(lastRequest().url).toBe('/api/users')
          expect(lastRequest().method).toBe('POST')
          expect(lastRequest().headers.map['content-type']).toEqual(['application/json'])
          expect(lastRequest()._bodyInit).toBe('{"name":"paco"}')
        })
      })
    })

    describe('when it fails', () => {
      const values = '{"errors": ["foo"]}'

      beforeEach(() => {
        data = { name: 'paco' }
        injectFail(values)
        action()
      })

      it('sends a xhr request with data parameters', () => {
        expect(ret.abort).toBeTruthy()

        return ret.promise.catch((vals) => {
          expect(vals).toEqual(['foo'])
        })
      })
    })
  })

  describe('put', () => {
    const data = { name: 'paco' }

    const action = () => {
      ret = adapter.put('/users', data)
    }

    testCommonOptions('put')

    describe('when it resolves', () => {
      const values = { id: 1, name: 'paco' }

      beforeEach(() => {
        injectDone(values)
        action()
      })

      it('sends a xhr request with data parameters', () => {
        expect(ret.abort).toBeTruthy()

        return ret.promise.then((vals) => {
          expect(vals).toEqual(values)
          expect(lastRequest().url).toBe('/api/users')
          expect(lastRequest().method).toBe('PUT')
          expect(lastRequest().headers.map['content-type']).toEqual(['application/json'])
          expect(lastRequest()._bodyInit).toBe('{"name":"paco"}')
        })
      })
    })

    describe('when it fails', () => {
      const values = '{"errors": ["foo"]}'

      beforeEach(() => {
        injectFail(values)
        action()
      })

      it('sends a xhr request with data parameters', () => {
        expect(ret.abort).toBeTruthy()

        return ret.promise.catch((vals) => {
          expect(vals).toEqual(['foo'])
        })
      })
    })
  })

  describe('del', () => {
    const action = () => {
      ret = adapter.del('/users')
    }

    testCommonOptions('del')

    describe('when it resolves', () => {
      const values = { id: 1, name: 'paco' }

      beforeEach(() => {
        injectDone(values)
        action()
      })

      it('sends a xhr request with data parameters', () => {
        expect(ret.abort).toBeTruthy()

        return ret.promise.then((vals) => {
          expect(vals).toEqual(values)
          expect(lastRequest().url).toEqual('/api/users')
          expect(lastRequest().method).toBe('DELETE')
          expect(lastRequest().headers.map['content-type']).toEqual(['application/json'])
        })
      })
    })

    describe('when it fails', () => {
      const values = '{"errors": ["foo"]}'

      beforeEach(() => {
        injectFail(values)
        action()
      })

      it('sends a xhr request with data parameters', () => {
        expect(ret.abort).toBeTruthy()

        return ret.promise.catch((vals) => {
          expect(vals).toEqual(['foo'])
        })
      })
    })
  })
})
<commit_msg>Forces silently failing tests to throw<commit_after>import adapter, { ajaxOptions } from '../src'
global.fetch = require('jest-fetch-mock')

adapter.apiPath = '/api'

let ret
function lastRequest () {
  const mock = global.fetch.mock
  return mock.calls[mock.calls.length - 1][0]
}

function injectDone (values) {
  global.fetch.mockResponseOnce(
    JSON.stringify(values), { status: 200 }
  )
}

function injectFail (values) {
  global.fetch.mockResponseOnce(
    JSON.stringify(values), { status: 422 }
  )
}

function testCommonOptions (method) {
  return it('deep merges the default `commonOptions` with the passed options', () => {
    adapter.commonOptions = {
      headers: {
        'some-header': 'test1'
      }
    }

    const options = {
      headers: {
        'some-other-header': 'test2'
      }
    }

    injectDone({})

    const args = method === 'del'
      ? ['/users', options]
      : ['/users', null, options]

    const request = adapter[method].apply(adapter, args)

    return request.promise.then(() => {
      expect(lastRequest().headers.get('some-header')).toEqual('test1')
      expect(lastRequest().headers.get('some-other-header')).toEqual('test2')
    })
  })
}

describe('adapter', () => {
  beforeEach(() => {
    adapter.commonOptions = {}
  })

  describe('ajaxOptions(options)', () => {
    it('allows to define custom headers', () => {
      const options = ajaxOptions({
        headers: {
          'some-header': 'test1',
          'some-other-header': 'test2'
        }
      })

      expect(options.headers.get('some-header')).toEqual('test1')
      expect(options.headers.get('some-other-header')).toEqual('test2')
    })
  })

  describe('ajax', () => {
    describe('when it fails with a malformed response', () => {
      const values = 'ERROR'

      beforeEach(() => {
        injectFail(values)
        ret = adapter.get('/users')
      })

      it('returns the error wrapper into an array', () => {
        expect.assertions(2)

        expect(ret.abort).toBeTruthy()

        return ret.promise.catch((vals) => {
          expect(vals).toEqual({})
        })
      })
    })
  })

  describe('get', () => {
    const data = { manager_id: 2 }

    const action = () => {
      ret = adapter.get('/users', data)
    }

    testCommonOptions('get')

    describe('when it resolves', () => {
      const values = { id: 1, name: 'paco' }

      beforeEach(() => {
        injectDone(values)
        action()
      })

      it('sends a xhr request with data parameters', () => {
        expect(ret.abort).toBeTruthy()

        return ret.promise.then((vals) => {
          expect(vals).toEqual(values)
          expect(lastRequest().url).toBe('/api/users?manager_id=2')
          expect(lastRequest().method).toBe('GET')
          expect(lastRequest().headers.map['content-type']).toEqual(['application/json'])
        })
      })
    })

    describe('when it fails', () => {
      const values = '{"errors": ["foo"]}'

      beforeEach(() => {
        injectFail(values)
        action()
      })

      it('sends a xhr request with data parameters', () => {
        expect.assertions(2)

        expect(ret.abort).toBeTruthy()

        return ret.promise.catch((vals) => {
          expect(vals).toEqual(['foo'])
        })
      })
    })
  })

  describe('post', () => {
    let data

    const action = () => {
      ret = adapter.post('/users', data)
    }

    testCommonOptions('post')

    describe('when it resolves', () => {
      const values = { id: 1, name: 'paco' }

      beforeEach(() => {
        data = { name: 'paco' }
        injectDone(values)
        action()
      })

      it('sends a xhr request with data parameters', () => {
        expect(ret.abort).toBeTruthy()

        return ret.promise.then((vals) => {
          expect(vals).toEqual(values)
          expect(lastRequest().url).toBe('/api/users')
          expect(lastRequest().method).toBe('POST')
          expect(lastRequest().headers.map['content-type']).toEqual(['application/json'])
          expect(lastRequest()._bodyInit).toBe('{"name":"paco"}')
        })
      })
    })

    describe('when it fails', () => {
      const values = '{"errors": ["foo"]}'

      beforeEach(() => {
        data = { name: 'paco' }
        injectFail(values)
        action()
      })

      it('sends a xhr request with data parameters', () => {
        expect.assertions(2)

        expect(ret.abort).toBeTruthy()

        return ret.promise.catch((vals) => {
          expect(vals).toEqual(['foo'])
        })
      })
    })
  })

  describe('put', () => {
    const data = { name: 'paco' }

    const action = () => {
      ret = adapter.put('/users', data)
    }

    testCommonOptions('put')

    describe('when it resolves', () => {
      const values = { id: 1, name: 'paco' }

      beforeEach(() => {
        injectDone(values)
        action()
      })

      it('sends a xhr request with data parameters', () => {
        expect(ret.abort).toBeTruthy()

        return ret.promise.then((vals) => {
          expect(vals).toEqual(values)
          expect(lastRequest().url).toBe('/api/users')
          expect(lastRequest().method).toBe('PUT')
          expect(lastRequest().headers.map['content-type']).toEqual(['application/json'])
          expect(lastRequest()._bodyInit).toBe('{"name":"paco"}')
        })
      })
    })

    describe('when it fails', () => {
      const values = '{"errors": ["foo"]}'

      beforeEach(() => {
        injectFail(values)
        action()
      })

      it('sends a xhr request with data parameters', () => {
        expect.assertions(2)

        expect(ret.abort).toBeTruthy()

        return ret.promise.catch((vals) => {
          expect(vals).toEqual(['foo'])
        })
      })
    })
  })

  describe('del', () => {
    const action = () => {
      ret = adapter.del('/users')
    }

    testCommonOptions('del')

    describe('when it resolves', () => {
      const values = { id: 1, name: 'paco' }

      beforeEach(() => {
        injectDone(values)
        action()
      })

      it('sends a xhr request with data parameters', () => {
        expect(ret.abort).toBeTruthy()

        return ret.promise.then((vals) => {
          expect(vals).toEqual(values)
          expect(lastRequest().url).toEqual('/api/users')
          expect(lastRequest().method).toBe('DELETE')
          expect(lastRequest().headers.map['content-type']).toEqual(['application/json'])
        })
      })
    })

    describe('when it fails', () => {
      const values = '{"errors": ["foo"]}'

      beforeEach(() => {
        injectFail(values)
        action()
      })

      it('sends a xhr request with data parameters', () => {
        expect.assertions(2)

        expect(ret.abort).toBeTruthy()

        return ret.promise.catch((vals) => {
          expect(vals).toEqual(['foo'])
        })
      })
    })
  })
})
<|endoftext|>