<commit_before>var Q = require('q');
var assert = require('assert');

var vumigo = require('../../lib');
var test_utils = vumigo.test_utils;
var DummyApi = vumigo.dummy.api.DummyApi;
var DummyResourceError = vumigo.dummy.resources.DummyResourceError;

describe("kv.dummy", function() {
    var api;
    var request;

    beforeEach(function() {
        api =  new DummyApi();
        request = test_utils.requester(api);
    });

    describe("DummyKvResource", function() {
        describe(".incr", function() {
            it("should increment the value if it is an integer", function() {
                api.kv.store.foo = 2;
                assert.strictEqual(api.kv.incr('foo', 6), 8);
                assert.equal(api.kv.store.foo, 8);
            });

            it("should use 1 as the default increment amount", function() {
                api.kv.store.foo = 2;
                assert.strictEqual(api.kv.incr('foo'), 3);
                assert.equal(api.kv.store.foo, 3);
            });

            it("should initialise new keys", function() {
                assert.strictEqual(api.kv.incr('foo'), 1);
                assert.equal(api.kv.store.foo, 1);
            });

            it("should throw an error for non-integer values", function() {
                api.kv.store.foo = 'bar';

                assert.throws(
                    function() {
                        api.kv.incr('foo');
                    },
                    function(e) {
                        assert(e instanceof DummyResourceError);
                        assert.equal(
                            e.message,
                            ["Cannot increment non-integer value for key",
                             "'foo': bar"].join(' '));

                        return true;
                    });
            });

            it("should throw an error for non-integer amount", function() {
                api.kv.store.foo = 2;

                assert.throws(
                    function() {
                        api.kv.incr('foo', 'bar');
                    },
                    function(e) {
                        assert(e instanceof DummyResourceError);
                        assert.equal(
                            e.message,
                            ["Non-integer increment amount given for key",
                             "'foo': bar"].join(' '));

                        return true;
                    });
            });
        });

        describe(".handlers", function() {
            describe(".get", function() {
                it("should retrieve the value for the given key", function() {
                    api.kv.store.foo = 'bar';

                    return request('kv.get', {
                        key: 'foo'
                    }).then(function(reply) {
                        assert(reply.success);
                        assert.equal(reply.value, 'bar');
                    });
                });

                it("should return null if the key does not exist", function() {
                    return request('kv.get', {
                        key: 'foo'
                    }).then(function(reply) {
                        assert(reply.success);
                        assert.strictEqual(reply.value, null);
                    });
                });
            });

            describe(".set", function() {
                it("should set the value of the given key", function() {
                    return request('kv.set', {
                        key: 'foo',
                        value: 'bar'
                    }).then(function(reply) {
                        assert(reply.success);
                        assert.equal(api.kv.store.foo, 'bar');
                    });
                });
            });

            describe(".incr", function() {
                it("should increment the value of the given key", function() {
                    api.kv.store.foo = 2;

                    return request('kv.incr', {
                        key: 'foo',
                        amount: 6
                    }).then(function(reply) {
                        assert(reply.success);
                        assert.equal(reply.value, 8);
                        assert.equal(api.kv.store.foo, 8);
                    });
                });

                it("should use 1 as the default increment amount", function() {
                    api.kv.store.foo = 2;

                    return request('kv.incr', {
                        key: 'foo',
                    }).then(function(reply) {
                        assert(reply.success);
                        assert.equal(reply.value, 3);
                        assert.equal(api.kv.store.foo, 3);
                    });
                });

                it("should fail for non-integer keys", function() {
                    api.kv.store.foo = 'bar';

                    return request('kv.incr', {
                        key: 'foo',
                    }).then(function(reply) {
                        assert(!reply.success);
                        assert.equal(
                            reply.reason,
                            ["Cannot increment non-integer value for key",
                             "'foo': bar"].join(' '));
                    });
                });

                it("should fail for non-integer amounts", function() {
                    api.kv.store.foo = 2;

                    return request('kv.incr', {
                        key: 'foo',
                        amount: 'bar'
                    }).then(function(reply) {
                        assert(!reply.success);
                        assert.equal(
                            reply.reason,
                            ["Non-integer increment amount given for key",
                             "'foo': bar"].join(' '));
                    });
                });
            });

            describe(".delete", function() {
                it("should delete the give key from the store", function() {
                    api.kv.store.foo = 'bar';

                    return request('kv.delete', {
                        key: 'foo',
                    }).then(function(reply) {
                        assert(reply.success);
                        assert(!('foo' in api.kv.store));
                    });
                });

                it("should reply with whether the key existed", function() {
                    api.kv.store.foo = 'bar';

                    return Q.all([
                        request('kv.delete', {key: 'foo'}),
                        request('kv.delete', {key: 'bar'})
                    ]).spread(function(reply1, reply2) {
                        assert(reply1.success);
                        assert(reply1.existed);

                        assert(reply2.success);
                        assert(!reply2.existed);
                    });
                });
            });
        });
    });
});
<commit_msg>Add tests for .expire.<commit_after>var Q = require('q');
var assert = require('assert');

var vumigo = require('../../lib');
var test_utils = vumigo.test_utils;
var DummyApi = vumigo.dummy.api.DummyApi;
var DummyResourceError = vumigo.dummy.resources.DummyResourceError;

describe("kv.dummy", function() {
    var api;
    var request;

    beforeEach(function() {
        api =  new DummyApi();
        request = test_utils.requester(api);
    });

    describe("DummyKvResource", function() {
        describe(".incr", function() {
            it("should increment the value if it is an integer", function() {
                api.kv.store.foo = 2;
                assert.strictEqual(api.kv.incr('foo', 6), 8);
                assert.equal(api.kv.store.foo, 8);
            });

            it("should use 1 as the default increment amount", function() {
                api.kv.store.foo = 2;
                assert.strictEqual(api.kv.incr('foo'), 3);
                assert.equal(api.kv.store.foo, 3);
            });

            it("should initialise new keys", function() {
                assert.strictEqual(api.kv.incr('foo'), 1);
                assert.equal(api.kv.store.foo, 1);
            });

            it("should throw an error for non-integer values", function() {
                api.kv.store.foo = 'bar';

                assert.throws(
                    function() {
                        api.kv.incr('foo');
                    },
                    function(e) {
                        assert(e instanceof DummyResourceError);
                        assert.equal(
                            e.message,
                            ["Cannot increment non-integer value for key",
                             "'foo': bar"].join(' '));

                        return true;
                    });
            });

            it("should throw an error for non-integer amount", function() {
                api.kv.store.foo = 2;

                assert.throws(
                    function() {
                        api.kv.incr('foo', 'bar');
                    },
                    function(e) {
                        assert(e instanceof DummyResourceError);
                        assert.equal(
                            e.message,
                            ["Non-integer increment amount given for key",
                             "'foo': bar"].join(' '));

                        return true;
                    });
            });
        });

        describe(".expire", function() {
            it("should set the expiry if given", function() {
                assert.deepEqual(api.kv.expiry, {});
                api.kv.expire("foo", 5);
                assert.deepEqual(api.kv.expiry, {"foo": 5});
            });

            it("should unset the expiry if seconds is null", function() {
                api.kv.expiry.foo = 10;
                api.kv.expire("foo", null);
                assert.deepEqual(api.kv.expiry, {});
            });

            it("should unset the expiry if seconds is undefined", function() {
                api.kv.expiry.foo = 10;
                api.kv.expire("foo");
                assert.deepEqual(api.kv.expiry, {});
            });
        });

        describe(".handlers", function() {
            describe(".get", function() {
                it("should retrieve the value for the given key", function() {
                    api.kv.store.foo = 'bar';

                    return request('kv.get', {
                        key: 'foo'
                    }).then(function(reply) {
                        assert(reply.success);
                        assert.equal(reply.value, 'bar');
                    });
                });

                it("should return null if the key does not exist", function() {
                    return request('kv.get', {
                        key: 'foo'
                    }).then(function(reply) {
                        assert(reply.success);
                        assert.strictEqual(reply.value, null);
                    });
                });
            });

            describe(".set", function() {
                it("should set the value of the given key", function() {
                    return request('kv.set', {
                        key: 'foo',
                        value: 'bar'
                    }).then(function(reply) {
                        assert(reply.success);
                        assert.equal(api.kv.store.foo, 'bar');
                    });
                });
            });

            describe(".incr", function() {
                it("should increment the value of the given key", function() {
                    api.kv.store.foo = 2;

                    return request('kv.incr', {
                        key: 'foo',
                        amount: 6
                    }).then(function(reply) {
                        assert(reply.success);
                        assert.equal(reply.value, 8);
                        assert.equal(api.kv.store.foo, 8);
                    });
                });

                it("should use 1 as the default increment amount", function() {
                    api.kv.store.foo = 2;

                    return request('kv.incr', {
                        key: 'foo',
                    }).then(function(reply) {
                        assert(reply.success);
                        assert.equal(reply.value, 3);
                        assert.equal(api.kv.store.foo, 3);
                    });
                });

                it("should fail for non-integer keys", function() {
                    api.kv.store.foo = 'bar';

                    return request('kv.incr', {
                        key: 'foo',
                    }).then(function(reply) {
                        assert(!reply.success);
                        assert.equal(
                            reply.reason,
                            ["Cannot increment non-integer value for key",
                             "'foo': bar"].join(' '));
                    });
                });

                it("should fail for non-integer amounts", function() {
                    api.kv.store.foo = 2;

                    return request('kv.incr', {
                        key: 'foo',
                        amount: 'bar'
                    }).then(function(reply) {
                        assert(!reply.success);
                        assert.equal(
                            reply.reason,
                            ["Non-integer increment amount given for key",
                             "'foo': bar"].join(' '));
                    });
                });
            });

            describe(".delete", function() {
                it("should delete the give key from the store", function() {
                    api.kv.store.foo = 'bar';

                    return request('kv.delete', {
                        key: 'foo',
                    }).then(function(reply) {
                        assert(reply.success);
                        assert(!('foo' in api.kv.store));
                    });
                });

                it("should reply with whether the key existed", function() {
                    api.kv.store.foo = 'bar';

                    return Q.all([
                        request('kv.delete', {key: 'foo'}),
                        request('kv.delete', {key: 'bar'})
                    ]).spread(function(reply1, reply2) {
                        assert(reply1.success);
                        assert(reply1.existed);

                        assert(reply2.success);
                        assert(!reply2.existed);
                    });
                });
            });
        });
    });
});
<|endoftext|>


