<commit_before>// 2017-03-03
// @see Df_GingerPaymentsBase/main
// https://github.com/mage2pro/ginger-payments-base/blob/0.1.1/view/frontend/web/main.js?ts=4
// @see Dfe_AllPay/main
// https://github.com/mage2pro/allpay/blob/1.1.37/view/frontend/web/main.js?ts=4
define([
	'df', 'Df_Core/my/redirectWithPost', 'Df_Payment/custom', 'jquery', 'ko'
], function(df, redirectWithPost, parent, $, ko) {'use strict'; return parent.extend({
	defaults: {df: {test: {showBackendTitle: false}}},
	/**
	 * 2016-08-08
	 * 2017-03-01
	 * Задаёт набор передаваемых на сервер при нажатии кнопки «Place Order» данных.
	 * @override
	 * @see mage2pro/core/Payment/view/frontend/web/mixin.js::dfData()
	 * @used-by mage2pro/core/Payment/view/frontend/web/mixin.js::getData()
	 * https://github.com/mage2pro/core/blob/2.0.21/Payment/view/frontend/web/mixin.js?ts=4#L208-L225
	 * @see \Dfe\AllPay\Method::II_OPTION
	 * https://github.com/mage2pro/allpay/blob/1.1.32/Method.php?ts=4#L126
	 * @returns {Object}
	 */
	dfData: function() {return df.o.merge(this._super(), df.clean({
		option: this.postProcessOption(this.option())
	}));},
	/**
	 * 2017-03-04
	 * @override
	 * @see Df_Payment/custom::initialize()
	 * @returns {Object}
	*/
	initialize: function() {
		this._super();
		// 2017-03-05
		// @used-by dfData()
		// @used-by Df_Payment/withOptions
		// https://github.com/mage2pro/core/blob/2.0.36/Payment/view/frontend/web/template/withOptions.html?ts=4#L12
		// @used-by Df_GingerPaymentsBase/main::dfData()
		// https://github.com/mage2pro/ginger-payments-base/blob/0.2.3/view/frontend/web/main.js?ts=4#L65
		// @used-by Dfe_AllPay/main::iPlans()
		// https://github.com/mage2pro/allpay/blob/1.2.0/view/frontend/web/main.js?ts=4#L50
		// @used-by Dfe_AllPay/one-off/simple
		// https://github.com/mage2pro/allpay/blob/1.2.0/view/frontend/web/template/one-off/simple.html?ts=4#L10
		// @used-by Dfe_AllPay/plans
		// https://github.com/mage2pro/allpay/blob/1.2.0/view/frontend/web/template/plans.html?ts=4#L21
		this.option = ko.observable();
		// 2017-03-05
		// Пример кода для отладки:
		//this.option.subscribe(function(v) {
		//	debugger;
		//}, this);
		return this;
	},
	/**
	 * 2016-08-06
	 * @override
	 * @see mage2pro/core/Payment/view/frontend/web/mixin.js
	 * @used-by placeOrderInternal()
	 */
	onSuccess: function(json) {
		/** @type {Object} */
		var data = $.parseJSON(json);
		df.u(data.uri) ? this._super() : redirectWithPost(data.uri, data.params);
	},
	/**
	 * 2016-08-15
	 * @final
	 * @used-by optionsA()
	 * @used-by Dfe_AllPay/main::oneOffOptions()
	 * https://github.com/mage2pro/allpay/blob/1.1.40/view/frontend/web/main.js?ts=4#L103
	 * @returns {Object}
	 */
	options: function() {return this.config('options');},
	/**
	 * 2016-08-15
	 * @returns {Object[]}
	 */
	optionsA: function() {var _this = this; return $.map(this.options(), function(v, k) {return {
		// 2017-03-04
		// @used-by Df_Payment/withOptions
		// https://github.com/mage2pro/core/blob/2.0.31/Payment/view/frontend/web/template/withOptions.html?ts=4#L10-L11
		domId: [_this.getCode(), 'option', v].join('-'), label: v, value: k
	};});},
	/**
	 * 2017-03-04
	 * Allows to add a control after an option.
	 * @see Df_Payment/null
	 * https://github.com/mage2pro/core/blob/2.0.35/Payment/view/frontend/web/template/null.html
	 * @used-by Df_Payment/withOptions
	 * https://github.com/mage2pro/core/blob/2.0.35/Payment/view/frontend/web/template/withOptions.html?ts=4#L20
	 * @see Df_GingerPaymentsBase/main::optionAfter()
	 * https://github.com/mage2pro/ginger-payments-base/blob/0.1.9/view/frontend/web/main.js?ts=4#L42-L52
	 * @param {String} v
	 * @returns {?String}
	 */
	optionAfter: function(v) {return null;},
	/**
	 * 2016-07-01
	 * @override
	 * @see https://github.com/magento/magento2/blob/2.1.0/app/code/Magento/Checkout/view/frontend/web/js/view/payment/default.js#L127-L159
	 * @used-by https://github.com/magento/magento2/blob/2.1.0/lib/web/knockoutjs/knockout.js#L3863
	*/
	placeOrder: function() {
		if (this.validate()) {
			this.placeOrderInternal();
		}
	},
	/**
	 * 2017-03-05
	 * @used-by dfData()
	 * @param {String} option
	 * @returns {?String}
	 */
	postProcessOption: function(option) {return option;}
});});
<commit_msg>no message<commit_after>// 2017-03-03
// @see Df_GingerPaymentsBase/main
// https://github.com/mage2pro/ginger-payments-base/blob/0.1.1/view/frontend/web/main.js?ts=4
// @see Dfe_AllPay/main
// https://github.com/mage2pro/allpay/blob/1.1.37/view/frontend/web/main.js?ts=4
define([
	'df', 'Df_Core/my/redirectWithPost', 'Df_Payment/custom', 'jquery', 'ko'
], function(df, redirectWithPost, parent, $, ko) {'use strict'; return parent.extend({
	defaults: {df: {test: {showBackendTitle: false}}},
	/**
	 * 2016-08-08
	 * 2017-03-01
	 * Задаёт набор передаваемых на сервер при нажатии кнопки «Place Order» данных.
	 * @override
	 * @see mage2pro/core/Payment/view/frontend/web/mixin.js::dfData()
	 * @used-by mage2pro/core/Payment/view/frontend/web/mixin.js::getData()
	 * https://github.com/mage2pro/core/blob/2.0.21/Payment/view/frontend/web/mixin.js?ts=4#L208-L225
	 * @see \Dfe\AllPay\Method::II_OPTION
	 * https://github.com/mage2pro/allpay/blob/1.1.32/Method.php?ts=4#L126
	 * @returns {Object}
	 */
	dfData: function() {return df.o.merge(this._super(), df.clean({
		option: this.postProcessOption(this.option())
	}));},
	/**
	 * 2017-03-04
	 * @override
	 * @see Df_Payment/custom::initialize()
	 * @returns {Object}
	*/
	initialize: function() {
		this._super();
		// 2017-03-05
		// @used-by dfData()
		// @used-by Df_Payment/withOptions
		// https://github.com/mage2pro/core/blob/2.0.36/Payment/view/frontend/web/template/withOptions.html?ts=4#L12
		// @used-by Df_GingerPaymentsBase/main::dfData()
		// https://github.com/mage2pro/ginger-payments-base/blob/0.2.3/view/frontend/web/main.js?ts=4#L65
		// @used-by Dfe_AllPay/main::iPlans()
		// https://github.com/mage2pro/allpay/blob/1.2.0/view/frontend/web/main.js?ts=4#L50
		// @used-by Dfe_AllPay/one-off/simple
		// https://github.com/mage2pro/allpay/blob/1.2.0/view/frontend/web/template/one-off/simple.html?ts=4#L10
		// @used-by Dfe_AllPay/plans
		// https://github.com/mage2pro/allpay/blob/1.2.0/view/frontend/web/template/plans.html?ts=4#L21
		this.option = ko.observable();
		// 2017-03-05
		// Пример кода для отладки:
		//this.option.subscribe(function(v) {
		//	debugger;
		//}, this);
		return this;
	},
	/**
	 * 2016-08-06
	 * @override
	 * @see mage2pro/core/Payment/view/frontend/web/mixin.js
	 * @used-by placeOrderInternal()
	 */
	onSuccess: function(json) {
		/** @type {Object} */
		var data = $.parseJSON(json);
		data.uri && data.uri.length ? redirectWithPost(data.uri, data.params) : this._super();
	},
	/**
	 * 2016-08-15
	 * @final
	 * @used-by optionsA()
	 * @used-by Dfe_AllPay/main::oneOffOptions()
	 * https://github.com/mage2pro/allpay/blob/1.1.40/view/frontend/web/main.js?ts=4#L103
	 * @returns {Object}
	 */
	options: function() {return this.config('options');},
	/**
	 * 2016-08-15
	 * @returns {Object[]}
	 */
	optionsA: function() {var _this = this; return $.map(this.options(), function(v, k) {return {
		// 2017-03-04
		// @used-by Df_Payment/withOptions
		// https://github.com/mage2pro/core/blob/2.0.31/Payment/view/frontend/web/template/withOptions.html?ts=4#L10-L11
		domId: [_this.getCode(), 'option', v].join('-'), label: v, value: k
	};});},
	/**
	 * 2017-03-04
	 * Allows to add a control after an option.
	 * @see Df_Payment/null
	 * https://github.com/mage2pro/core/blob/2.0.35/Payment/view/frontend/web/template/null.html
	 * @used-by Df_Payment/withOptions
	 * https://github.com/mage2pro/core/blob/2.0.35/Payment/view/frontend/web/template/withOptions.html?ts=4#L20
	 * @see Df_GingerPaymentsBase/main::optionAfter()
	 * https://github.com/mage2pro/ginger-payments-base/blob/0.1.9/view/frontend/web/main.js?ts=4#L42-L52
	 * @param {String} v
	 * @returns {?String}
	 */
	optionAfter: function(v) {return null;},
	/**
	 * 2016-07-01
	 * @override
	 * @see https://github.com/magento/magento2/blob/2.1.0/app/code/Magento/Checkout/view/frontend/web/js/view/payment/default.js#L127-L159
	 * @used-by https://github.com/magento/magento2/blob/2.1.0/lib/web/knockoutjs/knockout.js#L3863
	*/
	placeOrder: function() {
		if (this.validate()) {
			this.placeOrderInternal();
		}
	},
	/**
	 * 2017-03-05
	 * @used-by dfData()
	 * @param {String} option
	 * @returns {?String}
	 */
	postProcessOption: function(option) {return option;}
});});
<|endoftext|>