<commit_before>
import getPrebidPbjs from 'js/ads/prebid/getPrebidPbjs'
import { isInEuropeanUnion } from 'js/utils/client-location'
import {
  getNumberOfAdsToShow,
  getVerticalAdSizes,
  getHorizontalAdSizes,
  CONSENT_MANAGEMENT_TIMEOUT,
  VERTICAL_AD_UNIT_ID,
  VERTICAL_AD_SLOT_DOM_ID,
  SECOND_VERTICAL_AD_UNIT_ID,
  SECOND_VERTICAL_AD_SLOT_DOM_ID,
  HORIZONTAL_AD_UNIT_ID,
  HORIZONTAL_AD_SLOT_DOM_ID
} from 'js/ads/adSettings'

const getAdUnits = () => {
  const numAdsToShow = getNumberOfAdsToShow()

  // Leaderboard-style ad with all bidders
  const horizontalAdUnit = {
    code: HORIZONTAL_AD_SLOT_DOM_ID,
    mediaTypes: {
      banner: {
        sizes: getHorizontalAdSizes()
      }
    },
    bids: [
      {
        bidder: 'sonobi',
        params: {
          dom_id: HORIZONTAL_AD_SLOT_DOM_ID,
          ad_unit: HORIZONTAL_AD_UNIT_ID
        }
      },
      {
        bidder: 'pulsepoint',
        params: {
          cf: '728X90',
          cp: '560174',
          ct: '460981'
        }
      },
      {
        bidder: 'aol',
        params: {
          network: '10559.1',
          placement: '4117691',
          sizeId: '225'
        }
      },
      {
        bidder: 'sovrn',
        params: {
          tagid: '438918'
        }
      },
      {
        bidder: 'openx',
        params: {
          unit: '538658529',
          delDomain: 'tabforacause-d.openx.net'
        }
      },
      {
        bidder: 'brealtime',
        params: {
          placementId: '10955287'
        }
      },
      {
        bidder: 'rhythmone',
        params: {
          placementId: '73423'
        }
      }
    ]
  }

  // Rectangle-style ad with all bidders
  const verticalAdUnitForTwoAds = {
    code: VERTICAL_AD_SLOT_DOM_ID,
    mediaTypes: {
      banner: {
        sizes: getVerticalAdSizes()
      }
    },
    bids: [
      {
        bidder: 'sonobi',
        params: {
          dom_id: VERTICAL_AD_SLOT_DOM_ID,
          ad_unit: VERTICAL_AD_UNIT_ID
        }
      },
      {
        bidder: 'pulsepoint',
        params: {
          cf: '300X250',
          cp: '560174',
          ct: '460982'
        }
      },
      {
        bidder: 'aol',
        params: {
          network: '10559.1',
          placement: '4117692',
          sizeId: '170'
        }
      },
      {
        bidder: 'sovrn',
        params: {
          tagid: '438916'
        }
      },
      {
        bidder: 'openx',
        params: {
          unit: '538658529',
          delDomain: 'tabforacause-d.openx.net'
        }
      },
      {
        bidder: 'brealtime',
        params: {
          placementId: '10955690'
        }
      },
      {
        bidder: 'rhythmone',
        params: {
          placementId: '73423'
        }
      }
    ]
  }

  // Rectangle-style ad with some bidders for when
  // we are showing three ads
  const firstVerticalAdUnitForThreeAds = verticalAdUnitForTwoAds

  // Second rectangle-style ad with some bidders for when
  // we are showing three ads
  const secondVerticalAdUnitForThreeAds = {
    code: SECOND_VERTICAL_AD_SLOT_DOM_ID,
    mediaTypes: {
      banner: {
        sizes: getVerticalAdSizes()
      }
    },
    bids: [
      {
        bidder: 'sonobi',
        params: {
          dom_id: SECOND_VERTICAL_AD_SLOT_DOM_ID,
          ad_unit: SECOND_VERTICAL_AD_UNIT_ID
        }
      },
      {
        bidder: 'pulsepoint',
        params: {
          cf: '300X250',
          cp: '560174',
          ct: '665497'
        }
      },
      {
        bidder: 'aol',
        params: {
          network: '10559.1',
          placement: '4997858',
          sizeId: '170'
        }
      },
      {
        bidder: 'sovrn',
        params: {
          tagid: '589343'
        }
      },
      {
        bidder: 'openx',
        params: {
          unit: '538658529',
          delDomain: 'tabforacause-d.openx.net'
        }
      },
      // {
      //   bidder: 'brealtime',
      //   params: {
      //     placementId: 'TODO'
      //   }
      // },
      {
        bidder: 'rhythmone',
        params: {
          placementId: '73423'
        }
      }
    ]
  }

  if (!numAdsToShow) {
    return []
  } else if (numAdsToShow === 1) {
    return [horizontalAdUnit]
  } else if (numAdsToShow === 2) {
    return [
      horizontalAdUnit,
      verticalAdUnitForTwoAds
    ]
  } else {
    return [
      horizontalAdUnit,
      firstVerticalAdUnitForThreeAds,
      secondVerticalAdUnitForThreeAds
    ]
  }
}

/**
 * Return a promise that resolves when the Prebid auction is
 * complete. For a setup example, see:
 * http://prebid.org/dev-docs/examples/basic-example.html
 * @return {Promise<undefined>} Resolves when the Prebid
 *   auction completes (either all bids back or bid requests
 *   time out).
 */
export default () => {
  return new Promise(async (resolve, reject) => {
    // Determine if the user is in the EU, which may affect the
    // ads we show.
    var isInEU
    try {
      isInEU = await isInEuropeanUnion()
    } catch (e) {
      isInEU = false
    }
    const requiresConsentManagement = !!isInEU

    const adUnits = getAdUnits()

    const pbjs = getPrebidPbjs()

    pbjs.que.push(() => {
      // http://prebid.org/dev-docs/publisher-api-reference.html#module_pbjs.setConfig
      const protocol = process.env.WEBSITE_PROTOCOL ? process.env.WEBSITE_PROTOCOL : 'https'
      const publisherDomain = `${protocol}://${process.env.WEBSITE_DOMAIN}`
      const pagePath = window.location.pathname
      pbjs.setConfig({
        // bidderTimeout: 700 // default
        publisherDomain: publisherDomain, // Used for SafeFrame creative
        // Overrides the page URL adapters should use. Otherwise, some adapters
        // will use the current frame's URL while others use the top frame URL.
        // Only some adapters use this setting as of May 2018.
        // https://github.com/prebid/Prebid.js/issues/1882
        pageUrl: `${publisherDomain}${pagePath}`,
        // GDPR consent. Only enable the consentManagement module here
        // if consent is required, to avoid the unnecessary delay of calling
        // the CMP.
        // http://prebid.org/dev-docs/modules/consentManagement.html
        ...(requiresConsentManagement && {
          consentManagement: {
            cmpApi: 'iab',
            timeout: CONSENT_MANAGEMENT_TIMEOUT,
            allowAuctionWithoutConsent: true
          }
        })
      })

      pbjs.addAdUnits(adUnits)

      // Note: brealtime is automatically aliased by the
      // AppNexus bid adapter.
      pbjs.bidderSettings = {
        aol: {
        // AOL sends gross CPM.
          bidCpmAdjustment: function (bidCpm) {
            return bidCpm * 0.80
          }
        }
      }

      pbjs.requestBids({
        bidsBackHandler: handleAuctionEnd
      })
    })

    function handleAuctionEnd () {
      resolve()
    }
  })
}
<commit_msg>Add note to change brealtime to emx_digital<commit_after>
import getPrebidPbjs from 'js/ads/prebid/getPrebidPbjs'
import { isInEuropeanUnion } from 'js/utils/client-location'
import {
  getNumberOfAdsToShow,
  getVerticalAdSizes,
  getHorizontalAdSizes,
  CONSENT_MANAGEMENT_TIMEOUT,
  VERTICAL_AD_UNIT_ID,
  VERTICAL_AD_SLOT_DOM_ID,
  SECOND_VERTICAL_AD_UNIT_ID,
  SECOND_VERTICAL_AD_SLOT_DOM_ID,
  HORIZONTAL_AD_UNIT_ID,
  HORIZONTAL_AD_SLOT_DOM_ID
} from 'js/ads/adSettings'