<commit_before>const { alert, error } = require('../src/logger');

const { connect, close } = require('../src/utils/database');

const { StorageProviderModel } = require('../src/components/fileStorage/repo/db');
const fileStorageProviderRepo = require('../src/components/fileStorage/repo/fileStorageProvider.repo');

const setBucketLifecycleConfiguration = (storageProvider, bucketName) =>
	storageProvider
		.putBucketLifecycleConfiguration({
			Bucket: bucketName,
			LifecycleConfiguration: {
				Rules: [
					{
						Prefix: 'expiring_',
						Expiration: {
							Days: 1,
						},
						Status: 'Enabled',
					},
				],
			},
		})
		.promise();

const removeBucketLifecycleConfiguration = (storageProvider, bucketName) =>
	storageProvider
		.deleteBucketLifecycle({
			Bucket: bucketName,
		})
		.promise();

module.exports = {
	up: async () => {
		alert('start migration');
		await connect();
		const storageProviderInfos = await StorageProviderModel.find({}).lean().exec();
		alert(`${storageProviderInfos.length} storage providers found`);
		for (const storageProviderInfo of storageProviderInfos) {
			const storageProvider = fileStorageProviderRepo.private.createStorageProviderInstance(storageProviderInfo);
			// eslint-disable-next-line no-await-in-loop
			const buckets = await storageProvider.listBuckets().promise();
			alert(`${buckets.Buckets.length} buckets found in storage provider`);
			// eslint-disable-next-line no-await-in-loop
			await Promise.all(buckets.Buckets.map((bucket) => setBucketLifecycleConfiguration(storageProvider, bucket.Name)));
		}
		alert('done!');
		await close();
	},

	down: async () => {
		alert('start migration');
		await connect();
		const storageProviderInfos = await StorageProviderModel.find({}).lean().exec();
		alert(`${storageProviderInfos.length} storage providers found`);
		for (const storageProviderInfo of storageProviderInfos) {
			const storageProvider = fileStorageProviderRepo.private.createStorageProviderInstance(storageProviderInfo);
			// eslint-disable-next-line no-await-in-loop
			const buckets = await storageProvider.listBuckets().promise();
			alert(`${buckets.Buckets.length} buckets found in storage provider`);
			// eslint-disable-next-line no-await-in-loop
			await Promise.all(
				buckets.Buckets.map((bucket) => removeBucketLifecycleConfiguration(storageProvider, bucket.Name))
			);
		}
		alert('done!');
		await close();
	},
};
<commit_msg>SC-9092 change expiring date for S3 to 7 days<commit_after>const { alert } = require('../src/logger');

const { connect, close } = require('../src/utils/database');

const { StorageProviderModel } = require('../src/components/fileStorage/repo/db');
const fileStorageProviderRepo = require('../src/components/fileStorage/repo/fileStorageProvider.repo');

const setBucketLifecycleConfiguration = (storageProvider, bucketName) =>
	storageProvider
		.putBucketLifecycleConfiguration({
			Bucket: bucketName,
			LifecycleConfiguration: {
				Rules: [
					{
						Prefix: 'expiring_',
						Expiration: {
							Days: 7,
						},
						Status: 'Enabled',
					},
				],
			},
		})
		.promise();

const removeBucketLifecycleConfiguration = (storageProvider, bucketName) =>
	storageProvider
		.deleteBucketLifecycle({
			Bucket: bucketName,
		})
		.promise();

module.exports = {
	up: async () => {
		alert('start migration');
		await connect();
		const storageProviderInfos = await StorageProviderModel.find({}).lean().exec();
		alert(`${storageProviderInfos.length} storage providers found`);
		for (const storageProviderInfo of storageProviderInfos) {
			const storageProvider = fileStorageProviderRepo.private.createStorageProviderInstance(storageProviderInfo);
			// eslint-disable-next-line no-await-in-loop
			const buckets = await storageProvider.listBuckets().promise();
			alert(`${buckets.Buckets.length} buckets found in storage provider`);
			// eslint-disable-next-line no-await-in-loop
			await Promise.all(buckets.Buckets.map((bucket) => setBucketLifecycleConfiguration(storageProvider, bucket.Name)));
		}
		alert('done!');
		await close();
	},

	down: async () => {
		alert('start migration');
		await connect();
		const storageProviderInfos = await StorageProviderModel.find({}).lean().exec();
		alert(`${storageProviderInfos.length} storage providers found`);
		for (const storageProviderInfo of storageProviderInfos) {
			const storageProvider = fileStorageProviderRepo.private.createStorageProviderInstance(storageProviderInfo);
			// eslint-disable-next-line no-await-in-loop
			const buckets = await storageProvider.listBuckets().promise();
			alert(`${buckets.Buckets.length} buckets found in storage provider`);
			// eslint-disable-next-line no-await-in-loop
			await Promise.all(
				buckets.Buckets.map((bucket) => removeBucketLifecycleConfiguration(storageProvider, bucket.Name))
			);
		}
		alert('done!');
		await close();
	},
};
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/* globals module */

(function() {
    'use strict';

    const siteUrl = 'http://localhost:8080',
        inputSelector = 'input[type=text]',
        initialRenderTimeoutMilliseconds = 123,
        analysesSelector = '#analyses',
        firstAnalysisSelector = '.analysis:first-of-type',
        analysisTimeoutMilliseconds = 54;

    /* Create at least one e2e test verifying entry point + HTML with Vue.js
     * markup works as expected - at least for a happy path. */

    module.exports = {
        // jscs:disable jsDoc
        'hand with fifteens and pairs points': function(browser) {
            // jscs:enable jsDoc
            browser
                .url(siteUrl)
                .waitForElementVisible(inputSelector, initialRenderTimeoutMilliseconds)
                .setValue(inputSelector, 'Q7742A')
                .waitForElementPresent(firstAnalysisSelector,
                    analysisTimeoutMilliseconds)
                .assert.containsText(analysesSelector,
                    'Keep Q77A, discard 42 = 4 points.')
                .end();
        },

        // jscs:disable jsDoc
        'unknown card index': function(browser) {
            // jscs:enable jsDoc
            browser
                .url(siteUrl)
                .waitForElementVisible(inputSelector, initialRenderTimeoutMilliseconds)
                .setValue(inputSelector, 'A233XY')
                .waitForElementPresent(firstAnalysisSelector,
                    analysisTimeoutMilliseconds)
                .assert.containsText(analysesSelector,
                    'Keep A33X, discard 2Y = 2 points.')
                .end();
        },

        // jscs:disable jsDoc
        'analyses sorted in descending points order': function(browser) {
            // jscs:enable jsDoc
            browser
                .url(siteUrl)
                .waitForElementVisible(inputSelector, initialRenderTimeoutMilliseconds)
                .setValue(inputSelector, 'Q77772')
                .waitForElementPresent(firstAnalysisSelector,
                    analysisTimeoutMilliseconds)
                .assert.containsText(firstAnalysisSelector,
                    'Keep 7777, discard Q2 = 12 points.')
                .end();
        },

        // jscs:disable jsDoc
        'no cards to discard': function(browser) {
            // jscs:enable jsDoc
            browser
                .url(siteUrl)
                .waitForElementVisible(inputSelector, initialRenderTimeoutMilliseconds)
                .setValue(inputSelector, 'K774')
                .waitForElementPresent(firstAnalysisSelector,
                    analysisTimeoutMilliseconds)
                .assert.containsText(analysesSelector,
                    'Keep K774, discard nothing = 2 points.')
                .end();
        },

        // jscs:disable jsDoc
        'hand with just a 4-run': function(browser) {
            // jscs:enable jsDoc
            browser
                .url(siteUrl)
                .waitForElementVisible(inputSelector, initialRenderTimeoutMilliseconds)
                .setValue(inputSelector, 'A289TJ')
                .waitForElementPresent(firstAnalysisSelector,
                    analysisTimeoutMilliseconds)
                .assert.containsText(analysesSelector,
                    'Keep 89TJ, discard A2 = 4 points.')
                .end();
        },

        // jscs:disable jsDoc
        'hand with pairs, fifteens and runs points': function(browser) {
            // jscs:enable jsDoc
            browser
                .url(siteUrl)
                .waitForElementVisible(inputSelector, initialRenderTimeoutMilliseconds)
                .setValue(inputSelector, '8876KQ')
                .waitForElementPresent(firstAnalysisSelector,
                    analysisTimeoutMilliseconds)
                .assert.containsText(analysesSelector,
                    'Keep 8876, discard KQ = 12 points.')
                .end();
        }
    };
}());
<commit_msg>Allow new larger maximum e2e test times<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/* globals module */