const getAdUnits = () => {
  const numAdsToShow = getNumberOfAdsToShow()

  // Leaderboard-style ad with all bidders
  const horizontalAdUnit = {
    code: HORIZONTAL_AD_SLOT_DOM_ID,
    mediaTypes: {
      banner: {
        sizes: getHorizontalAdSizes()
      }
    },
    bids: [
      {
        bidder: 'sonobi',
        params: {
          dom_id: HORIZONTAL_AD_SLOT_DOM_ID,
          ad_unit: HORIZONTAL_AD_UNIT_ID
        }
      },
      {
        bidder: 'pulsepoint',
        params: {
          cf: '728X90',
          cp: '560174',
          ct: '460981'
        }
      },
      {
        bidder: 'aol',
        params: {
          network: '10559.1',
          placement: '4117691',
          sizeId: '225'
        }
      },
      {
        bidder: 'sovrn',
        params: {
          tagid: '438918'
        }
      },
      {
        bidder: 'openx',
        params: {
          unit: '538658529',
          delDomain: 'tabforacause-d.openx.net'
        }
      },
      // TODO: update to emx_digital
      // EMX Digitial was formerly brealtime.
      // http://prebid.org/dev-docs/bidders.html#emx_digital
      {
        bidder: 'brealtime',
        params: {
          placementId: '10955287'
        }
      },
      {
        bidder: 'rhythmone',
        params: {
          placementId: '73423'
        }
      }
    ]
  }

  // Rectangle-style ad with all bidders
  const verticalAdUnitForTwoAds = {
    code: VERTICAL_AD_SLOT_DOM_ID,
    mediaTypes: {
      banner: {
        sizes: getVerticalAdSizes()
      }
    },
    bids: [
      {
        bidder: 'sonobi',
        params: {
          dom_id: VERTICAL_AD_SLOT_DOM_ID,
          ad_unit: VERTICAL_AD_UNIT_ID
        }
      },
      {
        bidder: 'pulsepoint',
        params: {
          cf: '300X250',
          cp: '560174',
          ct: '460982'
        }
      },
      {
        bidder: 'aol',
        params: {
          network: '10559.1',
          placement: '4117692',
          sizeId: '170'
        }
      },
      {
        bidder: 'sovrn',
        params: {
          tagid: '438916'
        }
      },
      {
        bidder: 'openx',
        params: {
          unit: '538658529',
          delDomain: 'tabforacause-d.openx.net'
        }
      },
      // TODO: update to emx_digital
      {
        bidder: 'brealtime',
        params: {
          placementId: '10955690'
        }
      },
      {
        bidder: 'rhythmone',
        params: {
          placementId: '73423'
        }
      }
    ]
  }

  // Rectangle-style ad with some bidders for when
  // we are showing three ads
  const firstVerticalAdUnitForThreeAds = verticalAdUnitForTwoAds

  // Second rectangle-style ad with some bidders for when
  // we are showing three ads
  const secondVerticalAdUnitForThreeAds = {
    code: SECOND_VERTICAL_AD_SLOT_DOM_ID,
    mediaTypes: {
      banner: {
        sizes: getVerticalAdSizes()
      }
    },
    bids: [
      {
        bidder: 'sonobi',
        params: {
          dom_id: SECOND_VERTICAL_AD_SLOT_DOM_ID,
          ad_unit: SECOND_VERTICAL_AD_UNIT_ID
        }
      },
      {
        bidder: 'pulsepoint',
        params: {
          cf: '300X250',
          cp: '560174',
          ct: '665497'
        }
      },
      {
        bidder: 'aol',
        params: {
          network: '10559.1',
          placement: '4997858',
          sizeId: '170'
        }
      },
      {
        bidder: 'sovrn',
        params: {
          tagid: '589343'
        }
      },
      {
        bidder: 'openx',
        params: {
          unit: '538658529',
          delDomain: 'tabforacause-d.openx.net'
        }
      },
      // {
      //   bidder: 'emx_digital',
      //   params: {
      //     tagid: 'TODO'
      //   }
      // },
      {
        bidder: 'rhythmone',
        params: {
          placementId: '73423'
        }
      }
    ]
  }

  if (!numAdsToShow) {
    return []
  } else if (numAdsToShow === 1) {
    return [horizontalAdUnit]
  } else if (numAdsToShow === 2) {
    return [
      horizontalAdUnit,
      verticalAdUnitForTwoAds
    ]
  } else {
    return [
      horizontalAdUnit,
      firstVerticalAdUnitForThreeAds,
      secondVerticalAdUnitForThreeAds
    ]
  }
}

/**
 * Return a promise that resolves when the Prebid auction is
 * complete. For a setup example, see:
 * http://prebid.org/dev-docs/examples/basic-example.html
 * @return {Promise<undefined>} Resolves when the Prebid
 *   auction completes (either all bids back or bid requests
 *   time out).
 */
export default () => {
  return new Promise(async (resolve, reject) => {
    // Determine if the user is in the EU, which may affect the
    // ads we show.
    var isInEU
    try {
      isInEU = await isInEuropeanUnion()
    } catch (e) {
      isInEU = false
    }
    const requiresConsentManagement = !!isInEU

    const adUnits = getAdUnits()

    const pbjs = getPrebidPbjs()

    pbjs.que.push(() => {
      // http://prebid.org/dev-docs/publisher-api-reference.html#module_pbjs.setConfig
      const protocol = process.env.WEBSITE_PROTOCOL ? process.env.WEBSITE_PROTOCOL : 'https'
      const publisherDomain = `${protocol}://${process.env.WEBSITE_DOMAIN}`
      const pagePath = window.location.pathname
      pbjs.setConfig({
        // bidderTimeout: 700 // default
        publisherDomain: publisherDomain, // Used for SafeFrame creative
        // Overrides the page URL adapters should use. Otherwise, some adapters
        // will use the current frame's URL while others use the top frame URL.
        // Only some adapters use this setting as of May 2018.
        // https://github.com/prebid/Prebid.js/issues/1882
        pageUrl: `${publisherDomain}${pagePath}`,
        // GDPR consent. Only enable the consentManagement module here
        // if consent is required, to avoid the unnecessary delay of calling
        // the CMP.
        // http://prebid.org/dev-docs/modules/consentManagement.html
        ...(requiresConsentManagement && {
          consentManagement: {
            cmpApi: 'iab',
            timeout: CONSENT_MANAGEMENT_TIMEOUT,
            allowAuctionWithoutConsent: true
          }
        })
      })

      pbjs.addAdUnits(adUnits)

      // Note: brealtime is automatically aliased by the
      // AppNexus bid adapter.
      pbjs.bidderSettings = {
        aol: {
        // AOL sends gross CPM.
          bidCpmAdjustment: function (bidCpm) {
            return bidCpm * 0.80
          }
        }
      }

      pbjs.requestBids({
        bidsBackHandler: handleAuctionEnd
      })
    })

    function handleAuctionEnd () {
      resolve()
    }
  })
}
<|endoftext|>


<commit_before>/* @flow */

import React from 'react'
import PropTypes from 'prop-types'
import ReactNative, {
  Keyboard,
  Platform,
  UIManager,
  TextInput,
  findNodeHandle,
  Animated
} from 'react-native'
import { isIphoneX } from 'react-native-iphone-x-helper'
import type { KeyboardAwareInterface } from './KeyboardAwareInterface'

const _KAM_DEFAULT_TAB_BAR_HEIGHT: number = isIphoneX() ? 83 : 49
const _KAM_KEYBOARD_OPENING_TIME: number = 250
const _KAM_EXTRA_HEIGHT: number = 75

const supportedKeyboardEvents = [
  'keyboardWillShow',
  'keyboardDidShow',
  'keyboardWillHide',
  'keyboardDidHide',
  'keyboardWillChangeFrame',
  'keyboardDidChangeFrame',
]
const keyboardEventToCallbackName = (eventName: string) => (
  'on' + eventName[0].toUpperCase() + eventName.substring(1)
)
const keyboardEventPropTypes = supportedKeyboardEvents.reduce(
  (acc: Object, eventName: string) => (
    { ...acc, [keyboardEventToCallbackName(eventName)]: PropTypes.func }
  ), {}
)
const keyboardAwareHOCTypeEvents = supportedKeyboardEvents.reduce(
  (acc: Object, eventName: string) => (
    { ...acc, [keyboardEventToCallbackName(eventName)]: Function }
  ), {}
)

export type KeyboardAwareHOCProps = {
  viewIsInsideTabBar?: boolean,
  resetScrollToCoords?: {
    x: number,
    y: number
  },
  enableResetScrollToCoords?: boolean,
  enableAutomaticScroll?: boolean,
  extraHeight?: number,
  extraScrollHeight?: number,
  keyboardOpeningTime?: number,
  onScroll?: Function,
  update?: Function,
  contentContainerStyle?: any,
  enableOnAndroid?: boolean,
  innerRef?: Function,
  ...keyboardAwareHOCTypeEvents
}
export type KeyboardAwareHOCState = {
  keyboardSpace: number
}

export type ElementLayout = {
  x: number,
  y: number,
  width: number,
  height: number
}

export type ContentOffset = {
  x: number,
  y: number
}

export type ScrollPosition = {
  x: number,
  y: number,
  animated: boolean
}

export type ScrollIntoViewOptions = ?{
  getScrollPosition?: (
    parentLayout: ElementLayout,
    childLayout: ElementLayout,
    contentOffset: ContentOffset
  ) => ScrollPosition
}

function getDisplayName(WrappedComponent: React$Component) {
  return WrappedComponent.displayName || WrappedComponent.name || 'Component'
}

function listenToKeyboardEvents(ScrollableComponent: React$Component) {
  return class extends React.Component<
    KeyboardAwareHOCProps,
    KeyboardAwareHOCState
    > implements KeyboardAwareInterface {
    _rnkasv_keyboardView: any
    keyboardWillShowEvent: ?Function
    keyboardWillHideEvent: ?Function
    position: ContentOffset
    defaultResetScrollToCoords: ?{ x: number, y: number }
    resetCoords: ?{ x: number, y: number }
    mountedComponent: boolean
    handleOnScroll: Function
    state: KeyboardAwareHOCState
    static displayName = `KeyboardAware${getDisplayName(ScrollableComponent)}`

    static propTypes = {
      viewIsInsideTabBar: PropTypes.bool,
      resetScrollToCoords: PropTypes.shape({
        x: PropTypes.number.isRequired,
        y: PropTypes.number.isRequired
      }),
      enableResetScrollToCoords: PropTypes.bool,
      enableAutomaticScroll: PropTypes.bool,
      extraHeight: PropTypes.number,
      extraScrollHeight: PropTypes.number,
      keyboardOpeningTime: PropTypes.number,
      onScroll: PropTypes.func,
      update: PropTypes.func,
      contentContainerStyle: PropTypes.any,
      enableOnAndroid: PropTypes.bool,
      innerRef: PropTypes.func,
      ...keyboardEventPropTypes
    }

    static defaultProps = {
      enableAutomaticScroll: true,
      extraHeight: _KAM_EXTRA_HEIGHT,
      extraScrollHeight: 0,
      enableResetScrollToCoords: true,
      keyboardOpeningTime: _KAM_KEYBOARD_OPENING_TIME,
      viewIsInsideTabBar: false
    }

    constructor(props: KeyboardAwareHOCProps) {
      super(props)
      this.keyboardWillShowEvent = undefined
      this.keyboardWillHideEvent = undefined
      this.callbacks = {}
      this.position = { x: 0, y: 0 }
      this.defaultResetScrollToCoords = null
      const keyboardSpace: number = props.viewIsInsideTabBar
        ? _KAM_DEFAULT_TAB_BAR_HEIGHT
        : 0
      this.state = { keyboardSpace }
    }

    componentDidMount() {
      this.mountedComponent = true
      // Keyboard events
      if (Platform.OS === 'ios') {
        this.keyboardWillShowEvent = Keyboard.addListener(
          'keyboardWillShow',
          this._updateKeyboardSpace
        )
        this.keyboardWillHideEvent = Keyboard.addListener(
          'keyboardWillHide',
          this._resetKeyboardSpace
        )
      } else if (Platform.OS === 'android' && this.props.enableOnAndroid) {
        this.keyboardWillShowEvent = Keyboard.addListener(
          'keyboardDidShow',
          this._updateKeyboardSpace
        )
        this.keyboardWillHideEvent = Keyboard.addListener(
          'keyboardDidHide',
          this._resetKeyboardSpace
        )
      }

      supportedKeyboardEvents.forEach((eventName: string) => {
        const callbackName = keyboardEventToCallbackName(eventName)
        if (this.props[callbackName]) {
          this.callbacks[eventName] = Keyboard.addListener(eventName, this.props[callbackName])
        }
      })
    }

    componentWillReceiveProps(nextProps: KeyboardAwareHOCProps) {
      if (nextProps.viewIsInsideTabBar !== this.props.viewIsInsideTabBar) {
        const keyboardSpace: number = nextProps.viewIsInsideTabBar
          ? _KAM_DEFAULT_TAB_BAR_HEIGHT
          : 0
        if (this.state.keyboardSpace !== keyboardSpace) {
          this.setState({ keyboardSpace })
        }
      }
    }

    componentWillUnmount() {
      this.mountedComponent = false
      this.keyboardWillShowEvent && this.keyboardWillShowEvent.remove()
      this.keyboardWillHideEvent && this.keyboardWillHideEvent.remove()
      Object.values(this.callbacks).forEach((callback: Object) => callback.remove())
    }

    getScrollResponder = () => {
      return (
        this._rnkasv_keyboardView &&
        this._rnkasv_keyboardView.getScrollResponder()
      )
    }

    scrollToPosition = (x: number, y: number, animated: boolean = true) => {
      const responder = this.getScrollResponder()
      responder && responder.scrollResponderScrollTo({ x, y, animated })
    }

    scrollToEnd = (animated?: boolean = true) => {
      const responder = this.getScrollResponder()
      responder && responder.scrollResponderScrollToEnd({ animated })
    }

    scrollForExtraHeightOnAndroid = (extraHeight: number) => {
      this.scrollToPosition(0, this.position.y + extraHeight, true)
    }

    /**
     * @param keyboardOpeningTime: takes a different keyboardOpeningTime in consideration.
     * @param extraHeight: takes an extra height in consideration.
     */
    scrollToFocusedInput = (
      reactNode: any,
      extraHeight?: number,
      keyboardOpeningTime?: number
    ) => {
      if (extraHeight === undefined) {
        extraHeight = this.props.extraHeight || 0
      }
      if (keyboardOpeningTime === undefined) {
        keyboardOpeningTime = this.props.keyboardOpeningTime || 0
      }
      setTimeout(() => {
        if (!this.mountedComponent) {
          return
        }
        const responder = this.getScrollResponder()
        responder &&
          responder.scrollResponderScrollNativeHandleToKeyboard(
            reactNode,
            extraHeight,
            true
          )
      }, keyboardOpeningTime)
    }

    scrollIntoView = async (
      element: React.Element<*>,
      options: ScrollIntoViewOptions = {}
    ) => {
      if (!this._rnkasv_keyboardView || !element) {
        return
      }

      const [
        parentLayout,
        childLayout
      ] = await Promise.all([
        this._measureElement(this._rnkasv_keyboardView),
        this._measureElement(element)
      ])

      const getScrollPosition = options.getScrollPosition || this._defaultGetScrollPosition
      const { x, y, animated } = getScrollPosition(parentLayout, childLayout, this.position)
      this.scrollToPosition(x, y, animated)
    }

    _defaultGetScrollPosition = (
      parentLayout: ElementLayout,
      childLayout: ElementLayout,
      contentOffset: ContentOffset
    ): ScrollPosition => {
      return {
        x: 0,
        y: Math.max(0, childLayout.y - parentLayout.y + contentOffset.y),
        animated: true,
      }
    }

    _measureElement = (element: React.Element<*>): Promise<ElementLayout> => {
      const node = findNodeHandle(element)
      return new Promise((resolve: (ElementLayout) => void) => {
        UIManager.measureInWindow(node, (x: number, y: number, width: number, height: number) => {
          resolve({ x, y, width, height })
        })
      })
    }

    // Keyboard actions
    _updateKeyboardSpace = (frames: Object) => {
      let keyboardSpace: number = frames.endCoordinates.height + this.props.extraScrollHeight
      if (this.props.viewIsInsideTabBar) {
        keyboardSpace -= _KAM_DEFAULT_TAB_BAR_HEIGHT
      }
      this.setState({ keyboardSpace })
      // Automatically scroll to focused TextInput
      if (this.props.enableAutomaticScroll) {
        const currentlyFocusedField = TextInput.State.currentlyFocusedField()
        const responder = this.getScrollResponder()
        if (!currentlyFocusedField || !responder) {
          return
        }
        UIManager.viewIsDescendantOf(
          currentlyFocusedField,
          responder.getInnerViewNode(),
          (isAncestor: boolean) => {
            if (isAncestor) {
              // Check if the TextInput will be hidden by the keyboard
              UIManager.measureInWindow(
                currentlyFocusedField,
                (x: number, y: number, width: number, height: number) => {
                  const textInputBottomPosition = y + height
                  const keyboardPosition = frames.endCoordinates.screenY
                  const totalExtraHeight =
                    this.props.extraScrollHeight + this.props.extraHeight
                  if (Platform.OS === 'ios') {
                    if (
                      textInputBottomPosition >
                      keyboardPosition - totalExtraHeight
                    ) {
                      this._scrollToFocusedInputWithNodeHandle(
                        currentlyFocusedField
                      )
                    }
                  } else {
                    // On android, the system would scroll the text input just
                    // above the keyboard so we just neet to scroll the extra
                    // height part
                    if (textInputBottomPosition > keyboardPosition) {
                      // Since the system already scrolled the whole view up
                      // we should reduce that amount
                      keyboardSpace =
                        keyboardSpace -
                        (textInputBottomPosition - keyboardPosition)
                      this.setState({ keyboardSpace })
                      this.scrollForExtraHeightOnAndroid(totalExtraHeight)
                    } else if (
                      textInputBottomPosition >
                      keyboardPosition - totalExtraHeight
                    ) {
                      this.scrollForExtraHeightOnAndroid(
                        totalExtraHeight -
                          (keyboardPosition - textInputBottomPosition)
                      )
                    }
                  }
                }
              )
            }
          }
        )
      }
      if (!this.resetCoords) {
        if (!this.defaultResetScrollToCoords) {
          this.defaultResetScrollToCoords = this.position
        }
      }
    }

    _resetKeyboardSpace = () => {
      const keyboardSpace: number = this.props.viewIsInsideTabBar
        ? _KAM_DEFAULT_TAB_BAR_HEIGHT + this.props.extraScrollHeight || 0
        : this.props.extraScrollHeight || 0
      this.setState({ keyboardSpace })
      // Reset scroll position after keyboard dismissal
      if (this.props.enableResetScrollToCoords === false) {
        this.defaultResetScrollToCoords = null
        return
      } else if (this.resetCoords) {
        this.scrollToPosition(this.resetCoords.x, this.resetCoords.y, true)
      } else {
        if (this.defaultResetScrollToCoords) {
          this.scrollToPosition(
            this.defaultResetScrollToCoords.x,
            this.defaultResetScrollToCoords.y,
            true
          )
          this.defaultResetScrollToCoords = null
        } else {
          this.scrollToPosition(0, 0, true)
        }
      }
    }

    _scrollToFocusedInputWithNodeHandle = (
      nodeID: number,
      extraHeight?: number,
      keyboardOpeningTime?: number
    ) => {
      if (extraHeight === undefined) {
        extraHeight = this.props.extraHeight
      }
      const reactNode = ReactNative.findNodeHandle(nodeID)
      this.scrollToFocusedInput(
        reactNode,
        extraHeight + this.props.extraScrollHeight,
        keyboardOpeningTime !== undefined
          ? keyboardOpeningTime
          : this.props.keyboardOpeningTime || 0
      )
    }

    _handleOnScroll = (
      e: SyntheticEvent<*> & { nativeEvent: { contentOffset: number } }
    ) => {
      this.position = e.nativeEvent.contentOffset
    }

    _handleRef = (ref: React.Component<*>) => {
      this._rnkasv_keyboardView = ref.getNode ? ref.getNode() : ref
      if (this.props.innerRef) {
        this.props.innerRef(this._rnkasv_keyboardView)
      }
    }

    update = () => {
      const currentlyFocusedField = TextInput.State.currentlyFocusedField()
      const responder = this.getScrollResponder()

      if (!currentlyFocusedField || !responder) {
        return
      }

      this._scrollToFocusedInputWithNodeHandle(
        currentlyFocusedField
      )
    }

    render() {
      const { enableOnAndroid, contentContainerStyle, onScroll } = this.props
      let newContentContainerStyle
      if (Platform.OS === 'android' && enableOnAndroid) {
        newContentContainerStyle = [].concat(contentContainerStyle).concat({
          paddingBottom:
            ((contentContainerStyle || {}).paddingBottom || 0) +
            this.state.keyboardSpace
        })
      }
      return (
        <ScrollableComponent
          ref={this._handleRef}
          keyboardDismissMode='interactive'
          contentInset={{ bottom: this.state.keyboardSpace }}
          automaticallyAdjustContentInsets={false}
          showsVerticalScrollIndicator={true}
          scrollEventThrottle={1}
          {...this.props}
          contentContainerStyle={
            newContentContainerStyle || contentContainerStyle
          }
          keyboardSpace={this.state.keyboardSpace}
          getScrollResponder={this.getScrollResponder}
          scrollToPosition={this.scrollToPosition}
          scrollToEnd={this.scrollToEnd}
          scrollForExtraHeightOnAndroid={this.scrollForExtraHeightOnAndroid}
          scrollToFocusedInput={this.scrollToFocusedInput}
          scrollIntoView={this.scrollIntoView}
          resetKeyboardSpace={this._resetKeyboardSpace}
          handleOnScroll={this._handleOnScroll}
          update={this.update}
          onScroll={Animated.forkEvent(onScroll,this._handleOnScroll)}
        />
      )
    }
  }
}