(function() {
    'use strict';

    const siteUrl = 'http://localhost:8080',
        inputSelector = 'input[type=text]',
        initialRenderTimeoutMilliseconds = 653,
        analysesSelector = '#analyses',
        firstAnalysisSelector = '.analysis:first-of-type',
        analysisTimeoutMilliseconds = 179;

    /* Create at least one e2e test verifying entry point + HTML with Vue.js
     * markup works as expected - at least for a happy path. */

    module.exports = {
        // jscs:disable jsDoc
        'hand with fifteens and pairs points': function(browser) {
            // jscs:enable jsDoc
            browser
                .url(siteUrl)
                .waitForElementVisible(inputSelector, initialRenderTimeoutMilliseconds)
                .setValue(inputSelector, 'Q7742A')
                .waitForElementPresent(firstAnalysisSelector,
                    analysisTimeoutMilliseconds)
                .assert.containsText(analysesSelector,
                    'Keep Q77A, discard 42 = 4 points.')
                .end();
        },

        // jscs:disable jsDoc
        'unknown card index': function(browser) {
            // jscs:enable jsDoc
            browser
                .url(siteUrl)
                .waitForElementVisible(inputSelector, initialRenderTimeoutMilliseconds)
                .setValue(inputSelector, 'A233XY')
                .waitForElementPresent(firstAnalysisSelector,
                    analysisTimeoutMilliseconds)
                .assert.containsText(analysesSelector,
                    'Keep A33X, discard 2Y = 2 points.')
                .end();
        },

        // jscs:disable jsDoc
        'analyses sorted in descending points order': function(browser) {
            // jscs:enable jsDoc
            browser
                .url(siteUrl)
                .waitForElementVisible(inputSelector, initialRenderTimeoutMilliseconds)
                .setValue(inputSelector, 'Q77772')
                .waitForElementPresent(firstAnalysisSelector,
                    analysisTimeoutMilliseconds)
                .assert.containsText(firstAnalysisSelector,
                    'Keep 7777, discard Q2 = 12 points.')
                .end();
        },

        // jscs:disable jsDoc
        'no cards to discard': function(browser) {
            // jscs:enable jsDoc
            browser
                .url(siteUrl)
                .waitForElementVisible(inputSelector, initialRenderTimeoutMilliseconds)
                .setValue(inputSelector, 'K774')
                .waitForElementPresent(firstAnalysisSelector,
                    analysisTimeoutMilliseconds)
                .assert.containsText(analysesSelector,
                    'Keep K774, discard nothing = 2 points.')
                .end();
        },

        // jscs:disable jsDoc
        'hand with just a 4-run': function(browser) {
            // jscs:enable jsDoc
            browser
                .url(siteUrl)
                .waitForElementVisible(inputSelector, initialRenderTimeoutMilliseconds)
                .setValue(inputSelector, 'A289TJ')
                .waitForElementPresent(firstAnalysisSelector,
                    analysisTimeoutMilliseconds)
                .assert.containsText(analysesSelector,
                    'Keep 89TJ, discard A2 = 4 points.')
                .end();
        },

        // jscs:disable jsDoc
        'hand with pairs, fifteens and runs points': function(browser) {
            // jscs:enable jsDoc
            browser
                .url(siteUrl)
                .waitForElementVisible(inputSelector, initialRenderTimeoutMilliseconds)
                .setValue(inputSelector, '8876KQ')
                .waitForElementPresent(firstAnalysisSelector,
                    analysisTimeoutMilliseconds)
                .assert.containsText(analysesSelector,
                    'Keep 8876, discard KQ = 12 points.')
                .end();
        }
    };
}());
<|endoftext|>


<commit_before>'use strict';

const blueprintHelpers = require('ember-cli-blueprint-test-helpers/helpers');
const setupTestHooks = blueprintHelpers.setupTestHooks;
const emberNew = blueprintHelpers.emberNew;
const emberGenerateDestroy = blueprintHelpers.emberGenerateDestroy;
const modifyPackages = blueprintHelpers.modifyPackages;

const chai = require('ember-cli-blueprint-test-helpers/chai');
const expect = chai.expect;

const generateFakePackageManifest = require('../helpers/generate-fake-package-manifest');
const fixture = require('../helpers/fixture');

describe('Blueprint: acceptance-test', function() {
  setupTestHooks(this);

  describe('in app', function() {
    beforeEach(function() {
      return emberNew();
    });

    describe('with ember-cli-qunit@4.1.0', function() {
      beforeEach(function() {
        generateFakePackageManifest('ember-cli-qunit', '4.1.0');
      });

      it('acceptance-test foo', function() {
        return emberGenerateDestroy(['acceptance-test', 'foo'], _file => {
          expect(_file('tests/acceptance/foo-test.js')).to.equal(
            fixture('acceptance-test/default.js')
          );
        });
      });
    });

    describe('with ember-cli-qunit@4.2.0', function() {
      beforeEach(function() {
        generateFakePackageManifest('ember-cli-qunit', '4.2.0');
      });

      it('acceptance-test foo', function() {
        return emberGenerateDestroy(['acceptance-test', 'foo'], _file => {
          expect(_file('tests/acceptance/foo-test.js')).to.equal(
            fixture('acceptance-test/qunit-rfc268.js')
          );
        });
      });
    });

    describe('with ember-cli-mocha', function() {
      beforeEach(function() {
        return modifyPackages([
          { name: 'ember-cli-qunit', delete: true },
          { name: 'ember-cli-mocha', dev: true },
        ]);
      });

      it('acceptance-test foo', function() {
        return emberGenerateDestroy(['acceptance-test', 'foo'], _file => {
          expect(_file('tests/acceptance/foo-test.js')).to.equal(
            fixture('acceptance-test/mocha.js')
          );
        });
      });
    });

    describe('with ember-mocha@0.14.0', function() {
      beforeEach(function() {
        modifyPackages([
          { name: 'ember-cli-qunit', delete: true },
          { name: 'ember-mocha', dev: true },
        ]);
        generateFakePackageManifest('ember-mocha', '0.14.0');
      });

      it('acceptance-test foo', function() {
        return emberGenerateDestroy(['acceptance-test', 'foo'], _file => {
          expect(_file('tests/acceptance/foo-test.js')).to.equal(
            fixture('acceptance-test/mocha-rfc268.js')
          );
        });
      });
    });
  });

  describe('in addon', function() {
    beforeEach(function() {
      return emberNew({ target: 'addon' });
    });

    describe('with ember-cli-qunit@4.1.0', function() {
      beforeEach(function() {
        generateFakePackageManifest('ember-cli-qunit', '4.1.0');
      });

      it('acceptance-test foo', function() {
        return emberGenerateDestroy(['acceptance-test', 'foo'], _file => {
          expect(_file('tests/acceptance/foo-test.js')).to.equal(
            fixture('acceptance-test/addon-default.js')
          );

          expect(_file('app/acceptance-tests/foo.js')).to.not.exist;
        });
      });

      it('acceptance-test foo/bar', function() {
        return emberGenerateDestroy(['acceptance-test', 'foo/bar'], _file => {
          expect(_file('tests/acceptance/foo/bar-test.js')).to.equal(
            fixture('acceptance-test/addon-nested.js')
          );

          expect(_file('app/acceptance-tests/foo/bar.js')).to.not.exist;
        });
      });
    });

    describe('with ember-cli-qunit@4.2.0', function() {
      beforeEach(function() {
        generateFakePackageManifest('ember-cli-qunit', '4.2.0');
      });

      it('acceptance-test foo', function() {
        return emberGenerateDestroy(['acceptance-test', 'foo'], _file => {
          expect(_file('tests/acceptance/foo-test.js')).to.equal(
            fixture('acceptance-test/qunit-rfc268.js')
          );
        });
      });
    });
  });
});
<commit_msg>Add module unification tests for acceptance-test blueprint<commit_after>'use strict';

const blueprintHelpers = require('ember-cli-blueprint-test-helpers/helpers');
const setupTestHooks = blueprintHelpers.setupTestHooks;
const emberNew = blueprintHelpers.emberNew;
const emberGenerateDestroy = blueprintHelpers.emberGenerateDestroy;
const modifyPackages = blueprintHelpers.modifyPackages;

const chai = require('ember-cli-blueprint-test-helpers/chai');
const expect = chai.expect;
const fs = require('fs-extra');

const generateFakePackageManifest = require('../helpers/generate-fake-package-manifest');
const fixture = require('../helpers/fixture');