export default listenToKeyboardEvents
<commit_msg>Fix bug where ref is null<commit_after>/* @flow */

import React from 'react'
import PropTypes from 'prop-types'
import ReactNative, {
  Keyboard,
  Platform,
  UIManager,
  TextInput,
  findNodeHandle,
  Animated
} from 'react-native'
import { isIphoneX } from 'react-native-iphone-x-helper'
import type { KeyboardAwareInterface } from './KeyboardAwareInterface'

const _KAM_DEFAULT_TAB_BAR_HEIGHT: number = isIphoneX() ? 83 : 49
const _KAM_KEYBOARD_OPENING_TIME: number = 250
const _KAM_EXTRA_HEIGHT: number = 75

const supportedKeyboardEvents = [
  'keyboardWillShow',
  'keyboardDidShow',
  'keyboardWillHide',
  'keyboardDidHide',
  'keyboardWillChangeFrame',
  'keyboardDidChangeFrame',
]
const keyboardEventToCallbackName = (eventName: string) => (
  'on' + eventName[0].toUpperCase() + eventName.substring(1)
)
const keyboardEventPropTypes = supportedKeyboardEvents.reduce(
  (acc: Object, eventName: string) => (
    { ...acc, [keyboardEventToCallbackName(eventName)]: PropTypes.func }
  ), {}
)
const keyboardAwareHOCTypeEvents = supportedKeyboardEvents.reduce(
  (acc: Object, eventName: string) => (
    { ...acc, [keyboardEventToCallbackName(eventName)]: Function }
  ), {}
)

export type KeyboardAwareHOCProps = {
  viewIsInsideTabBar?: boolean,
  resetScrollToCoords?: {
    x: number,
    y: number
  },
  enableResetScrollToCoords?: boolean,
  enableAutomaticScroll?: boolean,
  extraHeight?: number,
  extraScrollHeight?: number,
  keyboardOpeningTime?: number,
  onScroll?: Function,
  update?: Function,
  contentContainerStyle?: any,
  enableOnAndroid?: boolean,
  innerRef?: Function,
  ...keyboardAwareHOCTypeEvents
}
export type KeyboardAwareHOCState = {
  keyboardSpace: number
}

export type ElementLayout = {
  x: number,
  y: number,
  width: number,
  height: number
}

export type ContentOffset = {
  x: number,
  y: number
}

export type ScrollPosition = {
  x: number,
  y: number,
  animated: boolean
}

export type ScrollIntoViewOptions = ?{
  getScrollPosition?: (
    parentLayout: ElementLayout,
    childLayout: ElementLayout,
    contentOffset: ContentOffset
  ) => ScrollPosition
}

function getDisplayName(WrappedComponent: React$Component) {
  return WrappedComponent.displayName || WrappedComponent.name || 'Component'
}