describe('Blueprint: acceptance-test', function() {
  setupTestHooks(this);

  describe('in app', function() {
    beforeEach(function() {
      return emberNew();
    });

    describe('with ember-cli-qunit@4.1.0', function() {
      beforeEach(function() {
        generateFakePackageManifest('ember-cli-qunit', '4.1.0');
      });

      it('acceptance-test foo', function() {
        return emberGenerateDestroy(['acceptance-test', 'foo'], _file => {
          expect(_file('tests/acceptance/foo-test.js')).to.equal(
            fixture('acceptance-test/default.js')
          );
        });
      });
    });

    describe('with ember-cli-qunit@4.2.0', function() {
      beforeEach(function() {
        generateFakePackageManifest('ember-cli-qunit', '4.2.0');
      });

      it('acceptance-test foo', function() {
        return emberGenerateDestroy(['acceptance-test', 'foo'], _file => {
          expect(_file('tests/acceptance/foo-test.js')).to.equal(
            fixture('acceptance-test/qunit-rfc268.js')
          );
        });
      });
    });

    describe('with ember-cli-mocha', function() {
      beforeEach(function() {
        return modifyPackages([
          { name: 'ember-cli-qunit', delete: true },
          { name: 'ember-cli-mocha', dev: true },
        ]);
      });

      it('acceptance-test foo', function() {
        return emberGenerateDestroy(['acceptance-test', 'foo'], _file => {
          expect(_file('tests/acceptance/foo-test.js')).to.equal(
            fixture('acceptance-test/mocha.js')
          );
        });
      });
    });

    describe('with ember-mocha@0.14.0', function() {
      beforeEach(function() {
        modifyPackages([
          { name: 'ember-cli-qunit', delete: true },
          { name: 'ember-mocha', dev: true },
        ]);
        generateFakePackageManifest('ember-mocha', '0.14.0');
      });

      it('acceptance-test foo', function() {
        return emberGenerateDestroy(['acceptance-test', 'foo'], _file => {
          expect(_file('tests/acceptance/foo-test.js')).to.equal(
            fixture('acceptance-test/mocha-rfc268.js')
          );
        });
      });
    });
  });

  describe('in addon', function() {
    beforeEach(function() {
      return emberNew({ target: 'addon' });
    });

    describe('with ember-cli-qunit@4.1.0', function() {
      beforeEach(function() {
        generateFakePackageManifest('ember-cli-qunit', '4.1.0');
      });

      it('acceptance-test foo', function() {
        return emberGenerateDestroy(['acceptance-test', 'foo'], _file => {
          expect(_file('tests/acceptance/foo-test.js')).to.equal(
            fixture('acceptance-test/addon-default.js')
          );

          expect(_file('app/acceptance-tests/foo.js')).to.not.exist;
        });
      });

      it('acceptance-test foo/bar', function() {
        return emberGenerateDestroy(['acceptance-test', 'foo/bar'], _file => {
          expect(_file('tests/acceptance/foo/bar-test.js')).to.equal(
            fixture('acceptance-test/addon-nested.js')
          );

          expect(_file('app/acceptance-tests/foo/bar.js')).to.not.exist;
        });
      });
    });

    describe('with ember-cli-qunit@4.2.0', function() {
      beforeEach(function() {
        generateFakePackageManifest('ember-cli-qunit', '4.2.0');
      });

      it('acceptance-test foo', function() {
        return emberGenerateDestroy(['acceptance-test', 'foo'], _file => {
          expect(_file('tests/acceptance/foo-test.js')).to.equal(
            fixture('acceptance-test/qunit-rfc268.js')
          );
        });
      });
    });
  });

  describe('in app - module unification', function() {
    beforeEach(function() {
      return emberNew().then(() => fs.ensureDirSync('src'));
    });

    describe('with ember-cli-qunit@4.1.0', function() {
      beforeEach(function() {
        generateFakePackageManifest('ember-cli-qunit', '4.1.0');
      });

      it('acceptance-test foo', function() {
        return emberGenerateDestroy(['acceptance-test', 'foo'], _file => {
          expect(_file('tests/acceptance/foo-test.js')).to.equal(
            fixture('acceptance-test/default.js')
          );
        });
      });
    });

    describe('with ember-cli-qunit@4.2.0', function() {
      beforeEach(function() {
        generateFakePackageManifest('ember-cli-qunit', '4.2.0');
      });

      it('acceptance-test foo', function() {
        return emberGenerateDestroy(['acceptance-test', 'foo'], _file => {
          expect(_file('tests/acceptance/foo-test.js')).to.equal(
            fixture('acceptance-test/qunit-rfc268.js')
          );
        });
      });
    });

    describe('with ember-cli-mocha', function() {
      beforeEach(function() {
        return modifyPackages([
          { name: 'ember-cli-qunit', delete: true },
          { name: 'ember-cli-mocha', dev: true },
        ]);
      });

      it('acceptance-test foo', function() {
        return emberGenerateDestroy(['acceptance-test', 'foo'], _file => {
          expect(_file('tests/acceptance/foo-test.js')).to.equal(
            fixture('acceptance-test/mocha.js')
          );
        });
      });
    });

    describe('with ember-mocha@0.14.0', function() {
      beforeEach(function() {
        modifyPackages([
          { name: 'ember-cli-qunit', delete: true },
          { name: 'ember-mocha', dev: true },
        ]);
        generateFakePackageManifest('ember-mocha', '0.14.0');
      });

      it('acceptance-test foo', function() {
        return emberGenerateDestroy(['acceptance-test', 'foo'], _file => {
          expect(_file('tests/acceptance/foo-test.js')).to.equal(
            fixture('acceptance-test/mocha-rfc268.js')
          );
        });
      });
    });
  });

  describe('in addon - module unification', function() {
    beforeEach(function() {
      return emberNew({ target: 'addon' }).then(() => fs.ensureDirSync('src'));
    });

    describe('with ember-cli-qunit@4.1.0', function() {
      beforeEach(function() {
        generateFakePackageManifest('ember-cli-qunit', '4.1.0');
      });

      it('acceptance-test foo', function() {
        return emberGenerateDestroy(['acceptance-test', 'foo'], _file => {
          expect(_file('tests/acceptance/foo-test.js')).to.equal(
            fixture('acceptance-test/addon-default.js')
          );

          expect(_file('app/acceptance-tests/foo.js')).to.not.exist;
        });
      });

      it('acceptance-test foo/bar', function() {
        return emberGenerateDestroy(['acceptance-test', 'foo/bar'], _file => {
          expect(_file('tests/acceptance/foo/bar-test.js')).to.equal(
            fixture('acceptance-test/addon-nested.js')
          );

          expect(_file('app/acceptance-tests/foo/bar.js')).to.not.exist;
        });
      });
    });

    describe('with ember-cli-qunit@4.2.0', function() {
      beforeEach(function() {
        generateFakePackageManifest('ember-cli-qunit', '4.2.0');
      });

      it('acceptance-test foo', function() {
        return emberGenerateDestroy(['acceptance-test', 'foo'], _file => {
          expect(_file('tests/acceptance/foo-test.js')).to.equal(
            fixture('acceptance-test/qunit-rfc268.js')
          );
        });
      });
    });
  });
});
<|endoftext|>


<commit_before>/*
 * Copyright 2012 Sakai Foundation (SF) Licensed under the
 * Educational Community License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License. You may
 * obtain a copy of the License at
 *
 *     http://www.osedu.org/licenses/ECL-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an "AS IS"
 * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */

var assert = require('assert');

var Signature = require('oae-util/lib/signature');
var Validator = require('oae-util/lib/validator').Validator;

describe('Signature', function() {
    describe('Validator', function() {

        /*!
         * Validate a simple signature.
         */
        var validate = function(body, signature, isValid) {
            var validator = new Validator();
            validator.check(signature, "Invalid signature").verifySignature('camtest', body);
            assert.equal(validator.hasErrors(), !isValid);
        };

        /*!
         * Validate an expiring signature.
         */
        var validateExpiring = function(body, signature, expires, isValid) {
            var validator = new Validator();
            validator.check(signature, "Invalid signature").verifyExpiringSignature('camtest', expires, body);
            assert.equal(validator.hasErrors(), !isValid);
        };

        /*!
         * Verify that the simple signature utility works.
         */
        it('#verifySignature()', function() {
            var body = "The quick brown fox jumped over the lazy dog.";
            var signature = Signature.sign('camtest', body);

            validate(body, signature, true);
            validate('totally different', signature, false);
            validate(body + 'a', signature, false);
        });

        /*!
         * Verify that the expring signature utility works.
         */
        it('#verifyExpiringSignature()', function(callback) {
            var body = "The quick brown fox jumped over the lazy dog.";
            // expire after 2 ms
            var expires = 2;
            var signature = Signature.createExpiringSignature('camtest', expires, body);

            validateExpiring(body, signature.signature, signature.expires, true);
            validateExpiring('totally different', signature.signature, signature.expires, false);
            validateExpiring(body + 'a', signature.signature, signature.expires, false);

            // Test expiration.
            setTimeout(function() {
                // The signature is now invalid as 20 ms have past.
                validateExpiring(body, signature.signature, signature.expires, false);
                callback();
            }, 20);
        });

        /*!
         * Verify that the expires-at-a-date signature utility works.
         */
        it('#verifyExpiresAtSignature()', function() {
            var body = "The quick brown fox jumped over the lazy dog.";
            // Expires at 2 minutes.
            var expiresAt = new Date(Date.now() + 120000);

            // Ensure they are the same
            var signature = Signature.createExpiresAtSignature('camtest', expiresAt, body);

            validateExpiring(body, signature.signature, signature.expires, true);
            validateExpiring('totally different', signature.signature, signature.expires, false);
            validateExpiring(body + 'a', signature.signature, signature.expires, false);

            // Test it generates the same for the same input fields.
            var signatureB = Signature.createExpiresAtSignature('camtest', expiresAt, body);
            assert.deepEqual(signature, signatureB);
        });
    });

    // Encapsulate the rolling test in it's own describe block
    // so we don't accidentally overwrite the Date.now method
    // for any other tests.
    describe('Rolling expiring signatures', function() {

        var properDateNow = null;

        // Monkey patch the Date.now method so we can verify the expire dates
        // against a known timestamp.
        beforeEach(function() {
            properDateNow = Date.now;
            Date.now = function() {
                // Fri, 25 Jan 2013 11:40:46 GMT
                return 1359114046782;
            };
        });

        // Reset it after each test.
        afterEach(function() {
            Date.now = properDateNow;
        });

        var verifyRollingSignature = function(duration, offset, shouldExpireAt) {
            var body = "The quick brown fox jumped over the lazy dog.";
            var signature = Signature.createRollingSignature('camtest', duration, offset, body);
            var expiresDate = new Date(signature.expires);
            assert.deepEqual(expiresDate.getTime(), shouldExpireAt.getTime(), 'Expected "' + shouldExpireAt + '" (' + shouldExpireAt.getTime() + ') got "' + expiresDate + '" (' + expiresDate.getTime() + ')');
        };

        /**
         * Verify the rolling signature functionality values that are known to be correct.
         */
        it('verify the expire timestamps against known values.', function() {
            verifyRollingSignature(30, 10, new Date(2013, 0, 25, 11, 41, 10));

            // 30 days expire duration, 1 day offset
            verifyRollingSignature(30*24*60*60, 24*60*60, new Date(2013, 1, 15, 0, 0, 0));
        });

        /**
         * Ensure that multiple calls within the window result in the same signature
         */
        it('verify rolling window', function() {
            // Remember, it's Fri, 25 Jan 2013 11:40:46 GMT in this test.
            var jan_25_sig = Signature.createRollingSignature('camtest', 10*24*60*60, 24*60*60, 'foo');

            // Set the 'Date.now' one day further,
            // generating a signature should return the same expires value.
            Date.now = function() {
                // Sat, 26 Jan 2013 11:40:46 GMT
                return 1359200446782;
            };
            var jan_26_sig = Signature.createRollingSignature('camtest', 10*24*60*60, 24*60*60, 'foo');
            assert.deepEqual(jan_25_sig, jan_26_sig);

            // If we set it 10 days further, we should get a new signature.
            Date.now = function() {
                // Tue Feb 05 2013 11:40:46 GMT
                return 1360064446782;
            };
            var feb_05_sig = Signature.createRollingSignature('camtest', 10*24*60*60, 24*60*60, 'foo');
            assert.notDeepEqual(jan_25_sig, feb_05_sig);
            assert.notDeepEqual(jan_26_sig, feb_05_sig);
        });

        /**
         * Ensure that signature does actually expire after the correct amount of time.
         */
        it('verify expiration', function(callback) {
            // Restore the Date.now method for this test.
            Date.now = properDateNow;

            // Create a signature that expires in 100 milliseconds.
            var signature = Signature.createRollingSignature('camtest', 0.1, 0, 'foo');
            setTimeout(function() {
                // By now, the signature should be expired.
                var isValid = Signature.verifyExpiringSignature('camtest', signature.expires, 'foo', signature.signature);
                assert.ok(!isValid);
                callback();
            }, 250);

        });
    });
});
<commit_msg>(Paris2013) Use Date.UTC so that the date is not created with a local GMT offset.<commit_after>/*
 * Copyright 2012 Sakai Foundation (SF) Licensed under the
 * Educational Community License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License. You may
 * obtain a copy of the License at
 *
 *     http://www.osedu.org/licenses/ECL-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an "AS IS"
 * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */

var assert = require('assert');

var Signature = require('oae-util/lib/signature');
var Validator = require('oae-util/lib/validator').Validator;

describe('Signature', function() {
    describe('Validator', function() {

        /*!
         * Validate a simple signature.
         */
        var validate = function(body, signature, isValid) {
            var validator = new Validator();
            validator.check(signature, "Invalid signature").verifySignature('camtest', body);
            assert.equal(validator.hasErrors(), !isValid);
        };

        /*!
         * Validate an expiring signature.
         */
        var validateExpiring = function(body, signature, expires, isValid) {
            var validator = new Validator();
            validator.check(signature, "Invalid signature").verifyExpiringSignature('camtest', expires, body);
            assert.equal(validator.hasErrors(), !isValid);
        };

        /*!
         * Verify that the simple signature utility works.
         */
        it('#verifySignature()', function() {
            var body = "The quick brown fox jumped over the lazy dog.";
            var signature = Signature.sign('camtest', body);

            validate(body, signature, true);
            validate('totally different', signature, false);
            validate(body + 'a', signature, false);
        });

        /*!
         * Verify that the expring signature utility works.
         */
        it('#verifyExpiringSignature()', function(callback) {
            var body = "The quick brown fox jumped over the lazy dog.";
            // expire after 2 ms
            var expires = 2;
            var signature = Signature.createExpiringSignature('camtest', expires, body);

            validateExpiring(body, signature.signature, signature.expires, true);
            validateExpiring('totally different', signature.signature, signature.expires, false);
            validateExpiring(body + 'a', signature.signature, signature.expires, false);

            // Test expiration.
            setTimeout(function() {
                // The signature is now invalid as 20 ms have past.
                validateExpiring(body, signature.signature, signature.expires, false);
                callback();
            }, 20);
        });

        /*!
         * Verify that the expires-at-a-date signature utility works.
         */
        it('#verifyExpiresAtSignature()', function() {
            var body = "The quick brown fox jumped over the lazy dog.";
            // Expires at 2 minutes.
            var expiresAt = new Date(Date.now() + 120000);

            // Ensure they are the same
            var signature = Signature.createExpiresAtSignature('camtest', expiresAt, body);

            validateExpiring(body, signature.signature, signature.expires, true);
            validateExpiring('totally different', signature.signature, signature.expires, false);
            validateExpiring(body + 'a', signature.signature, signature.expires, false);

            // Test it generates the same for the same input fields.
            var signatureB = Signature.createExpiresAtSignature('camtest', expiresAt, body);
            assert.deepEqual(signature, signatureB);
        });
    });

    // Encapsulate the rolling test in it's own describe block
    // so we don't accidentally overwrite the Date.now method
    // for any other tests.
    describe('Rolling expiring signatures', function() {

        var properDateNow = null;

        // Monkey patch the Date.now method so we can verify the expire dates
        // against a known timestamp.
        beforeEach(function() {
            properDateNow = Date.now;
            Date.now = function() {
                // Fri, 25 Jan 2013 11:40:46 GMT
                return 1359114046782;
            };
        });

        // Reset it after each test.
        afterEach(function() {
            Date.now = properDateNow;
        });

        var verifyRollingSignature = function(duration, offset, shouldExpireAt) {
            var body = "The quick brown fox jumped over the lazy dog.";
            var signature = Signature.createRollingSignature('camtest', duration, offset, body);
            var expiresDate = new Date(signature.expires);
            assert.deepEqual(expiresDate.getTime(), shouldExpireAt.getTime(), 'Expected "' + shouldExpireAt + '" (' + shouldExpireAt.getTime() + ') got "' + expiresDate + '" (' + expiresDate.getTime() + ')');
        };

        /**
         * Verify the rolling signature functionality values that are known to be correct.
         */
        it('verify the expire timestamps against known values.', function() {
            verifyRollingSignature(30, 10, new Date(Date.UTC(2013, 0, 25, 11, 41, 10)));

            // 30 days expire duration, 1 day offset
            verifyRollingSignature(30*24*60*60, 24*60*60, new Date(Date.UTC(2013, 1, 15, 0, 0, 0)));
        });

        /**
         * Ensure that multiple calls within the window result in the same signature
         */
        it('verify rolling window', function() {
            // Remember, it's Fri, 25 Jan 2013 11:40:46 GMT in this test.
            var jan_25_sig = Signature.createRollingSignature('camtest', 10*24*60*60, 24*60*60, 'foo');

            // Set the 'Date.now' one day further,
            // generating a signature should return the same expires value.
            Date.now = function() {
                // Sat, 26 Jan 2013 11:40:46 GMT
                return 1359200446782;
            };
            var jan_26_sig = Signature.createRollingSignature('camtest', 10*24*60*60, 24*60*60, 'foo');
            assert.deepEqual(jan_25_sig, jan_26_sig);

            // If we set it 10 days further, we should get a new signature.
            Date.now = function() {
                // Tue Feb 05 2013 11:40:46 GMT
                return 1360064446782;
            };
            var feb_05_sig = Signature.createRollingSignature('camtest', 10*24*60*60, 24*60*60, 'foo');
            assert.notDeepEqual(jan_25_sig, feb_05_sig);
            assert.notDeepEqual(jan_26_sig, feb_05_sig);
        });

        /**
         * Ensure that signature does actually expire after the correct amount of time.
         */
        it('verify expiration', function(callback) {
            // Restore the Date.now method for this test.
            Date.now = properDateNow;

            // Create a signature that expires in 100 milliseconds.
            var signature = Signature.createRollingSignature('camtest', 0.1, 0, 'foo');
            setTimeout(function() {
                // By now, the signature should be expired.
                var isValid = Signature.verifyExpiringSignature('camtest', signature.expires, 'foo', signature.signature);
                assert.ok(!isValid);
                callback();
            }, 250);

        });
    });
});
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2015-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 */
'use strict';

const _ = require('lodash');
const base64VLQ = require('./base64-vlq');
const BundleBase = require('./BundleBase');
const ModuleTransport = require('../lib/ModuleTransport');
const crypto = require('crypto');

const SOURCEMAPPING_URL = '\n\/\/# sourceMappingURL=';

class Bundle extends BundleBase {
  constructor({sourceMapUrl, dev, minify, ramGroups} = {}) {
    super();
    this._sourceMap = false;
    this._sourceMapUrl = sourceMapUrl;
    this._shouldCombineSourceMaps = false;
    this._numRequireCalls = 0;
    this._dev = dev;
    this._minify = minify;

    this._ramGroups = ramGroups;
    this._ramBundle = null; // cached RAM Bundle
  }

  addModule(resolver, resolutionResponse, module, moduleTransport) {
    const index = super.addModule(moduleTransport);
    return resolver.wrapModule({
      resolutionResponse,
      module,
      name: moduleTransport.name,
      code: moduleTransport.code,
      map: moduleTransport.map,
      meta: moduleTransport.meta,
      minify: this._minify,
      dev: this._dev,
    }).then(({code, map}) => {
      // If we get a map from the transformer we'll switch to a mode
      // were we're combining the source maps as opposed to
      if (!this._shouldCombineSourceMaps && map != null) {
        this._shouldCombineSourceMaps = true;
      }

      this.replaceModuleAt(
        index, new ModuleTransport({...moduleTransport, code, map}));
    });
  }

  finalize(options) {
    options = options || {};
    if (options.runMainModule) {
      options.runBeforeMainModule.forEach(this._addRequireCall, this);
      this._addRequireCall(super.getMainModuleId());
    }

    super.finalize(options);
  }

  _addRequireCall(moduleId) {
    const code = `;require(${JSON.stringify(moduleId)});`;
    const name = 'require-' + moduleId;
    super.addModule(new ModuleTransport({
      name,
      id: -this._numRequireCalls - 1,
      code,
      virtual: true,
      sourceCode: code,
      sourcePath: name + '.js',
      meta: {preloaded: true},
    }));
    this._numRequireCalls += 1;
  }

  _getInlineSourceMap(dev) {
    if (this._inlineSourceMap == null) {
      const sourceMap = this.getSourceMap({excludeSource: true, dev});
      /*eslint-env node*/
      const encoded = new Buffer(JSON.stringify(sourceMap)).toString('base64');
      this._inlineSourceMap = 'data:application/json;base64,' + encoded;
    }
    return this._inlineSourceMap;
  }

  getSource(options) {
    super.assertFinalized();

    options = options || {};

    let source = super.getSource();

    if (options.inlineSourceMap) {
      source += SOURCEMAPPING_URL + this._getInlineSourceMap(options.dev);
    } else if (this._sourceMapUrl) {
      source += SOURCEMAPPING_URL + this._sourceMapUrl;
    }

    return source;
  }

  getUnbundle(type) {
    this.assertFinalized();
    if (!this._ramBundle) {
      const modules = this.getModules().slice();

      // separate modules we need to preload from the ones we don't
      const [startupModules, lazyModules] = partition(modules, shouldPreload);

      const ramGroups = this._ramGroups;
      let groups;
      this._ramBundle = {
        startupModules,
        lazyModules,
        get groups() {
          if (!groups) {
            groups = createGroups(ramGroups || [], lazyModules);
          }
          return groups;
        }
      };
    }

    return this._ramBundle;
  }

  /**
   * Combine each of the sourcemaps multiple modules have into a single big
   * one. This works well thanks to a neat trick defined on the sourcemap spec
   * that makes use of of the `sections` field to combine sourcemaps by adding
   * an offset. This is supported only by Chrome for now.
   */
  _getCombinedSourceMaps(options) {
    const result = {
      version: 3,
      file: this._getSourceMapFile(),
      sections: [],
    };

    let line = 0;
    this.getModules().forEach(module => {
      let map = module.map;

      if (module.virtual) {
        map = generateSourceMapForVirtualModule(module);
      }

      if (options.excludeSource) {
        if (map.sourcesContent && map.sourcesContent.length) {
          map = Object.assign({}, map, {sourcesContent: []});
        }
      }

      result.sections.push({
        offset: { line: line, column: 0 },
        map: map,
      });
      line += module.code.split('\n').length;
    });

    return result;
  }

  getSourceMap(options) {
    super.assertFinalized();

    if (this._shouldCombineSourceMaps) {
      return this._getCombinedSourceMaps(options);
    }

    const mappings = this._getMappings();
    const modules = this.getModules();
    const map = {
      file: this._getSourceMapFile(),
      sources: modules.map(module => module.sourcePath),
      version: 3,
      names: [],
      mappings: mappings,
      sourcesContent: options.excludeSource
        ? [] : modules.map(module => module.sourceCode)
    };
    return map;
  }

  getEtag() {
    var eTag = crypto.createHash('md5').update(this.getSource()).digest('hex');
    return eTag;
  }

  _getSourceMapFile() {
    return this._sourceMapUrl
      ? this._sourceMapUrl.replace('.map', '.bundle')
      : 'bundle.js';
  }

  _getMappings() {
    const modules = super.getModules();

    // The first line mapping in our package is basically the base64vlq code for
    // zeros (A).
    const firstLine = 'AAAA';

    // Most other lines in our mappings are all zeros (for module, column etc)
    // except for the lineno mappinp: curLineno - prevLineno = 1; Which is C.
    const line = 'AACA';

    const moduleLines = Object.create(null);
    let mappings = '';
    for (let i = 0; i < modules.length; i++) {
      const module = modules[i];
      const code = module.code;
      let lastCharNewLine  = false;
      moduleLines[module.sourcePath] = 0;
      for (let t = 0; t < code.length; t++) {
        if (t === 0 && i === 0) {
          mappings += firstLine;
        } else if (t === 0) {
          mappings += 'AC';

          // This is the only place were we actually don't know the mapping ahead
          // of time. When it's a new module (and not the first) the lineno
          // mapping is 0 (current) - number of lines in prev module.
          mappings += base64VLQ.encode(
            0 - moduleLines[modules[i - 1].sourcePath]
          );
          mappings += 'A';
        } else if (lastCharNewLine) {
          moduleLines[module.sourcePath]++;
          mappings += line;
        }
        lastCharNewLine = code[t] === '\n';
        if (lastCharNewLine) {
          mappings += ';';
        }
      }
      if (i !== modules.length - 1) {
        mappings += ';';
      }
    }
    return mappings;
  }

  getJSModulePaths() {
    return this.getModules()
      // Filter out non-js files. Like images etc.
      .filter(module => !module.virtual)
      .map(module => module.sourcePath);
  }

  getDebugInfo() {
    return [
      '

Main Module:
 ' + super.getMainModuleId() + '
',
      '',
      '
 Module paths and transformed code:
',
      this.getModules().map(function(m) {
        return '

 Path:
' + m.sourcePath + '

 Source:
' +
               '
' +
               _.escape(m.code) + '

';
      }).join('\n'),
    ].join('\n');
  }

  setRamGroups(ramGroups) {
    this._ramGroups = ramGroups;
  }

  toJSON() {
    this.assertFinalized('Cannot serialize bundle unless finalized');

    return {
      ...super.toJSON(),
      sourceMapUrl: this._sourceMapUrl,
      numRequireCalls: this._numRequireCalls,
      shouldCombineSourceMaps: this._shouldCombineSourceMaps,
    };
  }

  static fromJSON(json) {
    const bundle = new Bundle({sourceMapUrl: json.sourceMapUrl});

    bundle._sourceMapUrl = json.sourceMapUrl;
    bundle._numRequireCalls = json.numRequireCalls;
    bundle._shouldCombineSourceMaps = json.shouldCombineSourceMaps;

    BundleBase.fromJSON(bundle, json);

    return bundle;
  }
}

function generateSourceMapForVirtualModule(module) {
  // All lines map 1-to-1
  let mappings = 'AAAA;';

  for (let i = 1; i < module.code.split('\n').length; i++) {
    mappings +=  'AACA;';
  }

  return {
    version: 3,
    sources: [ module.sourcePath ],
    names: [],
    mappings: mappings,
    file: module.sourcePath,
    sourcesContent: [ module.sourceCode ],
  };
}

function shouldPreload({meta}) {
  return meta && meta.preloaded;
}

function partition(array, predicate) {
  const included = [];
  const excluded = [];
  array.forEach(item => (predicate(item) ? included : excluded).push(item));
  return [included, excluded];
}

function * filter(iterator, predicate) {
  for (const value of iterator) {
    if (predicate(value)) {
      yield value;
    }
  }
}

function * subtree(moduleTransport, moduleTransportsByPath, seen = new Set()) {
  seen.add(moduleTransport.id);
  for (const [, {path}] of moduleTransport.meta.dependencyPairs) {
    const dependency = moduleTransportsByPath.get(path);
    if (dependency && !seen.has(dependency.id)) {
      yield dependency.id;
      yield * subtree(dependency, moduleTransportsByPath, seen);
    }
  }
}

class ArrayMap extends Map {
  get(key) {
    let array = super.get(key);
    if (!array) {
      array = [];
      this.set(key, array);
    }
    return array;
  }
}

function createGroups(ramGroups, lazyModules) {
  // build two maps that allow to lookup module data
  // by path or (numeric) module id;
  const byPath = new Map();
  const byId = new Map();
  lazyModules.forEach(m => {
    byPath.set(m.sourcePath, m);
    byId.set(m.id, m.sourcePath);
  });

  // build a map of group root IDs to an array of module IDs in the group
  const result = new Map(
    ramGroups
      .map(modulePath => {
        const root = byPath.get(modulePath);
        if (!root) {
          throw Error(`Group root ${modulePath} is not part of the bundle`);
        }
        return [
          root.id,
          // `subtree` yields the IDs of all transitive dependencies of a module
          new Set(subtree(byPath.get(root.sourcePath), byPath)),
        ];
      })
  );

  if (ramGroups.length > 1) {
    // build a map of all grouped module IDs to an array of group root IDs
    const all = new ArrayMap();
    for (const [parent, children] of result) {
      for (const module of children) {
        all.get(module).push(parent);
      }
    }

    // find all module IDs that are part of more than one group
    const doubles = filter(all, ([, parents]) => parents.length > 1);
    for (const [moduleId, parents] of doubles) {
      // remove them from their groups
      parents.forEach(p => result.get(p).delete(moduleId));

      // print a warning for each removed module
      const parentNames = parents.map(byId.get, byId);
      const lastName = parentNames.pop();
      console.warn(
        `Module ${byId.get(moduleId)} belongs to groups ${
          parentNames.join(', ')}, and ${lastName
          }. Removing it from all groups.`
      );
    }
  }

  return result;
}

module.exports = Bundle;
<commit_msg>Unbreak RAM groups for modules without dependency pairs<commit_after>/**
 * Copyright (c) 2015-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 */
'use strict';

const _ = require('lodash');
const base64VLQ = require('./base64-vlq');
const BundleBase = require('./BundleBase');
const ModuleTransport = require('../lib/ModuleTransport');
const crypto = require('crypto');

const SOURCEMAPPING_URL = '\n\/\/# sourceMappingURL=';

class Bundle extends BundleBase {
  constructor({sourceMapUrl, dev, minify, ramGroups} = {}) {
    super();
    this._sourceMap = false;
    this._sourceMapUrl = sourceMapUrl;
    this._shouldCombineSourceMaps = false;
    this._numRequireCalls = 0;
    this._dev = dev;
    this._minify = minify;

    this._ramGroups = ramGroups;
    this._ramBundle = null; // cached RAM Bundle
  }

  addModule(resolver, resolutionResponse, module, moduleTransport) {
    const index = super.addModule(moduleTransport);
    return resolver.wrapModule({
      resolutionResponse,
      module,
      name: moduleTransport.name,
      code: moduleTransport.code,
      map: moduleTransport.map,
      meta: moduleTransport.meta,
      minify: this._minify,
      dev: this._dev,
    }).then(({code, map}) => {
      // If we get a map from the transformer we'll switch to a mode
      // were we're combining the source maps as opposed to
      if (!this._shouldCombineSourceMaps && map != null) {
        this._shouldCombineSourceMaps = true;
      }

      this.replaceModuleAt(
        index, new ModuleTransport({...moduleTransport, code, map}));
    });
  }