function listenToKeyboardEvents(ScrollableComponent: React$Component) {
  return class extends React.Component<
    KeyboardAwareHOCProps,
    KeyboardAwareHOCState
    > implements KeyboardAwareInterface {
    _rnkasv_keyboardView: any
    keyboardWillShowEvent: ?Function
    keyboardWillHideEvent: ?Function
    position: ContentOffset
    defaultResetScrollToCoords: ?{ x: number, y: number }
    resetCoords: ?{ x: number, y: number }
    mountedComponent: boolean
    handleOnScroll: Function
    state: KeyboardAwareHOCState
    static displayName = `KeyboardAware${getDisplayName(ScrollableComponent)}`

    static propTypes = {
      viewIsInsideTabBar: PropTypes.bool,
      resetScrollToCoords: PropTypes.shape({
        x: PropTypes.number.isRequired,
        y: PropTypes.number.isRequired
      }),
      enableResetScrollToCoords: PropTypes.bool,
      enableAutomaticScroll: PropTypes.bool,
      extraHeight: PropTypes.number,
      extraScrollHeight: PropTypes.number,
      keyboardOpeningTime: PropTypes.number,
      onScroll: PropTypes.func,
      update: PropTypes.func,
      contentContainerStyle: PropTypes.any,
      enableOnAndroid: PropTypes.bool,
      innerRef: PropTypes.func,
      ...keyboardEventPropTypes
    }

    static defaultProps = {
      enableAutomaticScroll: true,
      extraHeight: _KAM_EXTRA_HEIGHT,
      extraScrollHeight: 0,
      enableResetScrollToCoords: true,
      keyboardOpeningTime: _KAM_KEYBOARD_OPENING_TIME,
      viewIsInsideTabBar: false
    }

    constructor(props: KeyboardAwareHOCProps) {
      super(props)
      this.keyboardWillShowEvent = undefined
      this.keyboardWillHideEvent = undefined
      this.callbacks = {}
      this.position = { x: 0, y: 0 }
      this.defaultResetScrollToCoords = null
      const keyboardSpace: number = props.viewIsInsideTabBar
        ? _KAM_DEFAULT_TAB_BAR_HEIGHT
        : 0
      this.state = { keyboardSpace }
    }

    componentDidMount() {
      this.mountedComponent = true
      // Keyboard events
      if (Platform.OS === 'ios') {
        this.keyboardWillShowEvent = Keyboard.addListener(
          'keyboardWillShow',
          this._updateKeyboardSpace
        )
        this.keyboardWillHideEvent = Keyboard.addListener(
          'keyboardWillHide',
          this._resetKeyboardSpace
        )
      } else if (Platform.OS === 'android' && this.props.enableOnAndroid) {
        this.keyboardWillShowEvent = Keyboard.addListener(
          'keyboardDidShow',
          this._updateKeyboardSpace
        )
        this.keyboardWillHideEvent = Keyboard.addListener(
          'keyboardDidHide',
          this._resetKeyboardSpace
        )
      }

      supportedKeyboardEvents.forEach((eventName: string) => {
        const callbackName = keyboardEventToCallbackName(eventName)
        if (this.props[callbackName]) {
          this.callbacks[eventName] = Keyboard.addListener(eventName, this.props[callbackName])
        }
      })
    }

    componentWillReceiveProps(nextProps: KeyboardAwareHOCProps) {
      if (nextProps.viewIsInsideTabBar !== this.props.viewIsInsideTabBar) {
        const keyboardSpace: number = nextProps.viewIsInsideTabBar
          ? _KAM_DEFAULT_TAB_BAR_HEIGHT
          : 0
        if (this.state.keyboardSpace !== keyboardSpace) {
          this.setState({ keyboardSpace })
        }
      }
    }

    componentWillUnmount() {
      this.mountedComponent = false
      this.keyboardWillShowEvent && this.keyboardWillShowEvent.remove()
      this.keyboardWillHideEvent && this.keyboardWillHideEvent.remove()
      Object.values(this.callbacks).forEach((callback: Object) => callback.remove())
    }

    getScrollResponder = () => {
      return (
        this._rnkasv_keyboardView &&
        this._rnkasv_keyboardView.getScrollResponder()
      )
    }

    scrollToPosition = (x: number, y: number, animated: boolean = true) => {
      const responder = this.getScrollResponder()
      responder && responder.scrollResponderScrollTo({ x, y, animated })
    }

    scrollToEnd = (animated?: boolean = true) => {
      const responder = this.getScrollResponder()
      responder && responder.scrollResponderScrollToEnd({ animated })
    }

    scrollForExtraHeightOnAndroid = (extraHeight: number) => {
      this.scrollToPosition(0, this.position.y + extraHeight, true)
    }

    /**
     * @param keyboardOpeningTime: takes a different keyboardOpeningTime in consideration.
     * @param extraHeight: takes an extra height in consideration.
     */
    scrollToFocusedInput = (
      reactNode: any,
      extraHeight?: number,
      keyboardOpeningTime?: number
    ) => {
      if (extraHeight === undefined) {
        extraHeight = this.props.extraHeight || 0
      }
      if (keyboardOpeningTime === undefined) {
        keyboardOpeningTime = this.props.keyboardOpeningTime || 0
      }
      setTimeout(() => {
        if (!this.mountedComponent) {
          return
        }
        const responder = this.getScrollResponder()
        responder &&
          responder.scrollResponderScrollNativeHandleToKeyboard(
            reactNode,
            extraHeight,
            true
          )
      }, keyboardOpeningTime)
    }

    scrollIntoView = async (
      element: React.Element<*>,
      options: ScrollIntoViewOptions = {}
    ) => {
      if (!this._rnkasv_keyboardView || !element) {
        return
      }

      const [
        parentLayout,
        childLayout
      ] = await Promise.all([
        this._measureElement(this._rnkasv_keyboardView),
        this._measureElement(element)
      ])

      const getScrollPosition = options.getScrollPosition || this._defaultGetScrollPosition
      const { x, y, animated } = getScrollPosition(parentLayout, childLayout, this.position)
      this.scrollToPosition(x, y, animated)
    }

    _defaultGetScrollPosition = (
      parentLayout: ElementLayout,
      childLayout: ElementLayout,
      contentOffset: ContentOffset
    ): ScrollPosition => {
      return {
        x: 0,
        y: Math.max(0, childLayout.y - parentLayout.y + contentOffset.y),
        animated: true,
      }
    }

    _measureElement = (element: React.Element<*>): Promise<ElementLayout> => {
      const node = findNodeHandle(element)
      return new Promise((resolve: (ElementLayout) => void) => {
        UIManager.measureInWindow(node, (x: number, y: number, width: number, height: number) => {
          resolve({ x, y, width, height })
        })
      })
    }

    // Keyboard actions
    _updateKeyboardSpace = (frames: Object) => {
      let keyboardSpace: number = frames.endCoordinates.height + this.props.extraScrollHeight
      if (this.props.viewIsInsideTabBar) {
        keyboardSpace -= _KAM_DEFAULT_TAB_BAR_HEIGHT
      }
      this.setState({ keyboardSpace })
      // Automatically scroll to focused TextInput
      if (this.props.enableAutomaticScroll) {
        const currentlyFocusedField = TextInput.State.currentlyFocusedField()
        const responder = this.getScrollResponder()
        if (!currentlyFocusedField || !responder) {
          return
        }
        UIManager.viewIsDescendantOf(
          currentlyFocusedField,
          responder.getInnerViewNode(),
          (isAncestor: boolean) => {
            if (isAncestor) {
              // Check if the TextInput will be hidden by the keyboard
              UIManager.measureInWindow(
                currentlyFocusedField,
                (x: number, y: number, width: number, height: number) => {
                  const textInputBottomPosition = y + height
                  const keyboardPosition = frames.endCoordinates.screenY
                  const totalExtraHeight =
                    this.props.extraScrollHeight + this.props.extraHeight
                  if (Platform.OS === 'ios') {
                    if (
                      textInputBottomPosition >
                      keyboardPosition - totalExtraHeight
                    ) {
                      this._scrollToFocusedInputWithNodeHandle(
                        currentlyFocusedField
                      )
                    }
                  } else {
                    // On android, the system would scroll the text input just
                    // above the keyboard so we just neet to scroll the extra
                    // height part
                    if (textInputBottomPosition > keyboardPosition) {
                      // Since the system already scrolled the whole view up
                      // we should reduce that amount
                      keyboardSpace =
                        keyboardSpace -
                        (textInputBottomPosition - keyboardPosition)
                      this.setState({ keyboardSpace })
                      this.scrollForExtraHeightOnAndroid(totalExtraHeight)
                    } else if (
                      textInputBottomPosition >
                      keyboardPosition - totalExtraHeight
                    ) {
                      this.scrollForExtraHeightOnAndroid(
                        totalExtraHeight -
                          (keyboardPosition - textInputBottomPosition)
                      )
                    }
                  }
                }
              )
            }
          }
        )
      }
      if (!this.resetCoords) {
        if (!this.defaultResetScrollToCoords) {
          this.defaultResetScrollToCoords = this.position
        }
      }
    }

    _resetKeyboardSpace = () => {
      const keyboardSpace: number = this.props.viewIsInsideTabBar
        ? _KAM_DEFAULT_TAB_BAR_HEIGHT + this.props.extraScrollHeight || 0
        : this.props.extraScrollHeight || 0
      this.setState({ keyboardSpace })
      // Reset scroll position after keyboard dismissal
      if (this.props.enableResetScrollToCoords === false) {
        this.defaultResetScrollToCoords = null
        return
      } else if (this.resetCoords) {
        this.scrollToPosition(this.resetCoords.x, this.resetCoords.y, true)
      } else {
        if (this.defaultResetScrollToCoords) {
          this.scrollToPosition(
            this.defaultResetScrollToCoords.x,
            this.defaultResetScrollToCoords.y,
            true
          )
          this.defaultResetScrollToCoords = null
        } else {
          this.scrollToPosition(0, 0, true)
        }
      }
    }

    _scrollToFocusedInputWithNodeHandle = (
      nodeID: number,
      extraHeight?: number,
      keyboardOpeningTime?: number
    ) => {
      if (extraHeight === undefined) {
        extraHeight = this.props.extraHeight
      }
      const reactNode = ReactNative.findNodeHandle(nodeID)
      this.scrollToFocusedInput(
        reactNode,
        extraHeight + this.props.extraScrollHeight,
        keyboardOpeningTime !== undefined
          ? keyboardOpeningTime
          : this.props.keyboardOpeningTime || 0
      )
    }

    _handleOnScroll = (
      e: SyntheticEvent<*> & { nativeEvent: { contentOffset: number } }
    ) => {
      this.position = e.nativeEvent.contentOffset
    }

    _handleRef = (ref: React.Component<*>) => {
      if (ref) {
        this._rnkasv_keyboardView = ref.getNode ? ref.getNode() : ref
        if (this.props.innerRef) {
          this.props.innerRef(this._rnkasv_keyboardView)
        }
      }
    }

    update = () => {
      const currentlyFocusedField = TextInput.State.currentlyFocusedField()
      const responder = this.getScrollResponder()

      if (!currentlyFocusedField || !responder) {
        return
      }

      this._scrollToFocusedInputWithNodeHandle(
        currentlyFocusedField
      )
    }

    render() {
      const { enableOnAndroid, contentContainerStyle, onScroll } = this.props
      let newContentContainerStyle
      if (Platform.OS === 'android' && enableOnAndroid) {
        newContentContainerStyle = [].concat(contentContainerStyle).concat({
          paddingBottom:
            ((contentContainerStyle || {}).paddingBottom || 0) +
            this.state.keyboardSpace
        })
      }
      return (
        <ScrollableComponent
          ref={this._handleRef}
          keyboardDismissMode='interactive'
          contentInset={{ bottom: this.state.keyboardSpace }}
          automaticallyAdjustContentInsets={false}
          showsVerticalScrollIndicator={true}
          scrollEventThrottle={1}
          {...this.props}
          contentContainerStyle={
            newContentContainerStyle || contentContainerStyle
          }
          keyboardSpace={this.state.keyboardSpace}
          getScrollResponder={this.getScrollResponder}
          scrollToPosition={this.scrollToPosition}
          scrollToEnd={this.scrollToEnd}
          scrollForExtraHeightOnAndroid={this.scrollForExtraHeightOnAndroid}
          scrollToFocusedInput={this.scrollToFocusedInput}
          scrollIntoView={this.scrollIntoView}
          resetKeyboardSpace={this._resetKeyboardSpace}
          handleOnScroll={this._handleOnScroll}
          update={this.update}
          onScroll={Animated.forkEvent(onScroll,this._handleOnScroll)}
        />
      )
    }
  }
}

export default listenToKeyboardEvents
<|endoftext|>


<commit_before>import test from 'tape'
import Immutable from 'immutable'

import reducer, { initialState } from '../../../src/client/reducers/report.js'
import {
  SET_PHOTO,
  SET_POSTING,
  SET_NAME,
  SET_LOCATION,
  SET_DESCRIPTION,
  SET_POST_RESULT
} from '../../../src/client/action_types.js'

test('report reducer: initailState', t => {
  t.equal(initialState.get('isPosting'), false, 'not posting request initially')

  t.equal(initialState.get('name'), '', 'name initially empty string')

  const location = initialState.get('location')
  t.ok(Immutable.List.isList(location), 'location is list')
  t.equal(location.size, 0, 'location list is empty')

  t.equal(initialState.get('description'), '', 'description is empty string')

  t.end()
})

test('report reducer: empty call', t => {
  const newState = reducer(undefined, {})

  t.equal(newState, initialState, 'returns initial state')

  t.end()
})

test('report: SET_POSTING', t => {
  const newState = reducer(initialState, { type: SET_POSTING })

  t.equal(newState.get('isPosting'), true, 'sets isPosting to true')

  t.end()
})

test('report: SET_POS_RESULT', t => {
  const statusCode = true
  const payload = 'payload'
  const newState = reducer(
    initialState.set('isPosting', true),
    { type: SET_POST_RESULT, statusCode, payload }
  )

  t.equal(newState.get('isPosting'), false, 'sets isPosting to false')
  t.equal(newState.get('statusCode'), statusCode, 'sets statusCode')
  t.equal(newState.get('payload'), payload, 'sets payload')

  t.end()
})

test('report: SET_PHOTO', t => {
  const photoData = 'photo data'
  const newState = reducer(
    initialState,
    { type: SET_PHOTO, photoData }
  )
  t.equal(
    photoData,
    newState.get('photoData'),
    'set photo puts photo data in state'
  )
  t.end()
})

test('report reducer: SET_NAME', t => {
  const name = 'name'
  const newState = reducer(initialState, { type: SET_NAME, name })

  t.equal(newState.get('name'), name, 'set the name')

  t.end()
})

test('report reducer: SET_LOCATION', t => {
  const location = 'location'

  const newState = reducer(
    initialState,
    { type: SET_LOCATION, location, locationIndex: 1 }
  )
  t.equal(
    newState.getIn(['location', 1]),
    location,
    'sets the location'
  )

  const finalState = reducer(
    newState,
    { type: SET_LOCATION, location, locationIndex: 0 }
  )
  t.equal(
    finalState.getIn(['location', 1]),
    '',
    'setting previous location wipes later locations'
  )

  t.end()
})