  finalize(options) {
    options = options || {};
    if (options.runMainModule) {
      options.runBeforeMainModule.forEach(this._addRequireCall, this);
      this._addRequireCall(super.getMainModuleId());
    }

    super.finalize(options);
  }

  _addRequireCall(moduleId) {
    const code = `;require(${JSON.stringify(moduleId)});`;
    const name = 'require-' + moduleId;
    super.addModule(new ModuleTransport({
      name,
      id: -this._numRequireCalls - 1,
      code,
      virtual: true,
      sourceCode: code,
      sourcePath: name + '.js',
      meta: {preloaded: true},
    }));
    this._numRequireCalls += 1;
  }

  _getInlineSourceMap(dev) {
    if (this._inlineSourceMap == null) {
      const sourceMap = this.getSourceMap({excludeSource: true, dev});
      /*eslint-env node*/
      const encoded = new Buffer(JSON.stringify(sourceMap)).toString('base64');
      this._inlineSourceMap = 'data:application/json;base64,' + encoded;
    }
    return this._inlineSourceMap;
  }

  getSource(options) {
    super.assertFinalized();

    options = options || {};

    let source = super.getSource();

    if (options.inlineSourceMap) {
      source += SOURCEMAPPING_URL + this._getInlineSourceMap(options.dev);
    } else if (this._sourceMapUrl) {
      source += SOURCEMAPPING_URL + this._sourceMapUrl;
    }

    return source;
  }

  getUnbundle(type) {
    this.assertFinalized();
    if (!this._ramBundle) {
      const modules = this.getModules().slice();

      // separate modules we need to preload from the ones we don't
      const [startupModules, lazyModules] = partition(modules, shouldPreload);

      const ramGroups = this._ramGroups;
      let groups;
      this._ramBundle = {
        startupModules,
        lazyModules,
        get groups() {
          if (!groups) {
            groups = createGroups(ramGroups || [], lazyModules);
          }
          return groups;
        }
      };
    }

    return this._ramBundle;
  }

  /**
   * Combine each of the sourcemaps multiple modules have into a single big
   * one. This works well thanks to a neat trick defined on the sourcemap spec
   * that makes use of of the `sections` field to combine sourcemaps by adding
   * an offset. This is supported only by Chrome for now.
   */
  _getCombinedSourceMaps(options) {
    const result = {
      version: 3,
      file: this._getSourceMapFile(),
      sections: [],
    };

    let line = 0;
    this.getModules().forEach(module => {
      let map = module.map;

      if (module.virtual) {
        map = generateSourceMapForVirtualModule(module);
      }

      if (options.excludeSource) {
        if (map.sourcesContent && map.sourcesContent.length) {
          map = Object.assign({}, map, {sourcesContent: []});
        }
      }

      result.sections.push({
        offset: { line: line, column: 0 },
        map: map,
      });
      line += module.code.split('\n').length;
    });

    return result;
  }

  getSourceMap(options) {
    super.assertFinalized();

    if (this._shouldCombineSourceMaps) {
      return this._getCombinedSourceMaps(options);
    }

    const mappings = this._getMappings();
    const modules = this.getModules();
    const map = {
      file: this._getSourceMapFile(),
      sources: modules.map(module => module.sourcePath),
      version: 3,
      names: [],
      mappings: mappings,
      sourcesContent: options.excludeSource
        ? [] : modules.map(module => module.sourceCode)
    };
    return map;
  }

  getEtag() {
    var eTag = crypto.createHash('md5').update(this.getSource()).digest('hex');
    return eTag;
  }

  _getSourceMapFile() {
    return this._sourceMapUrl
      ? this._sourceMapUrl.replace('.map', '.bundle')
      : 'bundle.js';
  }

  _getMappings() {
    const modules = super.getModules();

    // The first line mapping in our package is basically the base64vlq code for
    // zeros (A).
    const firstLine = 'AAAA';

    // Most other lines in our mappings are all zeros (for module, column etc)
    // except for the lineno mappinp: curLineno - prevLineno = 1; Which is C.
    const line = 'AACA';

    const moduleLines = Object.create(null);
    let mappings = '';
    for (let i = 0; i < modules.length; i++) {
      const module = modules[i];
      const code = module.code;
      let lastCharNewLine  = false;
      moduleLines[module.sourcePath] = 0;
      for (let t = 0; t < code.length; t++) {
        if (t === 0 && i === 0) {
          mappings += firstLine;
        } else if (t === 0) {
          mappings += 'AC';

          // This is the only place were we actually don't know the mapping ahead
          // of time. When it's a new module (and not the first) the lineno
          // mapping is 0 (current) - number of lines in prev module.
          mappings += base64VLQ.encode(
            0 - moduleLines[modules[i - 1].sourcePath]
          );
          mappings += 'A';
        } else if (lastCharNewLine) {
          moduleLines[module.sourcePath]++;
          mappings += line;
        }
        lastCharNewLine = code[t] === '\n';
        if (lastCharNewLine) {
          mappings += ';';
        }
      }
      if (i !== modules.length - 1) {
        mappings += ';';
      }
    }
    return mappings;
  }

  getJSModulePaths() {
    return this.getModules()
      // Filter out non-js files. Like images etc.
      .filter(module => !module.virtual)
      .map(module => module.sourcePath);
  }

  getDebugInfo() {
    return [
      '

Main Module:
 ' + super.getMainModuleId() + '
',
      '',
      '
 Module paths and transformed code:
',
      this.getModules().map(function(m) {
        return '

 Path:
' + m.sourcePath + '

 Source:
' +
               '
' +
               _.escape(m.code) + '

';
      }).join('\n'),
    ].join('\n');
  }

  setRamGroups(ramGroups) {
    this._ramGroups = ramGroups;
  }

  toJSON() {
    this.assertFinalized('Cannot serialize bundle unless finalized');

    return {
      ...super.toJSON(),
      sourceMapUrl: this._sourceMapUrl,
      numRequireCalls: this._numRequireCalls,
      shouldCombineSourceMaps: this._shouldCombineSourceMaps,
    };
  }

  static fromJSON(json) {
    const bundle = new Bundle({sourceMapUrl: json.sourceMapUrl});

    bundle._sourceMapUrl = json.sourceMapUrl;
    bundle._numRequireCalls = json.numRequireCalls;
    bundle._shouldCombineSourceMaps = json.shouldCombineSourceMaps;

    BundleBase.fromJSON(bundle, json);

    return bundle;
  }
}

function generateSourceMapForVirtualModule(module) {
  // All lines map 1-to-1
  let mappings = 'AAAA;';

  for (let i = 1; i < module.code.split('\n').length; i++) {
    mappings +=  'AACA;';
  }

  return {
    version: 3,
    sources: [ module.sourcePath ],
    names: [],
    mappings: mappings,
    file: module.sourcePath,
    sourcesContent: [ module.sourceCode ],
  };
}

function shouldPreload({meta}) {
  return meta && meta.preloaded;
}

function partition(array, predicate) {
  const included = [];
  const excluded = [];
  array.forEach(item => (predicate(item) ? included : excluded).push(item));
  return [included, excluded];
}

function * filter(iterator, predicate) {
  for (const value of iterator) {
    if (predicate(value)) {
      yield value;
    }
  }
}

function * subtree(moduleTransport, moduleTransportsByPath, seen = new Set()) {
  seen.add(moduleTransport.id);
  for (const [, {path}] of moduleTransport.meta.dependencyPairs || []) {
    const dependency = moduleTransportsByPath.get(path);
    if (dependency && !seen.has(dependency.id)) {
      yield dependency.id;
      yield * subtree(dependency, moduleTransportsByPath, seen);
    }
  }
}

class ArrayMap extends Map {
  get(key) {
    let array = super.get(key);
    if (!array) {
      array = [];
      this.set(key, array);
    }
    return array;
  }
}

function createGroups(ramGroups, lazyModules) {
  // build two maps that allow to lookup module data
  // by path or (numeric) module id;
  const byPath = new Map();
  const byId = new Map();
  lazyModules.forEach(m => {
    byPath.set(m.sourcePath, m);
    byId.set(m.id, m.sourcePath);
  });

  // build a map of group root IDs to an array of module IDs in the group
  const result = new Map(
    ramGroups
      .map(modulePath => {
        const root = byPath.get(modulePath);
        if (!root) {
          throw Error(`Group root ${modulePath} is not part of the bundle`);
        }
        return [
          root.id,
          // `subtree` yields the IDs of all transitive dependencies of a module
          new Set(subtree(byPath.get(root.sourcePath), byPath)),
        ];
      })
  );

  if (ramGroups.length > 1) {
    // build a map of all grouped module IDs to an array of group root IDs
    const all = new ArrayMap();
    for (const [parent, children] of result) {
      for (const module of children) {
        all.get(module).push(parent);
      }
    }

    // find all module IDs that are part of more than one group
    const doubles = filter(all, ([, parents]) => parents.length > 1);
    for (const [moduleId, parents] of doubles) {
      // remove them from their groups
      parents.forEach(p => result.get(p).delete(moduleId));

      // print a warning for each removed module
      const parentNames = parents.map(byId.get, byId);
      const lastName = parentNames.pop();
      console.warn(
        `Module ${byId.get(moduleId)} belongs to groups ${
          parentNames.join(', ')}, and ${lastName
          }. Removing it from all groups.`
      );
    }
  }

  return result;
}

module.exports = Bundle;
<|endoftext|>


<commit_before>import axios from 'axios';

export default class MultiDictClient {
  constructor(baseUrl = 'https://stage.multidict.fagbokforlaget.no/api/v2', timeout = 2000) {
    this.client = axios.create({
      'baseURL': baseUrl,
      'headers': {'X-Custom-Header': 'dict-client'},
      'timeout': timeout
    });
    this.bookTitle = undefined;
  }