test('report reducer: SET_DESCRIPTION', t => {
  const description = 'description'
  const action = { type: SET_DESCRIPTION, description }
  const newState = reducer(initialState, action)

  t.equal(newState.get('description'), description, 'sets the description')

  t.end()
})
<commit_msg>fix SET_PHOTO reducer test<commit_after>import test from 'tape'
import Immutable from 'immutable'

import reducer, { initialState } from '../../../src/client/reducers/report.js'
import {
  SET_PHOTO,
  SET_POSTING,
  SET_NAME,
  SET_LOCATION,
  SET_DESCRIPTION,
  SET_POST_RESULT
} from '../../../src/client/action_types.js'

test('report reducer: initailState', t => {
  t.equal(initialState.get('isPosting'), false, 'not posting request initially')

  t.equal(initialState.get('name'), '', 'name initially empty string')

  const location = initialState.get('location')
  t.ok(Immutable.List.isList(location), 'location is list')
  t.equal(location.size, 0, 'location list is empty')

  t.equal(initialState.get('description'), '', 'description is empty string')

  t.end()
})

test('report reducer: empty call', t => {
  const newState = reducer(undefined, {})

  t.equal(newState, initialState, 'returns initial state')

  t.end()
})

test('report: SET_POSTING', t => {
  const newState = reducer(initialState, { type: SET_POSTING })

  t.equal(newState.get('isPosting'), true, 'sets isPosting to true')

  t.end()
})

test('report: SET_POS_RESULT', t => {
  const statusCode = true
  const payload = 'payload'
  const newState = reducer(
    initialState.set('isPosting', true),
    { type: SET_POST_RESULT, statusCode, payload }
  )

  t.equal(newState.get('isPosting'), false, 'sets isPosting to false')
  t.equal(newState.get('statusCode'), statusCode, 'sets statusCode')
  t.equal(newState.get('payload'), payload, 'sets payload')

  t.end()
})

test('report: SET_PHOTO', t => {
  const photo = 'photo data'
  const newState = reducer(
    initialState,
    { type: SET_PHOTO, photo }
  )
  t.equal(
    photo,
    newState.get('photo'),
    'set photo puts photo data in state'
  )
  t.end()
})

test('report reducer: SET_NAME', t => {
  const name = 'name'
  const newState = reducer(initialState, { type: SET_NAME, name })

  t.equal(newState.get('name'), name, 'set the name')

  t.end()
})

test('report reducer: SET_LOCATION', t => {
  const location = 'location'

  const newState = reducer(
    initialState,
    { type: SET_LOCATION, location, locationIndex: 1 }
  )
  t.equal(
    newState.getIn(['location', 1]),
    location,
    'sets the location'
  )

  const finalState = reducer(
    newState,
    { type: SET_LOCATION, location, locationIndex: 0 }
  )
  t.equal(
    finalState.getIn(['location', 1]),
    '',
    'setting previous location wipes later locations'
  )

  t.end()
})

test('report reducer: SET_DESCRIPTION', t => {
  const description = 'description'
  const action = { type: SET_DESCRIPTION, description }
  const newState = reducer(initialState, action)

  t.equal(newState.get('description'), description, 'sets the description')

  t.end()
})
<|endoftext|>


<commit_before>if (enyo && enyo.version) {
	enyo.version.extra = "2.4.0-pre.2";
}
<commit_msg>Update version string to 2.4.0<commit_after>if (enyo && enyo.version) {
	enyo.version.extra = "2.4.0";
}
<|endoftext|>


<commit_before>import Ember from 'ember';
import { moduleFor, test } from 'ember-qunit';

moduleFor('util:scales/d3-linear-scale', 'Unit | Utility | scales/d3 linear scale');

test('domain/range', function(assert) {
  let scale = this.subject({domain: [0, 10], range: [0,100]}).get('scale');
  assert.equal(scale(5), 50);
});

test('domain element changed', function(assert) {
  let domain = Ember.A([0, 10]);
  let scale = this.subject({domain: domain, range: [0,100]}).get('scale');
  domain.replace(1, 1, 100);
  assert.equal(scale(50), 50);
});

test('domain changed', function(assert) {
  let scaleObserver = this.subject({domain: [0, 10], range: [0,100]});
  let scale = scaleObserver.get('scale');
  scaleObserver.set('domain', [0, 100]);
  assert.equal(scale(50), 50);
});

test('range element changed', function(assert) {
  let range = Ember.A([0, 100]);
  let scale = this.subject({domain: [0,10], range: range}).get('scale');
  range.replace(1, 1, 10);
  assert.equal(scale(5), 5);
});

test('range changed', function(assert) {
  let scaleObserver = this.subject({domain: [0, 10], range: [0,100]});
  let scale = scaleObserver.get('scale');
  scaleObserver.set('range', [0, 10]);
  assert.equal(scale(5), 5);
});

test('clamp', function(assert) {
  let scale = this.subject({domain: [0, 10], range: [0,100], clamp: true}).get('scale');
  assert.equal(scale(20), 100);
});

test('clamp changed', function(assert) {
  let scaleObserver = this.subject({domain: [0, 10], range: [0,100]});
  let scale = scaleObserver.get('scale');
  scaleObserver.set('clamp', true);
  assert.equal(scale(20), 100);
});

test('range round', function(assert) {
  let scale = this.subject({domain: [0, 10], rangeRound: [0,100]}).get('scale');
  assert.equal(scale(5.476), 55);
});

test('range round element changed', function(assert) {
  let range = Ember.A([0, 100]);
  let scale = this.subject({domain: [0,10], rangeRound: range}).get('scale');
  range.replace(1, 1, 10);
  assert.equal(scale(5.3257), 5);
});

test('nice', function(assert) {
  let scale = this.subject({domain: [0.1438, 0.8769], range: [0,100], nice: true}).get('scale');
  let domain = scale.domain();
  assert.equal(domain[0], 0.1);
  assert.equal(domain[1], 0.9);
});

test('nice changed', function(assert) {
  let scaleObserver = this.subject({domain: [0.1438, 0.8769], range: [0,100]});
  let scale = scaleObserver.get('scale');
  scaleObserver.set('nice', true);
  let domain = scale.domain();
  assert.equal(domain[0], 0.1);
  assert.equal(domain[1], 0.9);
});

test('nice changed', function(assert) {
  let scaleObserver = this.subject({domain: [0.1438, 0.8769], range: [0,100], nice: true});
  let scale = scaleObserver.get('scale');
  scaleObserver.set('nice', false);
  let domain = scale.domain();
  assert.equal(domain[0], 0.1438);
  assert.equal(domain[1], 0.8769);
});

test('niceTickCount', function(assert) {
  let scale = this.subject({domain: [0.1438, 0.8769], range: [0,100], nice: 10}).get('scale');
  let domain = scale.domain();
  assert.equal(domain[0], 0.1);
  assert.equal(domain[1], 0.9);
});

test('niceTickCount changed', function(assert) {
  let scaleObserver = this.subject({domain: [0.1438, 0.8769], range: [0,100]});
  let scale = scaleObserver.get('scale');
  scaleObserver.set('nice', 10);
  let domain = scale.domain();
  assert.equal(domain[0], 0.1);
  assert.equal(domain[1], 0.9);
});

test('interpolate', function(assert) {
  let scale = this.subject({domain: [0, 10], range: [0,100], interpolate: d3.interpolateRound}).get('scale');
  assert.equal(scale(5.476), 55);
});

test('interpolate changed', function(assert) {
  let scaleObserver = this.subject({domain: [0, 10], range: [0,100]});
  let scale = scaleObserver.get('scale');
  scaleObserver.set('interpolate', d3.interpolateRound);
  assert.equal(scale(5.476), 55);
});
<commit_msg>Make nice tests easier to read<commit_after>import Ember from 'ember';
import { moduleFor, test } from 'ember-qunit';

moduleFor('util:scales/d3-linear-scale', 'Unit | Utility | scales/d3 linear scale');

test('domain/range', function(assert) {
  let scale = this.subject({domain: [0, 10], range: [0,100]}).get('scale');
  assert.equal(scale(5), 50);
});

test('domain element changed', function(assert) {
  let domain = Ember.A([0, 10]);
  let scale = this.subject({domain: domain, range: [0,100]}).get('scale');
  domain.replace(1, 1, 100);
  assert.equal(scale(50), 50);
});

test('domain changed', function(assert) {
  let scaleObserver = this.subject({domain: [0, 10], range: [0,100]});
  let scale = scaleObserver.get('scale');
  scaleObserver.set('domain', [0, 100]);
  assert.equal(scale(50), 50);
});

test('range element changed', function(assert) {
  let range = Ember.A([0, 100]);
  let scale = this.subject({domain: [0,10], range: range}).get('scale');
  range.replace(1, 1, 10);
  assert.equal(scale(5), 5);
});

test('range changed', function(assert) {
  let scaleObserver = this.subject({domain: [0, 10], range: [0,100]});
  let scale = scaleObserver.get('scale');
  scaleObserver.set('range', [0, 10]);
  assert.equal(scale(5), 5);
});

test('clamp', function(assert) {
  let scale = this.subject({domain: [0, 10], range: [0,100], clamp: true}).get('scale');
  assert.equal(scale(20), 100);
});

test('clamp changed', function(assert) {
  let scaleObserver = this.subject({domain: [0, 10], range: [0,100]});
  let scale = scaleObserver.get('scale');
  scaleObserver.set('clamp', true);
  assert.equal(scale(20), 100);
});

test('range round', function(assert) {
  let scale = this.subject({domain: [0, 10], rangeRound: [0,100]}).get('scale');
  assert.equal(scale(5.476), 55);
});

test('range round element changed', function(assert) {
  let range = Ember.A([0, 100]);
  let scale = this.subject({domain: [0,10], rangeRound: range}).get('scale');
  range.replace(1, 1, 10);
  assert.equal(scale(5.3257), 5);
});