  search(phrase, language, trans_lang, fallback_lang) {
    let params = {'phrase': phrase, 'language': language};
    if ( trans_lang ) { params['trans_lang'] = trans_lang; }
    if ( fallback_lang ) { params['fallback_lang'] = fallback_lang; }
    if ( this.bookTitle ) { params['source'] = this.bookTitle; }
    let self = this;
    return new Promise(function(resolve, reject) {
        self.client.get('/phrases/search', {'params': params})
        .then(function(response) {
            resolve( self._apply_dict_rules(response, phrase) );
        }, function(error) {
            reject(error);
        });
    });
  }

  _apply_dict_rules(response, phrase){
    phrase = phrase.toLowerCase();
    response.data = this._inflection_rule(response.data, phrase);
    response.data = this._baseform(response.data, phrase);
    return response;
  }

  _baseform(data, lookup_word){
    if (typeof(data) !== 'object' ){
      return;
    }
    data.forEach(function(el){
      let baseForm = el.phrase.props.idx;
      if (baseForm && lookup_word != baseForm) {
        el.phrase.base_form = baseForm;
      }
    });

    return data;
  }

  _inflection_rule(data, lookup_word){
    if (typeof(data) !== 'object' ){
      return;
    }
    data.forEach(function(el){
      let inflections = el.phrase.inflections;
      el.phrase.lookup_word_form = {};
      // Seperate inflections and auto inflections
      if (typeof(inflections) === 'object' ){

        let auto_inflections = [];
        let inf_by_form = {};

        inflections.forEach(function(inf, i){
          if ( inf.props.automatic || inf.props.type == 'extra'){
            auto_inflections.push(inf);
          }
          else {
            if ( inf.props.name == lookup_word ) {
              el.phrase.lookup_word_form = inf.form;
            }
            /*
              We need to find all inflection of same form and we need to keep the order too
              Lets create a object example
              ordered_inflection = {
                  form_id : [
                      order_no : { inflection object }
                  ]
              }
            */
            if (!inf_by_form[inf.form.id]){
              inf_by_form[inf.form.id] = [];
            }
            let order_no = inf.props.order || 0;
            inf_by_form[inf.form.id][order_no] = inf;
          }
        });

        let phrase_inflections = [];
        /*
          Combine same form inflections
          check for same form.id and props.order for right order
        */
        Object.keys(inf_by_form).forEach(function (key) {
          let value = inf_by_form[key];
          let inf   = value[0];
          inf.props.name = value.map(function(ks){
            return ks.props.name;
          }).join('/');
          phrase_inflections.push(inf);
        });

        el.phrase.inflections = phrase_inflections;
        el.phrase.auto_inflections = auto_inflections;
      }
    });
    return data;
  }

}
<commit_msg>feat: use production url for multidict<commit_after>import axios from 'axios';

export default class MultiDictClient {
  constructor(baseUrl = 'https://multidict.fagbokforlaget.no/api/v2', timeout = 2000) {
    this.client = axios.create({
      'baseURL': baseUrl,
      'headers': {'X-Custom-Header': 'dict-client'},
      'timeout': timeout
    });
    this.bookTitle = undefined;
  }

  search(phrase, language, trans_lang, fallback_lang) {
    let params = {'phrase': phrase, 'language': language};
    if ( trans_lang ) { params['trans_lang'] = trans_lang; }
    if ( fallback_lang ) { params['fallback_lang'] = fallback_lang; }
    if ( this.bookTitle ) { params['source'] = this.bookTitle; }
    let self = this;
    return new Promise(function(resolve, reject) {
        self.client.get('/phrases/search', {'params': params})
        .then(function(response) {
            resolve( self._apply_dict_rules(response, phrase) );
        }, function(error) {
            reject(error);
        });
    });
  }

  _apply_dict_rules(response, phrase){
    phrase = phrase.toLowerCase();
    response.data = this._inflection_rule(response.data, phrase);
    response.data = this._baseform(response.data, phrase);
    return response;
  }

  _baseform(data, lookup_word){
    if (typeof(data) !== 'object' ){
      return;
    }
    data.forEach(function(el){
      let baseForm = el.phrase.props.idx;
      if (baseForm && lookup_word != baseForm) {
        el.phrase.base_form = baseForm;
      }
    });

    return data;
  }

  _inflection_rule(data, lookup_word){
    if (typeof(data) !== 'object' ){
      return;
    }
    data.forEach(function(el){
      let inflections = el.phrase.inflections;
      el.phrase.lookup_word_form = {};
      // Seperate inflections and auto inflections
      if (typeof(inflections) === 'object' ){

        let auto_inflections = [];
        let inf_by_form = {};

        inflections.forEach(function(inf, i){
          if ( inf.props.automatic || inf.props.type == 'extra'){
            auto_inflections.push(inf);
          }
          else {
            if ( inf.props.name == lookup_word ) {
              el.phrase.lookup_word_form = inf.form;
            }
            /*
              We need to find all inflection of same form and we need to keep the order too
              Lets create a object example
              ordered_inflection = {
                  form_id : [
                      order_no : { inflection object }
                  ]
              }
            */
            if (!inf_by_form[inf.form.id]){
              inf_by_form[inf.form.id] = [];
            }
            let order_no = inf.props.order || 0;
            inf_by_form[inf.form.id][order_no] = inf;
          }
        });

        let phrase_inflections = [];
        /*
          Combine same form inflections
          check for same form.id and props.order for right order
        */
        Object.keys(inf_by_form).forEach(function (key) {
          let value = inf_by_form[key];
          let inf   = value[0];
          inf.props.name = value.map(function(ks){
            return ks.props.name;
          }).join('/');
          phrase_inflections.push(inf);
        });

        el.phrase.inflections = phrase_inflections;
        el.phrase.auto_inflections = auto_inflections;
      }
    });
    return data;
  }

}
<|endoftext|>


<commit_before>import React from "react";
import { renderToStaticMarkup } from "react-dom/server";
import Helmet from "react-helmet";
import {
  styled,
  themes,
  Icon,
  Symbol,
  IconDefinitions
} from "@patternplate/components";
import * as svg from "../utils/svg";

const THEMES = themes();

class FavIcon extends React.Component {
  constructor(...args) {
    super(...args);
    this.state = {};
  }

  componentDidMount() {
    svg
      .png(getSource(this.props))
      .then(href => this.setState({ href }))
      .catch(err => {
        console.error(err);
        this.setState({ href: null });
      });
  }

  componentWillReceiveProps(next) {
    svg
      .png(getSource(next))
      .then(href => this.setState({ href }))
      .catch(err => {
        console.error(err);
        this.setState({ href: null });
      });
  }

  render() {
    return (
      <Helmet
        link={[
          { rel: "icon", href: this.state.href, type: "image/png" },
          {
            rel: "icon",
            href: svg.btoa(getSource(this.props)),
            type: "image/svg+xml"
          }
        ]}
      />
    );
  }
}

export default styled(FavIcon)`
  width: 100%;
  height: auto;
  stroke: ${props => props.theme.color};
  stroke-width: 0;
  fill: ${props => props.theme.color};
`;

function getSource(props) {
  if (!props.source) {
    return renderToStaticMarkup(
      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
        <Symbol
          definition={IconDefinitions.patternplate}
          emit={true}
          style={{ fill: getFill(props) }}
        />
      </svg>
    );
  }

  const [purged] = svg.purge([svg.parse(props.source)]);
  return svg.stringify(purged);
}

function getFill(props) {
  if (props.error) {
    return THEMES.dark.error;
  }
  return THEMES.dark.active;
}
<commit_msg>fix: make favicon work on ff<commit_after>import React from "react";
import { renderToStaticMarkup } from "react-dom/server";
import Helmet from "react-helmet";
import {
  styled,
  themes,
  Icon,
  Symbol,
  IconDefinitions
} from "@patternplate/components";
import * as svg from "../utils/svg";
import platform from "platform";

const THEMES = themes();

const SVG_FAVICON_SUPPORT = ["Firefox"];

class FavIcon extends React.Component {
  constructor(...args) {
    super(...args);
    this.state = {};
  }

  componentDidMount() {
    if (SVG_FAVICON_SUPPORT.indexOf(platform.name) > -1) {
      return;
    }

    svg
      .png(getSource(this.props))
      .then(pngHref => this.setState({
        pngHref
      }))
      .catch(err => {
        console.error(err);
        this.setState({
          pngHref: null
        });
      });
  }

  componentWillReceiveProps(next) {
    if (SVG_FAVICON_SUPPORT.indexOf(platform.name) > -1) {
      return;
    }

    svg
      .png(getSource(next))
      .then(pngHref => this.setState({
        pngHref
      }))
      .catch(err => {
        console.error(err);
        this.setState({
          pngHref: null
        });
      });
  }

  render() {
    const source = getSource(this.props);
    const svgHref = svg.btoa(source);

    return (
      <Helmet
        link={[
          ...(this.state.pngHref ? [{ rel: "icon", href: this.state.pngHref, type: "image/png" }] : []),
          {
            rel: "icon",
            href: svgHref,
            type: "image/svg+xml"
          }
        ]}
      />
    );
  }
}

export default styled(FavIcon)`
  width: 100%;
  height: auto;
  stroke: ${props => props.theme.color};
  stroke-width: 0;
  fill: ${props => props.theme.color};
`;

function getSource(props) {
  if (!props.source) {
    return renderToStaticMarkup(
      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
        <Symbol
          definition={IconDefinitions.patternplate}
          emit={true}
          style={{ fill: getFill(props) }}
        />
      </svg>
    );
  }

  const [purged] = svg.purge([svg.parse(props.source)]);
  return svg.stringify(purged);
}

function getFill(props) {
  if (props.error) {
    return THEMES.dark.error;
  }
  return THEMES.dark.active;
}
<|endoftext|>