test('nice', function(assert) {
  let scale = this.subject({domain: [0.1438, 0.8769], range: [0,100], nice: true}).get('scale');
  let domain = scale.domain();
  assert.equal(domain[0], 0.1);
  assert.equal(domain[1], 0.9);
});

test('nice changed', function(assert) {
  let scaleObserver = this.subject({domain: [0.1438, 0.8769], range: [0,100]});
  let scale = scaleObserver.get('scale');
  scaleObserver.set('nice', true);
  let domain = scale.domain();
  assert.equal(domain[0], 0.1);
  assert.equal(domain[1], 0.9);
});

test('nice reset', function(assert) {
  let scaleObserver = this.subject({domain: [0.1438, 0.8769], range: [0,100], nice: true});
  let scale = scaleObserver.get('scale');
  scaleObserver.set('nice', false);
  let domain = scale.domain();
  assert.equal(domain[0], 0.1438);
  assert.equal(domain[1], 0.8769);
});

test('nice with ticks', function(assert) {
  let scale = this.subject({domain: [0.1438, 0.8769], range: [0,100], nice: 10}).get('scale');
  let domain = scale.domain();
  assert.equal(domain[0], 0.1);
  assert.equal(domain[1], 0.9);
});

test('nice with ticks changed', function(assert) {
  let scaleObserver = this.subject({domain: [0.1438, 0.8769], range: [0,100]});
  let scale = scaleObserver.get('scale');
  scaleObserver.set('nice', 10);
  let domain = scale.domain();
  assert.equal(domain[0], 0.1);
  assert.equal(domain[1], 0.9);
});

test('interpolate', function(assert) {
  let scale = this.subject({domain: [0, 10], range: [0,100], interpolate: d3.interpolateRound}).get('scale');
  assert.equal(scale(5.476), 55);
});

test('interpolate changed', function(assert) {
  let scaleObserver = this.subject({domain: [0, 10], range: [0,100]});
  let scale = scaleObserver.get('scale');
  scaleObserver.set('interpolate', d3.interpolateRound);
  assert.equal(scale(5.476), 55);
});
<|endoftext|>


<commit_before>var Http = require('http')
,   Promise = require('promise')
,   Fs = require('fs')
,   List = require('immutable').List
,   Url = require('url')
,   Specberus = require("../specberus/lib/validator").Specberus;
;

// Zip a list with another list
// Example: (a, b) zip (c, d) == ((a, c), (b, d))
// This is temporary until progress on
// https://github.com/facebook/immutable-js/issues/51
List.prototype.zip = function(list) {
  return this.map(function (item, index) {
    return List.of(item, list.get(index));
  });
};

var DocumentDownloader = function() {};

DocumentDownloader.fetch = function (url) {
  return new Promise(function (resolve) {
    Http.get(url, function(res) {
      var content = '';

      res.on('data', function(data) { content = content + data; });
      res.on('end', function() { resolve(content); });
    });
  });
};

DocumentDownloader.fetchAll = function (urls) {
  return Promise.all(urls.toArray().map(this.fetch)).then(List);
};

DocumentDownloader.install = function (dest, content) {
  return Promise.denodeify(Fs.writeFile)(dest, content);
};

DocumentDownloader.installAll = function(destsContents) {
  return Promise.all(destsContents.toArray().map(function (e) { // e == [dest, content]
    return DocumentDownloader.install(e.get(0), e.get(1));
  }));
};

DocumentDownloader.fetchAndInstall = function (url, dest, isManifest) {
  var mkdir = Promise.denodeify(Fs.mkdir);

  return new Promise(function (resolve) {
    Fs.exists(dest, function (exists) {
      resolve(exists);
    });
  }).then(function (pathExists) {
    if (!pathExists) {
      return mkdir(dest);
    }
  }).then(function () {
    return DocumentDownloader.fetch(url).then(function (content) {
      if (isManifest) {
        var filenames = DocumentDownloader.getFilenames(content);
        var dests = filenames.set(0, 'Overview.html').map(function (filename) {
          return dest + '/' + filename;
        });
        var urls = filenames.map(function (filename) {
          return Url.resolve(url, filename);
        });
        return DocumentDownloader.fetchAll(urls).then(function (contents) {
          return DocumentDownloader.installAll(dests.zip(contents));
        });
      }
      else {
        return DocumentDownloader.install(dest + '/Overview.html', content);
      }
    });
  });
};

DocumentDownloader.getFilenames = function getFilenames(manifest) {
  return manifest.split('\n').reduce(function (acc, line) {
    var filename = line.split('#')[0].trim();

    if (filename !== '') {
      return acc.push(filename);
    }
    else {
      return acc;
    }
  }, List());
};

exports.DocumentDownloader = DocumentDownloader;

var SpecberusWrapper = function () {};

SpecberusWrapper.validate = function (url) {
  return new Promise(function (resolve, reject) {
    function Sink () {}
    require("util").inherits(Sink, require("events").EventEmitter);

    var sink = new Sink();
    var errors = List();
    var specberus = new Specberus();

    sink.on("start-all", function (profilename) {
      console.log("start-all", profilename);
    });

    sink.on("end-all", function (profilename) {
      resolve({
        errors: errors,
        metadata: specberus.data
      });
    });

    sink.on("err", function (type, data) {
      data.type = type;
      errors = errors.push(data);
    });

    sink.on("exception", function (exception) {
      reject(new Error(exception.message));
    });

    specberus.validate({
      url: url,
      profile: require("../specberus/lib/profiles/WD"),
      events: sink,
      // validation: "recursive",
      // validation: "simple-validation",
      validation: "no-validation",
      noRecTrack: false,
      informativeOnly: false,
      // patentPolicy: patentPolicy,
      processDocument: "2005"
    });
  });
}

exports.SpecberusWrapper = SpecberusWrapper;
<commit_msg>Set params for Specberus validation<commit_after>var Http = require('http')
,   Promise = require('promise')
,   Fs = require('fs')
,   List = require('immutable').List
,   Url = require('url')
,   Specberus = require("../specberus/lib/validator").Specberus;
;

// Zip a list with another list
// Example: (a, b) zip (c, d) == ((a, c), (b, d))
// This is temporary until progress on
// https://github.com/facebook/immutable-js/issues/51
List.prototype.zip = function(list) {
  return this.map(function (item, index) {
    return List.of(item, list.get(index));
  });
};

var DocumentDownloader = function() {};

DocumentDownloader.fetch = function (url) {
  return new Promise(function (resolve) {
    Http.get(url, function(res) {
      var content = '';

      res.on('data', function(data) { content = content + data; });
      res.on('end', function() { resolve(content); });
    });
  });
};

DocumentDownloader.fetchAll = function (urls) {
  return Promise.all(urls.toArray().map(this.fetch)).then(List);
};

DocumentDownloader.install = function (dest, content) {
  return Promise.denodeify(Fs.writeFile)(dest, content);
};

DocumentDownloader.installAll = function(destsContents) {
  return Promise.all(destsContents.toArray().map(function (e) { // e == [dest, content]
    return DocumentDownloader.install(e.get(0), e.get(1));
  }));
};

DocumentDownloader.fetchAndInstall = function (url, dest, isManifest) {
  var mkdir = Promise.denodeify(Fs.mkdir);

  return new Promise(function (resolve) {
    Fs.exists(dest, function (exists) {
      resolve(exists);
    });
  }).then(function (pathExists) {
    if (!pathExists) {
      return mkdir(dest);
    }
  }).then(function () {
    return DocumentDownloader.fetch(url).then(function (content) {
      if (isManifest) {
        var filenames = DocumentDownloader.getFilenames(content);
        var dests = filenames.set(0, 'Overview.html').map(function (filename) {
          return dest + '/' + filename;
        });
        var urls = filenames.map(function (filename) {
          return Url.resolve(url, filename);
        });
        return DocumentDownloader.fetchAll(urls).then(function (contents) {
          return DocumentDownloader.installAll(dests.zip(contents));
        });
      }
      else {
        return DocumentDownloader.install(dest + '/Overview.html', content);
      }
    });
  });
};

DocumentDownloader.getFilenames = function getFilenames(manifest) {
  return manifest.split('\n').reduce(function (acc, line) {
    var filename = line.split('#')[0].trim();

    if (filename !== '') {
      return acc.push(filename);
    }
    else {
      return acc;
    }
  }, List());
};

exports.DocumentDownloader = DocumentDownloader;

var SpecberusWrapper = function () {};

SpecberusWrapper.validate = function (url) {
  return new Promise(function (resolve, reject) {
    function Sink () {}
    require("util").inherits(Sink, require("events").EventEmitter);

    var sink = new Sink();
    var errors = List();
    var specberus = new Specberus();

    sink.on("end-all", function (profilename) {
      resolve({
        errors: errors,
        metadata: specberus.data
      });
    });

    sink.on("err", function (type, data) {
      data.type = type;
      errors = errors.push(data);
    });

    sink.on("exception", function (exception) {
      reject(new Error(exception.message));
    });

    specberus.validate({
      url: url,
      profile: require("../specberus/lib/profiles/WD"),
      events: sink,
      // validation: "recursive",
      validation: "simple-validation",
      noRecTrack: false,
      informativeOnly: false,
      processDocument: "2014"
    });
  });
}

exports.SpecberusWrapper = SpecberusWrapper;
<|endoftext|>


<commit_before>import React from 'react';
import Board from './board';
import { changeTurn } from '../actions';

export default class Game extends React.Component {
  render () {
    return (

        <Board />

    );
  }
}

const mapStateToProps = (state) => {
  return {
    state: "black"
  };
};

const mapDispatchToProps = (dispatch) => {
  return {
    onClick: () => {
      dispatch(changeTurn());
    }
  };
};
<commit_msg>Remove unnecessary constants<commit_after>import React from 'react';
import Board from './board';
import { changeTurn } from '../actions';

export default class Game extends React.Component {
  render () {
    return (

        <Board />

    );
  }
}
<|endoftext|>