<commit_before>/* eslint-disable new-cap */

'use strict'

const util = require('lambda-proxy-utils')
const satlib = require('@sat-utils/api-lib')

module.exports.handler = (event, context, cb) => {
  console.log(`API handler: ${JSON.stringify(event)}`)

  // function to send response to browser
  function respond(err, resp) {
    if (err) {
      console.log(err)
      const res = new util.Response({ cors: true, statusCode: 400 })
      return cb(null, res.send({ details: err.message }))
    }
    const res = new util.Response({ cors: true, statusCode: 200 })
    return cb(null, res.send(resp))
  }

  let msg

  // split and remove empty strings
  const resources = event.path.split('/').filter((x) => x)
  console.log('resources', resources)
  // make sure this is a STAC endpoint
  if (resources[0] !== 'stac') {
    msg = 'endpoint not defined (use /stac)'
    console.log(msg, resources)
    respond(null, msg)
    return
  }

  // determine endpoint
  let endpoint
  if ('X-Forwarded-Host' in event.headers) {
    endpoint = `${event.headers['X-Forwarded-Proto']}://${event.headers['X-Forwarded-Host']}`
  }
  else {
    endpoint = `${event.headers['X-Forwarded-Proto']}://${event.headers.Host}`
    if ('stage' in event.requestContext) {
      endpoint = `${endpoint}/${event.requestContext.stage}`
    }
  }

  // get payload
  const method = event.httpMethod
  let query = {}
  if (method === 'POST' && event.body) {
    query = JSON.parse(event.body)
  }
  else if (method === 'GET' && event.queryStringParameters) {
    query = event.queryStringParameters
  }
  // default page and limit
  var page = query.page || 1
  var limit = query.limit || 100

  // /stac
  if (resources.length === 1) {
    msg = 'STAC catalog (see endpoints /search and /collections)'
    const catalog = {
      name: 'sat-api',
      description: 'A STAC API of public datasets',
      links: [
        { rel: 'self', href: `${endpoint}/stac` }
      ]
    }
    //respond(null, catalog)
    satlib.es.client().then((esClient) => {
      const api = new satlib.api(esClient, query, endpoint, page, limit=100)
      api.search('collections', (err, results) => {
        if (err) respond(err)
        for (let col of results.collections) {
          catalog.links.push({rel: 'child', href: `${endpoint}/stac/collections/${col.name}`})
        }
        respond(null, catalog)
      })
    })
  } else {
    // drop the /stac prefix
    resources.splice(0, 1)
    // STAC endpoints
    switch (resources[0]) {
    case 'api':
      msg = 'TODO - return API doc'
      console.log(msg, resources)
      respond(null, msg)
      break
    // collections endpoint
    case 'collections':
      if (resources.length === 1) {
        // all collections
        satlib.es.client().then((esClient) => {
          const api = new satlib.api(esClient, query, endpoint, page, limit)
          api.search_collections(respond)
        })
      } else if (resources.length === 2) {
        // specific collection
        satlib.es.client().then((esClient) => {
          const api = new satlib.api(esClient, query, endpoint, page, limit)
          api.get_collection(resources[1], (err, resp) => {
            respond(err, resp)
          })
        })
      } else if (resources[2] == 'items') {
        console.log('search items in this collection')
        // this is a search across items in this collection
        satlib.es.client().then((esClient) => {
          query['cid'] = resources[1]
          const api = new satlib.api(esClient, query, endpoint, page, limit)
          api.search_items(respond)
        })
      } else {
        msg = 'endpoint not defined'
        console.log(msg, resources)
        respond(null, msg)
      }
      break;
    case 'search':
      // items api
      satlib.es.client().then((esClient) => {
        const api = new satlib.api(esClient, query, endpoint, page, limit)
        api.search_items(respond)
      })
      break
    default:
      respond(null, 'endpoint not defined')
    }
  }
}
<commit_msg>tweak api collection lookup<commit_after>/* eslint-disable new-cap */

'use strict'

const util = require('lambda-proxy-utils')
const satlib = require('@sat-utils/api-lib')

module.exports.handler = (event, context, cb) => {
  console.log(`API handler: ${JSON.stringify(event)}`)

  // function to send response to browser
  function respond(err, resp) {
    if (err) {
      console.log(err)
      const res = new util.Response({ cors: true, statusCode: 400 })
      return cb(null, res.send({ details: err.message }))
    }
    const res = new util.Response({ cors: true, statusCode: 200 })
    return cb(null, res.send(resp))
  }

  let msg

  // split and remove empty strings
  const resources = event.path.split('/').filter((x) => x)
  console.log('resources', resources)
  // make sure this is a STAC endpoint
  if (resources[0] !== 'stac') {
    msg = 'endpoint not defined (use /stac)'
    console.log(msg, resources)
    respond(null, msg)
    return
  }

  // determine endpoint
  let endpoint
  if ('X-Forwarded-Host' in event.headers) {
    endpoint = `${event.headers['X-Forwarded-Proto']}://${event.headers['X-Forwarded-Host']}`
  }
  else {
    endpoint = `${event.headers['X-Forwarded-Proto']}://${event.headers.Host}`
    if ('stage' in event.requestContext) {
      endpoint = `${endpoint}/${event.requestContext.stage}`
    }
  }

  // get payload
  const method = event.httpMethod
  let query = {}
  if (method === 'POST' && event.body) {
    query = JSON.parse(event.body)
  }
  else if (method === 'GET' && event.queryStringParameters) {
    query = event.queryStringParameters
  }
  // default page and limit
  var page = query.page || 1
  var limit = query.limit || 100

  // /stac
  if (resources.length === 1) {
    msg = 'STAC catalog (see endpoints /search and /collections)'
    const catalog = {
      name: 'sat-api',
      description: 'A STAC API of public datasets',
      links: [
        { rel: 'self', href: `${endpoint}/stac` }
      ]
    }
    //respond(null, catalog)
    satlib.es.client().then((esClient) => {
      const api = new satlib.api(esClient, query, endpoint, page, limit=100)
      api.search_collections((err, results) => {
        if (err) respond(err)
        for (let c of results.collections) {
          catalog.links.push({rel: 'child', href: `${endpoint}/stac/collections/${c.name}`})
        }
        respond(null, catalog)
      })
    })
  } else {
    // drop the /stac prefix
    resources.splice(0, 1)
    // STAC endpoints
    switch (resources[0]) {
    case 'api':
      msg = 'TODO - return API doc'
      console.log(msg, resources)
      respond(null, msg)
      break
    // collections endpoint
    case 'collections':
      if (resources.length === 1) {
        // all collections
        satlib.es.client().then((esClient) => {
          const api = new satlib.api(esClient, query, endpoint, page, limit)
          api.search_collections(respond)
        })
      } else if (resources.length === 2) {
        // specific collection
        satlib.es.client().then((esClient) => {
          const api = new satlib.api(esClient, query, endpoint, page, limit)
          api.get_collection(resources[1], (err, resp) => {
            respond(err, resp)
          })
        })
      } else if (resources[2] == 'items') {
        console.log('search items in this collection')
        // this is a search across items in this collection
        satlib.es.client().then((esClient) => {
          query['cid'] = resources[1]
          const api = new satlib.api(esClient, query, endpoint, page, limit)
          api.search_items(respond)
        })
      } else {
        msg = 'endpoint not defined'
        console.log(msg, resources)
        respond(null, msg)
      }
      break;
    case 'search':
      // items api
      satlib.es.client().then((esClient) => {
        const api = new satlib.api(esClient, query, endpoint, page, limit)
        api.search_items(respond)
      })
      break
    default:
      respond(null, 'endpoint not defined')
    }
  }
}
<|endoftext|>


<commit_before>import notify from './notify';
import { options } from './config';

export default class {
    constructor(notifyVue) {
        this.notify = notifyVue;
        this.options = options;
    }

    postOptions(body) {
        const postOptions = {...this.options};
        postOptions['method'] = 'post';
        postOptions['body'] = JSON.stringify(body);

        return postOptions;
    }

    async request(path, options) {
        const resp = await fetch(path, options);

        if (!resp.ok) {
            return Promise.reject(resp);
        }

        return resp;
    }

    async fetch(query) {
        let url = '/list.json?';
        if (query !== undefined) {
            Object.keys(query).map(k => url += k + '=' + query[k] + '&');
        }
        const resp = await this.request(url.substring(url.length - 1, -1), this.options);

        return await resp.json();
    }

    async before_create(code, callback) {
        try {
            const resp = await this.request('/fetch?code=' + code, this.options);
            callback(await resp.json(), resp.headers.get('X-Request-Id'));
        } catch (e) {
            notify(this.notify, e);
        }
    }

    async create(entry, reqId, sid) {
        try {
            const reqOptions = this.postOptions({ 'id': reqId, 'sid': sid });
            const resp = await this.request('/create', reqOptions);
            notify(this.notify, resp);

            return resp.json();
        } catch (e) {
            notify(this.notify, e);
        }
    }

    async delete(ids) {
        return await this.request('/delete', this.postOptions({ ids: ids }));
    }

    async edit(entry) {
        return await this.request('/edit', this.postOptions(entry));
    }
}
<commit_msg>await し忘れ修正<commit_after>import notify from './notify';
import { options } from './config';

export default class {
    constructor(notifyVue) {
        this.notify = notifyVue;
        this.options = options;
    }

    postOptions(body) {
        const postOptions = {...this.options};
        postOptions['method'] = 'post';
        postOptions['body'] = JSON.stringify(body);

        return postOptions;
    }

    async request(path, options) {
        const resp = await fetch(path, options);

        if (!resp.ok) {
            return Promise.reject(resp);
        }

        return resp;
    }

    async fetch(query) {
        let url = '/list.json?';
        if (query !== undefined) {
            Object.keys(query).map(k => url += k + '=' + query[k] + '&');
        }
        const resp = await this.request(url.substring(url.length - 1, -1), this.options);

        return await resp.json();
    }

    async before_create(code, callback) {
        try {
            const resp = await this.request('/fetch?code=' + code, this.options);
            callback(await resp.json(), resp.headers.get('X-Request-Id'));
        } catch (e) {
            notify(this.notify, e);
        }
    }

    async create(entry, reqId, sid) {
        try {
            const reqOptions = this.postOptions({ 'id': reqId, 'sid': sid });
            const resp = await this.request('/create', reqOptions);
            notify(this.notify, resp);

            return await resp.json();
        } catch (e) {
            notify(this.notify, e);
        }
    }

    async delete(ids) {
        return await this.request('/delete', this.postOptions({ ids: ids }));
    }

    async edit(entry) {
        return await this.request('/edit', this.postOptions(entry));
    }
}
<|endoftext|>


<commit_before>'use strict';
var React = require('react-native');
var { requireNativeComponent } = React;

var RTCView = {
  name: 'RTCVideoView',
  propTypes: {
    streamURL: React.PropTypes.number,
  },
};

var v = requireNativeComponent('RTCVideoView', RTCView, {nativeOnly: {
  'scaleX': true,
  'scaleY': true,
  'testID': true,
  'decomposedMatrix': true,
  'backgroundColor': true,
  'accessibilityComponentType': true,
  'renderToHardwareTextureAndroid': true,
  'translateY': true,
  'translateX': true,
  'accessibilityLabel': true,
  'accessibilityLiveRegion': true,
  'importantForAccessibility': true,
  'rotation': true,
  'opacity': true,
}});

module.exports = v;
<commit_msg>Fixes Android RTCVideoView.onLayout issue<commit_after>'use strict';
var React = require('react-native');
var { requireNativeComponent } = React;

var RTCView = {
  name: 'RTCVideoView',
  propTypes: {
    streamURL: React.PropTypes.number,
  },
};

var v = requireNativeComponent('RTCVideoView', RTCView, {nativeOnly: {
  'scaleX': true,
  'scaleY': true,
  'testID': true,
  'decomposedMatrix': true,
  'backgroundColor': true,
  'accessibilityComponentType': true,
  'renderToHardwareTextureAndroid': true,
  'translateY': true,
  'translateX': true,
  'accessibilityLabel': true,
  'accessibilityLiveRegion': true,
  'importantForAccessibility': true,
  'rotation': true,
  'opacity': true,
  'onLayout': true,
}});

module.exports = v;
<|endoftext|>


<commit_before>'use strict';

/* jshint -W030 */
var chai = require('chai')
  , expect = chai.expect
  , sinon = require('sinon')
  , Support = require(__dirname + '/../support')
  , Sequelize = require(__dirname + '/../../../index')
  , DataTypes = require(__dirname + '/../../../lib/data-types')
  , current = Support.sequelize
  , Promise = Sequelize.Promise
  , _ = require('lodash');

if (current.dialect.supports.groupedLimit) {
  describe(Support.getTestDialectTeaser('Include'), function() {
    describe('separate', function () {
      it('should run a hasMany association in a separate query', function () {
        var User = this.sequelize.define('User', {})
          , Task = this.sequelize.define('Task', {})
          , sqlSpy = sinon.spy();

        User.Tasks = User.hasMany(Task, {as: 'tasks'});

        return this.sequelize.sync({force: true}).then(function () {
          return Promise.join(
            User.create({
              id: 1,
              tasks: [
                {},
                {},
                {}
              ]
            }, {
              include: [User.Tasks]
            }),
            User.create({
              id: 2,
              tasks: [
                {}
              ]
            }, {
              include: [User.Tasks]
            })
          ).then(function () {
            return User.findAll({
              include: [
                {association: User.Tasks, separate: true}
              ],
              order: [
                ['id', 'ASC']
              ],
              logging: sqlSpy
            });
          }).then(function (users) {
            expect(users[0].get('tasks')).to.be.ok;
            expect(users[0].get('tasks').length).to.equal(3);
            expect(users[1].get('tasks')).to.be.ok;
            expect(users[1].get('tasks').length).to.equal(1);

            expect(users[0].get('tasks')[0].createdAt).to.be.ok;
            expect(users[0].get('tasks')[0].updatedAt).to.be.ok;

            expect(sqlSpy).to.have.been.calledTwice;
          });
        });
      });

      it('should work even if the id was not included', function () {
        var User = this.sequelize.define('User', {
            name: DataTypes.STRING
          })
          , Task = this.sequelize.define('Task', {})
          , sqlSpy = sinon.spy();

        User.Tasks = User.hasMany(Task, {as: 'tasks'});

        return this.sequelize.sync({force: true}).then(function () {
          return User.create({
              id: 1,
              tasks: [
                {},
                {},
                {}
              ]
            }, {
              include: [User.Tasks]
            }).then(function () {
              return User.findAll({
                attributes: ['name'],
                include: [
                  {association: User.Tasks, separate: true}
                ],
                order: [
                  ['id', 'ASC']
                ],
                logging: sqlSpy
              });
            }).then(function (users) {
              expect(users[0].get('tasks')).to.be.ok;
              expect(users[0].get('tasks').length).to.equal(3);
              expect(sqlSpy).to.have.been.calledTwice;
            });
        });
      });

      it('should not break a nested include with null values', function () {
        var User = this.sequelize.define('User', {})
          , Team = this.sequelize.define('Team', {})
          , Company = this.sequelize.define('Company', {});

        User.Team = User.belongsTo(Team);
        Team.Company = Team.belongsTo(Company);

        return this.sequelize.sync({force: true}).then(function () {
          return User.create({});
        }).then(function () {
          return User.findAll({
            include: [
              {association: User.Team, include: [Team.Company]}
            ]
          });
        });
      });

      it('should run a hasMany association with limit in a separate query', function () {
        var User = this.sequelize.define('User', {})
          , Task = this.sequelize.define('Task', {
              userId: {
                type: DataTypes.INTEGER,
                field: 'user_id'
              }
            })
          , sqlSpy = sinon.spy();

        User.Tasks = User.hasMany(Task, {as: 'tasks', foreignKey: 'userId'});

        return this.sequelize.sync({force: true}).then(function () {
          return Promise.join(
            User.create({
              id: 1,
              tasks: [
                {},
                {},
                {}
              ]
            }, {
              include: [User.Tasks]
            }),
            User.create({
              id: 2,
              tasks: [
                {},
                {},
                {},
                {}
              ]
            }, {
              include: [User.Tasks]
            })
          ).then(function () {
            return User.findAll({
              include: [
                {association: User.Tasks, limit: 2}
              ],
              order: [
                ['id', 'ASC']
              ],
              logging: sqlSpy
            });
          }).then(function (users) {
            expect(users[0].get('tasks')).to.be.ok;
            expect(users[0].get('tasks').length).to.equal(2);
            expect(users[1].get('tasks')).to.be.ok;
            expect(users[1].get('tasks').length).to.equal(2);
            expect(sqlSpy).to.have.been.calledTwice;
          });
        });
      });

      it('should run a nested (from a non-separate include) hasMany association in a separate query', function () {
        var User = this.sequelize.define('User', {})
          , Company = this.sequelize.define('Company')
          , Task = this.sequelize.define('Task', {})
          , sqlSpy = sinon.spy();

        User.Company = User.belongsTo(Company, {as: 'company'});
        Company.Tasks = Company.hasMany(Task, {as: 'tasks'});

        return this.sequelize.sync({force: true}).then(function () {
          return Promise.join(
            User.create({
              id: 1,
              company: {
                tasks: [
                  {},
                  {},
                  {}
                ]
              }
            }, {
              include: [
                {association: User.Company, include: [Company.Tasks]}
              ]
            }),
            User.create({
              id: 2,
              company: {
                tasks: [
                  {}
                ]
              }
            }, {
              include: [
                {association: User.Company, include: [Company.Tasks]}
              ]
            })
          ).then(function () {
            return User.findAll({
              include: [
                {association: User.Company, include: [
                  {association: Company.Tasks, separate: true}
                ]}
              ],
              order: [
                ['id', 'ASC']
              ],
              logging: sqlSpy
            });
          }).then(function (users) {
            expect(users[0].get('company').get('tasks')).to.be.ok;
            expect(users[0].get('company').get('tasks').length).to.equal(3);
            expect(users[1].get('company').get('tasks')).to.be.ok;
            expect(users[1].get('company').get('tasks').length).to.equal(1);
            expect(sqlSpy).to.have.been.calledTwice;
          });
        });
      });

      it('should work having a separate include between a parent and child include', function () {
        var User = this.sequelize.define('User', {})
          , Project = this.sequelize.define('Project')
          , Company = this.sequelize.define('Company')
          , Task = this.sequelize.define('Task', {})
          , sqlSpy = sinon.spy();

        Company.Users = Company.hasMany(User, {as: 'users'});
        User.Tasks = User.hasMany(Task, {as: 'tasks'});
        Task.Project = Task.belongsTo(Project, {as: 'project'});

        return this.sequelize.sync({force: true}).then(function () {
          return Promise.join(
            Company.create({
              id: 1,
              users: [
                {
                  tasks: [
                    {project: {}},
                    {project: {}},
                    {project: {}}
                  ]
                }
              ]
            }, {
              include: [
                {association: Company.Users, include: [
                  {association: User.Tasks, include: [
                    Task.Project
                  ]}
                ]}
              ]
            })
          ).then(function () {
            return Company.findAll({
              include: [
                {association: Company.Users, include: [
                  {association: User.Tasks, separate: true, include: [
                    Task.Project
                  ]}
                ]}
              ],
              order: [
                ['id', 'ASC']
              ],
              logging: sqlSpy
            });
          }).then(function (companies) {
            expect(sqlSpy).to.have.been.calledTwice;

            expect(companies[0].users[0].tasks[0].project).to.be.ok;
          });
        });
      });

      it('should run two nested hasMany association in a separate queries', function () {
        var User = this.sequelize.define('User', {})
          , Project = this.sequelize.define('Project', {})
          , Task = this.sequelize.define('Task', {})
          , sqlSpy = sinon.spy();

        User.Projects = User.hasMany(Project, {as: 'projects'});
        Project.Tasks = Project.hasMany(Task, {as: 'tasks'});

        return this.sequelize.sync({force: true}).then(function () {
          return Promise.join(
            User.create({
              id: 1,
              projects: [
                {
                  id: 1,
                  tasks: [
                    {},
                    {},
                    {}
                  ]
                },
                {
                  id: 2,
                  tasks: [
                    {}
                  ]
                }
              ]
            }, {
              include: [
                {association: User.Projects, include: [Project.Tasks]}
              ]
            }),
            User.create({
              id: 2,
              projects: [
                {
                  id: 3,
                  tasks: [
                    {},
                    {}
                  ]
                }
              ]
            }, {
              include: [
                {association: User.Projects, include: [Project.Tasks]}
              ]
            })
          ).then(function () {
            return User.findAll({
              include: [
                {association: User.Projects, separate: true, include: [
                  {association: Project.Tasks, separate: true}
                ]}
              ],
              order: [
                ['id', 'ASC']
              ],
              logging: sqlSpy
            });
          }).then(function (users) {
            var u1projects = users[0].get('projects');

            expect(u1projects).to.be.ok;
            expect(u1projects[0].get('tasks')).to.be.ok;
            expect(u1projects[1].get('tasks')).to.be.ok;
            expect(u1projects.length).to.equal(2);

            // WTB ES2015 syntax ...
            expect(_.find(u1projects, function (p) { return p.id === 1; }).get('tasks').length).to.equal(3);
            expect(_.find(u1projects, function (p) { return p.id === 2; }).get('tasks').length).to.equal(1);

            expect(users[1].get('projects')).to.be.ok;
            expect(users[1].get('projects')[0].get('tasks')).to.be.ok;
            expect(users[1].get('projects').length).to.equal(1);
            expect(users[1].get('projects')[0].get('tasks').length).to.equal(2);

            expect(sqlSpy).to.have.been.calledThrice;
          });
        });
      });

      it('should work with two schema models in a hasMany association', function() {
        var User = this.sequelize.define('User', {}, {schema: 'archive'})
          , Task = this.sequelize.define('Task', {
              title: DataTypes.STRING
            }, {schema: 'archive'});

        User.Tasks = User.hasMany(Task, {as: 'tasks'});

        return this.sequelize.dropAllSchemas().then(() => {
          return this.sequelize.createSchema('archive').then(() => {
            return this.sequelize.sync({force: true}).then(() => {
              return Promise.join(
                User.create({
                  tasks: [
                    {title: 'b'},
                    {title: 'd'},
                    {title: 'c'},
                    {title: 'a'}
                  ]
                }, {
                  include: [User.Tasks]
                }),
                User.create({
                  tasks: [
                    {title: 'a'},
                    {title: 'c'},
                    {title: 'b'}
                  ]
                }, {
                  include: [User.Tasks]
                })
              );
            }).then((users) => {
              return User.findAll({
                include: [{ model: Task, limit: 2, as: 'tasks' }],
                order: [
                  ['id', 'ASC']
                ],
                logging: console.log
              }).then((result) => {
                expect(result[0].tasks.length).to.equal(2);
                expect(result[0].tasks[0].title).to.equal('b');
                expect(result[0].tasks[1].title).to.equal('d');

                expect(result[1].tasks.length).to.equal(2);
                expect(result[1].tasks[0].title).to.equal('a');
                expect(result[1].tasks[1].title).to.equal('c');
              });
            });
          });
        });
      });
    });
  });
}
<commit_msg>Seperate test fix (#6321)<commit_after>'use strict';

/* jshint -W030 */
var chai = require('chai')
  , expect = chai.expect
  , sinon = require('sinon')
  , Support = require(__dirname + '/../support')
  , Sequelize = require(__dirname + '/../../../index')
  , DataTypes = require(__dirname + '/../../../lib/data-types')
  , current = Support.sequelize
  , Promise = Sequelize.Promise
  , _ = require('lodash');

if (current.dialect.supports.groupedLimit) {
  describe(Support.getTestDialectTeaser('Include'), function() {
    describe('separate', function () {
      it('should run a hasMany association in a separate query', function () {
        var User = this.sequelize.define('User', {})
          , Task = this.sequelize.define('Task', {})
          , sqlSpy = sinon.spy();

        User.Tasks = User.hasMany(Task, {as: 'tasks'});

        return this.sequelize.sync({force: true}).then(function () {
          return Promise.join(
            User.create({
              id: 1,
              tasks: [
                {},
                {},
                {}
              ]
            }, {
              include: [User.Tasks]
            }),
            User.create({
              id: 2,
              tasks: [
                {}
              ]
            }, {
              include: [User.Tasks]
            })
          ).then(function () {
            return User.findAll({
              include: [
                {association: User.Tasks, separate: true}
              ],
              order: [
                ['id', 'ASC']
              ],
              logging: sqlSpy
            });
          }).then(function (users) {
            expect(users[0].get('tasks')).to.be.ok;
            expect(users[0].get('tasks').length).to.equal(3);
            expect(users[1].get('tasks')).to.be.ok;
            expect(users[1].get('tasks').length).to.equal(1);

            expect(users[0].get('tasks')[0].createdAt).to.be.ok;
            expect(users[0].get('tasks')[0].updatedAt).to.be.ok;

            expect(sqlSpy).to.have.been.calledTwice;
          });
        });
      });

      it('should work even if the id was not included', function () {
        var User = this.sequelize.define('User', {
            name: DataTypes.STRING
          })
          , Task = this.sequelize.define('Task', {})
          , sqlSpy = sinon.spy();

        User.Tasks = User.hasMany(Task, {as: 'tasks'});

        return this.sequelize.sync({force: true}).then(function () {
          return User.create({
              id: 1,
              tasks: [
                {},
                {},
                {}
              ]
            }, {
              include: [User.Tasks]
            }).then(function () {
              return User.findAll({
                attributes: ['name'],
                include: [
                  {association: User.Tasks, separate: true}
                ],
                order: [
                  ['id', 'ASC']
                ],
                logging: sqlSpy
              });
            }).then(function (users) {
              expect(users[0].get('tasks')).to.be.ok;
              expect(users[0].get('tasks').length).to.equal(3);
              expect(sqlSpy).to.have.been.calledTwice;
            });
        });
      });

      it('should not break a nested include with null values', function () {
        var User = this.sequelize.define('User', {})
          , Team = this.sequelize.define('Team', {})
          , Company = this.sequelize.define('Company', {});

        User.Team = User.belongsTo(Team);
        Team.Company = Team.belongsTo(Company);

        return this.sequelize.sync({force: true}).then(function () {
          return User.create({});
        }).then(function () {
          return User.findAll({
            include: [
              {association: User.Team, include: [Team.Company]}
            ]
          });
        });
      });

      it('should run a hasMany association with limit in a separate query', function () {
        var User = this.sequelize.define('User', {})
          , Task = this.sequelize.define('Task', {
              userId: {
                type: DataTypes.INTEGER,
                field: 'user_id'
              }
            })
          , sqlSpy = sinon.spy();

        User.Tasks = User.hasMany(Task, {as: 'tasks', foreignKey: 'userId'});

        return this.sequelize.sync({force: true}).then(function () {
          return Promise.join(
            User.create({
              id: 1,
              tasks: [
                {},
                {},
                {}
              ]
            }, {
              include: [User.Tasks]
            }),
            User.create({
              id: 2,
              tasks: [
                {},
                {},
                {},
                {}
              ]
            }, {
              include: [User.Tasks]
            })
          ).then(function () {
            return User.findAll({
              include: [
                {association: User.Tasks, limit: 2}
              ],
              order: [
                ['id', 'ASC']
              ],
              logging: sqlSpy
            });
          }).then(function (users) {
            expect(users[0].get('tasks')).to.be.ok;
            expect(users[0].get('tasks').length).to.equal(2);
            expect(users[1].get('tasks')).to.be.ok;
            expect(users[1].get('tasks').length).to.equal(2);
            expect(sqlSpy).to.have.been.calledTwice;
          });
        });
      });

      it('should run a nested (from a non-separate include) hasMany association in a separate query', function () {
        var User = this.sequelize.define('User', {})
          , Company = this.sequelize.define('Company')
          , Task = this.sequelize.define('Task', {})
          , sqlSpy = sinon.spy();

        User.Company = User.belongsTo(Company, {as: 'company'});
        Company.Tasks = Company.hasMany(Task, {as: 'tasks'});

        return this.sequelize.sync({force: true}).then(function () {
          return Promise.join(
            User.create({
              id: 1,
              company: {
                tasks: [
                  {},
                  {},
                  {}
                ]
              }
            }, {
              include: [
                {association: User.Company, include: [Company.Tasks]}
              ]
            }),
            User.create({
              id: 2,
              company: {
                tasks: [
                  {}
                ]
              }
            }, {
              include: [
                {association: User.Company, include: [Company.Tasks]}
              ]
            })
          ).then(function () {
            return User.findAll({
              include: [
                {association: User.Company, include: [
                  {association: Company.Tasks, separate: true}
                ]}
              ],
              order: [
                ['id', 'ASC']
              ],
              logging: sqlSpy
            });
          }).then(function (users) {
            expect(users[0].get('company').get('tasks')).to.be.ok;
            expect(users[0].get('company').get('tasks').length).to.equal(3);
            expect(users[1].get('company').get('tasks')).to.be.ok;
            expect(users[1].get('company').get('tasks').length).to.equal(1);
            expect(sqlSpy).to.have.been.calledTwice;
          });
        });
      });

      it('should work having a separate include between a parent and child include', function () {
        var User = this.sequelize.define('User', {})
          , Project = this.sequelize.define('Project')
          , Company = this.sequelize.define('Company')
          , Task = this.sequelize.define('Task', {})
          , sqlSpy = sinon.spy();

        Company.Users = Company.hasMany(User, {as: 'users'});
        User.Tasks = User.hasMany(Task, {as: 'tasks'});
        Task.Project = Task.belongsTo(Project, {as: 'project'});

        return this.sequelize.sync({force: true}).then(function () {
          return Promise.join(
            Company.create({
              id: 1,
              users: [
                {
                  tasks: [
                    {project: {}},
                    {project: {}},
                    {project: {}}
                  ]
                }
              ]
            }, {
              include: [
                {association: Company.Users, include: [
                  {association: User.Tasks, include: [
                    Task.Project
                  ]}
                ]}
              ]
            })
          ).then(function () {
            return Company.findAll({
              include: [
                {association: Company.Users, include: [
                  {association: User.Tasks, separate: true, include: [
                    Task.Project
                  ]}
                ]}
              ],
              order: [
                ['id', 'ASC']
              ],
              logging: sqlSpy
            });
          }).then(function (companies) {
            expect(sqlSpy).to.have.been.calledTwice;

            expect(companies[0].users[0].tasks[0].project).to.be.ok;
          });
        });
      });

      it('should run two nested hasMany association in a separate queries', function () {
        var User = this.sequelize.define('User', {})
          , Project = this.sequelize.define('Project', {})
          , Task = this.sequelize.define('Task', {})
          , sqlSpy = sinon.spy();

        User.Projects = User.hasMany(Project, {as: 'projects'});
        Project.Tasks = Project.hasMany(Task, {as: 'tasks'});

        return this.sequelize.sync({force: true}).then(function () {
          return Promise.join(
            User.create({
              id: 1,
              projects: [
                {
                  id: 1,
                  tasks: [
                    {},
                    {},
                    {}
                  ]
                },
                {
                  id: 2,
                  tasks: [
                    {}
                  ]
                }
              ]
            }, {
              include: [
                {association: User.Projects, include: [Project.Tasks]}
              ]
            }),
            User.create({
              id: 2,
              projects: [
                {
                  id: 3,
                  tasks: [
                    {},
                    {}
                  ]
                }
              ]
            }, {
              include: [
                {association: User.Projects, include: [Project.Tasks]}
              ]
            })
          ).then(function () {
            return User.findAll({
              include: [
                {association: User.Projects, separate: true, include: [
                  {association: Project.Tasks, separate: true}
                ]}
              ],
              order: [
                ['id', 'ASC']
              ],
              logging: sqlSpy
            });
          }).then(function (users) {
            var u1projects = users[0].get('projects');

            expect(u1projects).to.be.ok;
            expect(u1projects[0].get('tasks')).to.be.ok;
            expect(u1projects[1].get('tasks')).to.be.ok;
            expect(u1projects.length).to.equal(2);

            // WTB ES2015 syntax ...
            expect(_.find(u1projects, function (p) { return p.id === 1; }).get('tasks').length).to.equal(3);
            expect(_.find(u1projects, function (p) { return p.id === 2; }).get('tasks').length).to.equal(1);

            expect(users[1].get('projects')).to.be.ok;
            expect(users[1].get('projects')[0].get('tasks')).to.be.ok;
            expect(users[1].get('projects').length).to.equal(1);
            expect(users[1].get('projects')[0].get('tasks').length).to.equal(2);

            expect(sqlSpy).to.have.been.calledThrice;
          });
        });
      });

      it('should work with two schema models in a hasMany association', function() {
        var User = this.sequelize.define('User', {}, {schema: 'archive'})
          , Task = this.sequelize.define('Task', {
              id: { type: DataTypes.INTEGER, primaryKey: true },
              title: DataTypes.STRING
            }, {schema: 'archive'});

        User.Tasks = User.hasMany(Task, {as: 'tasks'});

        return this.sequelize.dropAllSchemas().then(() => {
          return this.sequelize.createSchema('archive').then(() => {
            return this.sequelize.sync({force: true}).then(() => {
              return Promise.join(
                User.create({
                  tasks: [
                    {id: 1, title: 'b'},
                    {id: 2, title: 'd'},
                    {id: 3, title: 'c'},
                    {id: 4, title: 'a'}
                  ]
                }, {
                  include: [User.Tasks]
                }),
                User.create({
                  tasks: [
                    {id: 5, title: 'a'},
                    {id: 6, title: 'c'},
                    {id: 7, title: 'b'}
                  ]
                }, {
                  include: [User.Tasks]
                })
              );
            }).then((users) => {
              return User.findAll({
                include: [{ model: Task, limit: 2, as: 'tasks' }],
                order: [
                  ['id', 'ASC']
                ],
                logging: console.log
              }).then((result) => {
                expect(result[0].tasks.length).to.equal(2);
                expect(result[0].tasks[0].title).to.equal('b');
                expect(result[0].tasks[1].title).to.equal('d');

                expect(result[1].tasks.length).to.equal(2);
                expect(result[1].tasks[0].title).to.equal('a');
                expect(result[1].tasks[1].title).to.equal('c');
              });
            });
          });
        });
      });
    });
  });
}
<|endoftext|>


<commit_before>/**
 * Copyright 2014-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.
 *
 * @providesModule ReactElementValidator
 */

/**
 * ReactElementValidator provides a wrapper around a element factory
 * which validates the props passed to the element. This is intended to be
 * used only in DEV and could be replaced by a static type checker for languages
 * that support it.
 */

'use strict';

var ReactCurrentOwner = require('ReactCurrentOwner');
var ReactComponentTreeHook = require('ReactComponentTreeHook');
var ReactElement = require('ReactElement');

var checkReactTypeSpec = require('checkReactTypeSpec');

var canDefineProperty = require('canDefineProperty');
var getComponentName = require('getComponentName');
var getIteratorFn = require('getIteratorFn');
var warning = require('warning');

function getDeclarationErrorAddendum() {
  if (ReactCurrentOwner.current) {
    var name = getComponentName(ReactCurrentOwner.current);
    if (name) {
      return '\n\nCheck the render method of `' + name + '`.';
    }
  }
  return '';
}

function getSourceInfoErrorAddendum(elementProps) {
  if (
    elementProps !== null &&
    elementProps !== undefined &&
    elementProps.__source !== undefined
  ) {
    var source = elementProps.__source;
    var fileName = source.fileName.replace(/^.*[\\\/]/, '');
    var lineNumber = source.lineNumber;
    return '\n\nCheck your code at ' + fileName + ':' + lineNumber + '.';
  }
  return '';
}

/**
 * Warn if there's no key explicitly set on dynamic arrays of children or
 * object keys are not valid. This allows us to keep track of children between
 * updates.
 */
var ownerHasKeyUseWarning = {};

function getCurrentComponentErrorInfo(parentType) {
  var info = getDeclarationErrorAddendum();

  if (!info) {
    var parentName = typeof parentType === 'string' ?
      parentType : parentType.displayName || parentType.name;
    if (parentName) {
      info = `\n\nCheck the top-level render call using <${parentName}>.`;
    }
  }
  return info;
}

/**
 * Warn if the element doesn't have an explicit key assigned to it.
 * This element is in an array. The array could grow and shrink or be
 * reordered. All children that haven't already been validated are required to
 * have a "key" property assigned to it. Error statuses are cached so a warning
 * will only be shown once.
 *
 * @internal
 * @param {ReactElement} element Element that requires a key.
 * @param {*} parentType element's parent's type.
 */
function validateExplicitKey(element, parentType) {
  if (!element._store || element._store.validated || element.key != null) {
    return;
  }
  element._store.validated = true;

  var memoizer = ownerHasKeyUseWarning.uniqueKey || (
    ownerHasKeyUseWarning.uniqueKey = {}
  );

  var currentComponentErrorInfo = getCurrentComponentErrorInfo(parentType);
  if (memoizer[currentComponentErrorInfo]) {
    return;
  }
  memoizer[currentComponentErrorInfo] = true;

  // Usually the current owner is the offender, but if it accepts children as a
  // property, it may be the creator of the child that's responsible for
  // assigning it a key.
  var childOwner = '';
  if (element &&
      element._owner &&
      element._owner !== ReactCurrentOwner.current) {
    // Give the component that originally created this child.
    childOwner =
      ` It was passed a child from ${getComponentName(element._owner)}.`;
  }

  warning(
    false,
    'Each child in an array or iterator should have a unique "key" prop.' +
    '%s%s See https://fb.me/react-warning-keys for more information.%s',
    currentComponentErrorInfo,
    childOwner,
    ReactComponentTreeHook.getCurrentStackAddendum(element)
  );
}

/**
 * Ensure that every element either is passed in a static location, in an
 * array with an explicit keys property defined, or in an object literal
 * with valid key property.
 *
 * @internal
 * @param {ReactNode} node Statically passed child of any type.
 * @param {*} parentType node's parent's type.
 */
function validateChildKeys(node, parentType) {
  if (typeof node !== 'object') {
    return;
  }
  if (Array.isArray(node)) {
    for (var i = 0; i < node.length; i++) {
      var child = node[i];
      if (ReactElement.isValidElement(child)) {
        validateExplicitKey(child, parentType);
      }
    }
  } else if (ReactElement.isValidElement(node)) {
    // This element was passed in a valid location.
    if (node._store) {
      node._store.validated = true;
    }
  } else if (node) {
    var iteratorFn = getIteratorFn(node);
    // Entry iterators provide implicit keys.
    if (iteratorFn) {
      if (iteratorFn !== node.entries) {
        var iterator = iteratorFn.call(node);
        var step;
        while (!(step = iterator.next()).done) {
          if (ReactElement.isValidElement(step.value)) {
            validateExplicitKey(step.value, parentType);
          }
        }
      }
    }
  }
}

/**
 * Given an element, validate that its props follow the propTypes definition,
 * provided by the type.
 *
 * @param {ReactElement} element
 */
function validatePropTypes(element) {
  var componentClass = element.type;
  if (typeof componentClass !== 'function') {
    return;
  }
  var name = componentClass.displayName || componentClass.name;
  if (componentClass.propTypes) {
    checkReactTypeSpec(
      componentClass.propTypes,
      element.props,
      'prop',
      name,
      element,
      null
    );
  }
  if (typeof componentClass.getDefaultProps === 'function') {
    warning(
      componentClass.getDefaultProps.isReactClassApproved,
      'getDefaultProps is only used on classic React.createClass ' +
      'definitions. Use a static property named `defaultProps` instead.'
    );
  }
}

var ReactElementValidator = {

  createElement: function(type, props, children) {
    var validType =
      typeof type === 'string' ||
      typeof type === 'function';
    // We warn in this case but don't throw. We expect the element creation to
    // succeed and there will likely be errors in render.
    if (!validType) {
      if (
        typeof type !== 'function' &&
        typeof type !== 'string'
      ) {
        var info = '';
        if (
          type === undefined ||
          typeof type === 'object' &&
          type !== null &&
          Object.keys(type).length === 0
        ) {
          info +=
            ' You likely forgot to export your component from the file ' +
            'it\'s defined in.';
        }

        var sourceInfo = getSourceInfoErrorAddendum(props);
        if (sourceInfo) {
          info += sourceInfo;
        } else {
          info += getDeclarationErrorAddendum();
        }

        info += ReactComponentTreeHook.getCurrentStackAddendum();

        warning(
          false,
          'React.createElement: type is invalid -- expected a string (for ' +
          'built-in components) or a class/function (for composite ' +
          'components) but got: %s.%s',
          type == null ? type : typeof type,
          info,
        );
      }
    }

    var element = ReactElement.createElement.apply(this, arguments);

    // The result can be nullish if a mock or a custom function is used.
    // TODO: Drop this when these are no longer allowed as the type argument.
    if (element == null) {
      return element;
    }

    // Skip key warning if the type isn't valid since our key validation logic
    // doesn't expect a non-string/function type and can throw confusing errors.
    // We don't want exception behavior to differ between dev and prod.
    // (Rendering will throw with a helpful message and as soon as the type is
    // fixed, the key warnings will appear.)
    if (validType) {
      for (var i = 2; i < arguments.length; i++) {
        validateChildKeys(arguments[i], type);
      }
    }

    validatePropTypes(element);

    return element;
  },

  createFactory: function(type) {
    var validatedFactory = ReactElementValidator.createElement.bind(
      null,
      type
    );
    // Legacy hook TODO: Warn if this is accessed
    validatedFactory.type = type;

    if (__DEV__) {
      if (canDefineProperty) {
        Object.defineProperty(
          validatedFactory,
          'type',
          {
            enumerable: false,
            get: function() {
              warning(
                false,
                'Factory.type is deprecated. Access the class directly ' +
                'before passing it to createFactory.'
              );
              Object.defineProperty(this, 'type', {
                value: type,
              });
              return type;
            },
          }
        );
      }
    }

    return validatedFactory;
  },

  cloneElement: function(element, props, children) {
    var newElement = ReactElement.cloneElement.apply(this, arguments);
    for (var i = 2; i < arguments.length; i++) {
      validateChildKeys(arguments[i], newElement.type);
    }
    validatePropTypes(newElement);
    return newElement;
  },

};

module.exports = ReactElementValidator;
<commit_msg>Removed unnecessary if (#9031)<commit_after>/**
 * Copyright 2014-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.
 *
 * @providesModule ReactElementValidator
 */

/**
 * ReactElementValidator provides a wrapper around a element factory
 * which validates the props passed to the element. This is intended to be
 * used only in DEV and could be replaced by a static type checker for languages
 * that support it.
 */

'use strict';

var ReactCurrentOwner = require('ReactCurrentOwner');
var ReactComponentTreeHook = require('ReactComponentTreeHook');
var ReactElement = require('ReactElement');

var checkReactTypeSpec = require('checkReactTypeSpec');

var canDefineProperty = require('canDefineProperty');
var getComponentName = require('getComponentName');
var getIteratorFn = require('getIteratorFn');
var warning = require('warning');

function getDeclarationErrorAddendum() {
  if (ReactCurrentOwner.current) {
    var name = getComponentName(ReactCurrentOwner.current);
    if (name) {
      return '\n\nCheck the render method of `' + name + '`.';
    }
  }
  return '';
}

function getSourceInfoErrorAddendum(elementProps) {
  if (
    elementProps !== null &&
    elementProps !== undefined &&
    elementProps.__source !== undefined
  ) {
    var source = elementProps.__source;
    var fileName = source.fileName.replace(/^.*[\\\/]/, '');
    var lineNumber = source.lineNumber;
    return '\n\nCheck your code at ' + fileName + ':' + lineNumber + '.';
  }
  return '';
}

/**
 * Warn if there's no key explicitly set on dynamic arrays of children or
 * object keys are not valid. This allows us to keep track of children between
 * updates.
 */
var ownerHasKeyUseWarning = {};

function getCurrentComponentErrorInfo(parentType) {
  var info = getDeclarationErrorAddendum();

  if (!info) {
    var parentName = typeof parentType === 'string' ?
      parentType : parentType.displayName || parentType.name;
    if (parentName) {
      info = `\n\nCheck the top-level render call using <${parentName}>.`;
    }
  }
  return info;
}

/**
 * Warn if the element doesn't have an explicit key assigned to it.
 * This element is in an array. The array could grow and shrink or be
 * reordered. All children that haven't already been validated are required to
 * have a "key" property assigned to it. Error statuses are cached so a warning
 * will only be shown once.
 *
 * @internal
 * @param {ReactElement} element Element that requires a key.
 * @param {*} parentType element's parent's type.
 */
function validateExplicitKey(element, parentType) {
  if (!element._store || element._store.validated || element.key != null) {
    return;
  }
  element._store.validated = true;

  var memoizer = ownerHasKeyUseWarning.uniqueKey || (
    ownerHasKeyUseWarning.uniqueKey = {}
  );

  var currentComponentErrorInfo = getCurrentComponentErrorInfo(parentType);
  if (memoizer[currentComponentErrorInfo]) {
    return;
  }
  memoizer[currentComponentErrorInfo] = true;

  // Usually the current owner is the offender, but if it accepts children as a
  // property, it may be the creator of the child that's responsible for
  // assigning it a key.
  var childOwner = '';
  if (element &&
      element._owner &&
      element._owner !== ReactCurrentOwner.current) {
    // Give the component that originally created this child.
    childOwner =
      ` It was passed a child from ${getComponentName(element._owner)}.`;
  }

  warning(
    false,
    'Each child in an array or iterator should have a unique "key" prop.' +
    '%s%s See https://fb.me/react-warning-keys for more information.%s',
    currentComponentErrorInfo,
    childOwner,
    ReactComponentTreeHook.getCurrentStackAddendum(element)
  );
}

/**
 * Ensure that every element either is passed in a static location, in an
 * array with an explicit keys property defined, or in an object literal
 * with valid key property.
 *
 * @internal
 * @param {ReactNode} node Statically passed child of any type.
 * @param {*} parentType node's parent's type.
 */
function validateChildKeys(node, parentType) {
  if (typeof node !== 'object') {
    return;
  }
  if (Array.isArray(node)) {
    for (var i = 0; i < node.length; i++) {
      var child = node[i];
      if (ReactElement.isValidElement(child)) {
        validateExplicitKey(child, parentType);
      }
    }
  } else if (ReactElement.isValidElement(node)) {
    // This element was passed in a valid location.
    if (node._store) {
      node._store.validated = true;
    }
  } else if (node) {
    var iteratorFn = getIteratorFn(node);
    // Entry iterators provide implicit keys.
    if (iteratorFn) {
      if (iteratorFn !== node.entries) {
        var iterator = iteratorFn.call(node);
        var step;
        while (!(step = iterator.next()).done) {
          if (ReactElement.isValidElement(step.value)) {
            validateExplicitKey(step.value, parentType);
          }
        }
      }
    }
  }
}

/**
 * Given an element, validate that its props follow the propTypes definition,
 * provided by the type.
 *
 * @param {ReactElement} element
 */
function validatePropTypes(element) {
  var componentClass = element.type;
  if (typeof componentClass !== 'function') {
    return;
  }
  var name = componentClass.displayName || componentClass.name;
  if (componentClass.propTypes) {
    checkReactTypeSpec(
      componentClass.propTypes,
      element.props,
      'prop',
      name,
      element,
      null
    );
  }
  if (typeof componentClass.getDefaultProps === 'function') {
    warning(
      componentClass.getDefaultProps.isReactClassApproved,
      'getDefaultProps is only used on classic React.createClass ' +
      'definitions. Use a static property named `defaultProps` instead.'
    );
  }
}

var ReactElementValidator = {

  createElement: function(type, props, children) {
    var validType =
      typeof type === 'string' ||
      typeof type === 'function';
    // We warn in this case but don't throw. We expect the element creation to
    // succeed and there will likely be errors in render.
    if (!validType) {
      var info = '';
      if (
        type === undefined ||
        typeof type === 'object' &&
        type !== null &&
        Object.keys(type).length === 0
      ) {
        info +=
          ' You likely forgot to export your component from the file ' +
          'it\'s defined in.';
      }

      var sourceInfo = getSourceInfoErrorAddendum(props);
      if (sourceInfo) {
        info += sourceInfo;
      } else {
        info += getDeclarationErrorAddendum();
      }

      info += ReactComponentTreeHook.getCurrentStackAddendum();

      warning(
        false,
        'React.createElement: type is invalid -- expected a string (for ' +
        'built-in components) or a class/function (for composite ' +
        'components) but got: %s.%s',
        type == null ? type : typeof type,
        info,
      );
    }

    var element = ReactElement.createElement.apply(this, arguments);

    // The result can be nullish if a mock or a custom function is used.
    // TODO: Drop this when these are no longer allowed as the type argument.
    if (element == null) {
      return element;
    }

    // Skip key warning if the type isn't valid since our key validation logic
    // doesn't expect a non-string/function type and can throw confusing errors.
    // We don't want exception behavior to differ between dev and prod.
    // (Rendering will throw with a helpful message and as soon as the type is
    // fixed, the key warnings will appear.)
    if (validType) {
      for (var i = 2; i < arguments.length; i++) {
        validateChildKeys(arguments[i], type);
      }
    }

    validatePropTypes(element);

    return element;
  },

  createFactory: function(type) {
    var validatedFactory = ReactElementValidator.createElement.bind(
      null,
      type
    );
    // Legacy hook TODO: Warn if this is accessed
    validatedFactory.type = type;

    if (__DEV__) {
      if (canDefineProperty) {
        Object.defineProperty(
          validatedFactory,
          'type',
          {
            enumerable: false,
            get: function() {
              warning(
                false,
                'Factory.type is deprecated. Access the class directly ' +
                'before passing it to createFactory.'
              );
              Object.defineProperty(this, 'type', {
                value: type,
              });
              return type;
            },
          }
        );
      }
    }

    return validatedFactory;
  },

  cloneElement: function(element, props, children) {
    var newElement = ReactElement.cloneElement.apply(this, arguments);
    for (var i = 2; i < arguments.length; i++) {
      validateChildKeys(arguments[i], newElement.type);
    }
    validatePropTypes(newElement);
    return newElement;
  },

};

module.exports = ReactElementValidator;
<|endoftext|>


<commit_before>/**
 * (c) 2012 Spredfast, Inc. BSD Licensed; see LICENSE.txt
 */
steal("jquery","can/observe/compute","jquery/lang/string","jquery/model","mustache",function($,compute) {
	"use strict";
	/*global Handlebars can */
	var toString = Object.prototype.toString;

	var _ = {
		map: function(obj,iterator,context) {
			return $.map(obj,function(value,key) {
				return iterator.call(context,value,key);
			});
		},
		keys: function(obj) {
			return _.map(obj,function(v,key) {
				return key;
			});
		},
		isFunction: function(obj) {
			return toString.call(obj) == '[object Function]';
		},
		isString: function(obj) {
			return toString.call(obj) == '[object String]';
		},
		find: function(obj,iterator) {
			for(var i = 0, l = obj.length; i < l; i++) {
				if(iterator(obj[i])) {
					return obj[i];
				}
			}
		}
	};

	_.each = _.map;

	var TMPL = /\{([^\s\{\}]+)\}/g,
		PREFIX = 'data-live-hookup',
		// XXX jQuery does strange things with data keys, so test how it maps PREFIX
		DATA_KEY = _.keys($('
').data())[0],
		hookups = {},
		lists = {},
		id = 0,
		listId = 0;

	// allows multiple hookups per element
	// $.View.hookup will only work for the first hookup on an element, but we may have multiple
	function addHookup(fn) {
		hookups[++id] = fn;
		return new Handlebars.SafeString(
			$.View.hook(runHookups) +
		'" '+PREFIX+id);
	}

	function bindings(obj,el,createBinder) {
		/*jshint validthis:true */
		var model = this;
		_.map(obj,function(value,key,obj) {
			var binding = createBinder.call(this,value,key,obj),
				compute = binding[0],
				binder = binding[1];
			compute.bind('change',binder);
			el.bind('destroyed',function() {
				compute.unbind('change',binder);
			});
			return binder;
		});
	}

	// takes a simple string that may have substitutions and figures out what
	// attributes it depends on
	function parseEvents(bindTo) {
		var attrs = [];
		if(_.isString(bindTo) && bindTo.match(TMPL)) {
			bindTo.replace(TMPL,function(match,attr) {
				attrs.push(attr);
			});
			return {attrs:attrs};
		} else {
			return bindTo;
		}
	}

	function getValue(obj,attr) {
		var attrs = parseEvents(attr);
		if(attrs.attrs) {
			var results = {};
			_.each(attrs.attrs,function(attr) {
				results[attr] = getValue(obj,attr);
			});
			return results;
		} else if(_.isFunction(obj[attrs])) {
			return obj[attrs]();
		} else if(_.isFunction(attr)) {
			return attr.call(obj);
		} else {
			return obj.attr(attrs);
		}
	}

	// add a binding based on doing substitions on the value for each name="value" pair
	// in the options hash
	// either ctx or this is bound to, depending on who has a bind function
	function bindMany(ctx,options,update) {
		/*jshint validthis:true */
		if(!ctx.bind) {
			options = ctx;
			ctx = this;
		}
		return addHookup(bindingsSetup(ctx,options.hash,update));
	}

	function bindingsSetup(ctx,options,update) {
		return function(el) {
			bindings.call(ctx,options,el,function(bindTo,key) {
				var length, not, tmpl;
				if( _.isString(bindTo) ) {
					tmpl = bindTo.match(TMPL);
					not = !tmpl && bindTo.charAt(0) === '!';
					bindTo = not ? bindTo.substring(1) : bindTo;
					length = !tmpl && bindTo.charAt(0) === '#';
					bindTo = length ? (bindTo.substring(1) + '.length') : bindTo;
				}
				function simpleUpdate() {
					var foo = length;
					var value = getValue(ctx,bindTo);
					update.call(ctx,el,
						tmpl ? $.String.sub(bindTo,value) :
							not ? !value : value,
						key);
					return value;
				}
				return [compute(simpleUpdate),simpleUpdate];
			});
		};
	}

	// bind to a single attribute change
	function bindOne(attr,options,update) {
		/*jshint validthis:true */
		var ctx = options.hash.context || this;
		return bindMany.call(this,ctx,{hash:{attr:attr}},update);
	}

	// run all the hookups attached to el
	function runHookups(el) {
		/*jshint validthis:true */
		el = $(el);
		_.each(el.data(),function(value,key) {
			var id;
			if(key.indexOf(DATA_KEY) === 0) {
				id = +(key.substring(DATA_KEY.length));
				hookups[id](el);
				delete hookups[id];
				el.removeData(key);
			}
		},this);
	}

	Handlebars.registerHelper('bindAttr',function(ctx,options) {
		return bindMany.call(this,ctx,options,function(el,value,attr) {
			el.attr(attr,""+value);
		});
	});

	Handlebars.registerHelper('bindClass',function(ctx,options) {
		return bindMany.call(this,ctx,options,function(el,condition,className) {
			el.toggleClass(""+className,!!condition);
		});
	});

	Handlebars.registerHelper('bindHtml',function(attr,options) {
		return bindOne.call(this,attr,options,function(el,html) {
			el.html(""+html);
		});
	});

	Handlebars.registerHelper('bindIf',function(attr,options) {
		var ctx = options.hash.context || this,
			templateContext = this;
		return '<span ' + addHookup(function(el) {
			var parent = $(el).parent(),
				bind = {_changed:attr},
				content = $(el);
			if(!parent.length) {
				throw new Error('Cannot use bindIf without a wrapper element.');
			}
			bindingsSetup(ctx,bind,function(parent,condition) {
				var newContent = $('
').
					html( (condition ? options.fn : options.inverse)(templateContext) ).
					children();

				if(!newContent.length) {
					newContent = $('');
				}

				content.replaceWith(newContent);
				content = newContent;
			})(parent);
		}) +'>';
	});

	// class we add ot each item to mark it as part of the bound list
	var LIST_BINDING = 'live-handlebars-list-';
	// data key for the custom item id
	var ITEM_BINDING = 'live-handlebars-list-item-id';
	Handlebars.registerHelper('bindList',function(ctx,options) {
		if(!ctx.bind) {
			options = ctx;
			ctx = this;
		}
		lists[++listId] = {};
		var id = listId, ns = '',
			sort = options.hash.sortBy;
		var sortBy = sort ? _.isFunction(sort) ? sort : function(model) {
			return sort === '.' ? model : model && model.attr && model.attr(sort);
		} : false;
		if(options.hash.namespace) {
			ns = '.' + options.hash.namespace;
		}
		function findBefore(model,el) {
			if(!sortBy) return;

			var value = sortBy(model);
			var before = _.find(el.find('.'+LIST_BINDING+id),function(item) {
				return sortBy(modelStore[$(item).data(ITEM_BINDING)].value) > value;
			});
			return before && $(before);
		}
		var modelStore = {}, modelIds = 0;
		function lookupModel(model,remove) {
			var type = model.constructor,
				idProp = type && type.id,
				id = model.attr && model.attr(idProp),
				eq = id ? function(m) {
					return m instanceof type && m.attr(idProp) === id;
				} : function(m) {
					return m === model;
				}, m;
			_.each(modelStore,function(wrapper) {
				if(eq(wrapper.value)) {
					if(remove) {
						delete modelStore[wrapper.id];
					}
					m = wrapper;
				}
			});
			if(!remove && !m) {
				m = {
					id: modelIds++,
					value: model
				};
				modelStore[m.id] = m;
			}
			return m;
		}
		function elements(model,el) {
			var wrapper = lookupModel(model,true);
			if(wrapper) {
				return el.find('.'+LIST_BINDING+id).filter(function() {
					return $(this).data(ITEM_BINDING) === wrapper.id;
				});
			}
			return $([]);
		}
		return addHookup(function(el) {
			function add(ev,models) {
				_.each(models,function(model) {
					var config = {
						appendTo: el,
						before: findBefore(model,el,modelStore),
						item: $($.View.frag(lists[id].tmpl(model))).children()
					};
					el.trigger('beforeAdd'+ns,config);
					if(config.before) {
						config.before.before( config.item );
					} else {
						config.appendTo.append( config.item );
					}
					if(model.hookup) {
						model.hookup(config.item[0]);
					}
					var wrapper = lookupModel(model);
					config.item.
						data(ITEM_BINDING,wrapper.id).
						addClass(LIST_BINDING+id).
						trigger('add'+ns);
				});
			}
			function remove(ev,models) {
				_.each(models,function(model) {
					elements(model,el).remove();
				});
			}
			ctx.bind('add',add);
			ctx.bind('remove',remove);
			el.bind('destroyed',function() {
				ctx.unbind('add',add);
				ctx.unbind('remove',remove);
				delete lists[id];
			});
			// add all the existing models
			add(null,ctx);
		});
	});

	// just saves the item template for the current list
	Handlebars.registerHelper('bindItem',function(ctx,options) {
		lists[listId].tmpl = (options || ctx).fn;
		return '';
	});

	Handlebars.registerHelper('bindProp',function(ctx,options) {
		return bindMany.call(this,ctx,options,function(el,value,prop) {
			el.prop(prop,value);
		});
	});

	Handlebars.registerHelper('bindText',function(attr,options) {
		return bindOne.call(this,attr,options,function(el,text) {
			el.text(""+text);
		});
	});

	Handlebars.registerHelper('bindVal',function(attr,options) {
		var def = options && options.hash && options.hash['default'];
		return bindOne.call(this,attr,options,function(el,val) {
			var old = el.val();
			if(old !== val) {
				// the default value comes into play if val is undefined
				// or null (hence ==) because 0 or the empty string is OK
				/*jshint eqnull:true */
				el.val(""+((val == null && def != null) ? def : val));
			}
		});
	});

	Handlebars.registerHelper('bindSelect',function(attr,options) {
		return bindOne.call(this,attr,options,function(el,val) {
			el.find('option').filter(function() {
				return String($(this).val()) === String(val);
			}).prop('selected',true);
		});
	});

	// HACK have to overwrite hookupModel because it doesn't support multiple hookups
	Handlebars.registerHelper('hookupModel',function(ctx,options) {
		var model = ctx && ctx.bind && ctx || this;
		return addHookup(function(el) {
			model.hookup(el[0]);
		});
	});

	return {
		/**
		 * Hook for building your own live bindings.
		 * Usage:
		 addBindings.call(this,{key:'attribute'},function(el,attrValue,key) {
			// update el
			// attrValue is the bound value
			// key is the key you used in attrs
		 });
		 */
		addBindings: function(attrs,update,ctx) {
			/*jshint validthis:true */
			return bindMany.call(this,ctx || this,{hash:attrs},update);
		}
	};
});
<commit_msg>fix handling when no context arg is given<commit_after>/**
 * (c) 2012 Spredfast, Inc. BSD Licensed; see LICENSE.txt
 */
steal("jquery","can/observe/compute","jquery/lang/string","jquery/model","mustache",function($,compute) {
	"use strict";
	/*global Handlebars can */
	var toString = Object.prototype.toString;

	var _ = {
		map: function(obj,iterator,context) {
			return $.map(obj,function(value,key) {
				return iterator.call(context,value,key);
			});
		},
		keys: function(obj) {
			return _.map(obj,function(v,key) {
				return key;
			});
		},
		isFunction: function(obj) {
			return toString.call(obj) == '[object Function]';
		},
		isString: function(obj) {
			return toString.call(obj) == '[object String]';
		},
		find: function(obj,iterator) {
			for(var i = 0, l = obj.length; i < l; i++) {
				if(iterator(obj[i])) {
					return obj[i];
				}
			}
		}
	};

	_.each = _.map;

	var TMPL = /\{([^\s\{\}]+)\}/g,
		PREFIX = 'data-live-hookup',
		// XXX jQuery does strange things with data keys, so test how it maps PREFIX
		DATA_KEY = _.keys($('
').data())[0],
		hookups = {},
		lists = {},
		id = 0,
		listId = 0;

	// allows multiple hookups per element
	// $.View.hookup will only work for the first hookup on an element, but we may have multiple
	function addHookup(fn) {
		hookups[++id] = fn;
		return new Handlebars.SafeString(
			$.View.hook(runHookups) +
		'" '+PREFIX+id);
	}

	function bindings(obj,el,createBinder) {
		/*jshint validthis:true */
		var model = this;
		_.map(obj,function(value,key,obj) {
			var binding = createBinder.call(this,value,key,obj),
				compute = binding[0],
				binder = binding[1];
			compute.bind('change',binder);
			el.bind('destroyed',function() {
				compute.unbind('change',binder);
			});
			return binder;
		});
	}

	// takes a simple string that may have substitutions and figures out what
	// attributes it depends on
	function parseEvents(bindTo) {
		var attrs = [];
		if(_.isString(bindTo) && bindTo.match(TMPL)) {
			bindTo.replace(TMPL,function(match,attr) {
				attrs.push(attr);
			});
			return {attrs:attrs};
		} else {
			return bindTo;
		}
	}

	function getValue(obj,attr) {
		var attrs = parseEvents(attr);
		if(attrs.attrs) {
			var results = {};
			_.each(attrs.attrs,function(attr) {
				results[attr] = getValue(obj,attr);
			});
			return results;
		} else if(_.isFunction(obj[attrs])) {
			return obj[attrs]();
		} else if(_.isFunction(attr)) {
			return attr.call(obj);
		} else {
			return obj.attr(attrs);
		}
	}

	// add a binding based on doing substitions on the value for each name="value" pair
	// in the options hash
	// either ctx or this is bound to, depending on who has a bind function
	function bindMany(ctx,options,update) {
		/*jshint validthis:true */
		if(!options) {
			options = ctx;
			ctx = this;
		}
		return addHookup(bindingsSetup(ctx,options.hash,update));
	}

	function bindingsSetup(ctx,options,update) {
		return function(el) {
			bindings.call(ctx,options,el,function(bindTo,key) {
				var length, not, tmpl;
				if( _.isString(bindTo) ) {
					tmpl = bindTo.match(TMPL);
					not = !tmpl && bindTo.charAt(0) === '!';
					bindTo = not ? bindTo.substring(1) : bindTo;
					length = !tmpl && bindTo.charAt(0) === '#';
					bindTo = length ? (bindTo.substring(1) + '.length') : bindTo;
				}
				function simpleUpdate() {
					var foo = length;
					var value = getValue(ctx,bindTo);
					update.call(ctx,el,
						tmpl ? $.String.sub(bindTo,value) :
							not ? !value : value,
						key);
					return value;
				}
				return [compute(simpleUpdate),simpleUpdate];
			});
		};
	}

	// bind to a single attribute change
	function bindOne(attr,options,update) {
		/*jshint validthis:true */
		var ctx = options.hash.context || this;
		return bindMany.call(this,ctx,{hash:{attr:attr}},update);
	}

	// run all the hookups attached to el
	function runHookups(el) {
		/*jshint validthis:true */
		el = $(el);
		_.each(el.data(),function(value,key) {
			var id;
			if(key.indexOf(DATA_KEY) === 0) {
				id = +(key.substring(DATA_KEY.length));
				hookups[id](el);
				delete hookups[id];
				el.removeData(key);
			}
		},this);
	}

	Handlebars.registerHelper('bindAttr',function(ctx,options) {
		return bindMany.call(this,ctx,options,function(el,value,attr) {
			el.attr(attr,""+value);
		});
	});

	Handlebars.registerHelper('bindClass',function(ctx,options) {
		return bindMany.call(this,ctx,options,function(el,condition,className) {
			el.toggleClass(""+className,!!condition);
		});
	});

	Handlebars.registerHelper('bindHtml',function(attr,options) {
		return bindOne.call(this,attr,options,function(el,html) {
			el.html(""+html);
		});
	});

	Handlebars.registerHelper('bindIf',function(attr,options) {
		var ctx = options.hash.context || this,
			templateContext = this;
		return '<span ' + addHookup(function(el) {
			var parent = $(el).parent(),
				bind = {_changed:attr},
				content = $(el);
			if(!parent.length) {
				throw new Error('Cannot use bindIf without a wrapper element.');
			}
			bindingsSetup(ctx,bind,function(parent,condition) {
				var newContent = $('
').
					html( (condition ? options.fn : options.inverse)(templateContext) ).
					children();

				if(!newContent.length) {
					newContent = $('');
				}

				content.replaceWith(newContent);
				content = newContent;
			})(parent);
		}) +'>';
	});

	// class we add ot each item to mark it as part of the bound list
	var LIST_BINDING = 'live-handlebars-list-';
	// data key for the custom item id
	var ITEM_BINDING = 'live-handlebars-list-item-id';
	Handlebars.registerHelper('bindList',function(ctx,options) {
		if(!ctx.bind) {
			options = ctx;
			ctx = this;
		}
		lists[++listId] = {};
		var id = listId, ns = '',
			sort = options.hash.sortBy;
		var sortBy = sort ? _.isFunction(sort) ? sort : function(model) {
			return sort === '.' ? model : model && model.attr && model.attr(sort);
		} : false;
		if(options.hash.namespace) {
			ns = '.' + options.hash.namespace;
		}
		function findBefore(model,el) {
			if(!sortBy) return;

			var value = sortBy(model);
			var before = _.find(el.find('.'+LIST_BINDING+id),function(item) {
				return sortBy(modelStore[$(item).data(ITEM_BINDING)].value) > value;
			});
			return before && $(before);
		}
		var modelStore = {}, modelIds = 0;
		function lookupModel(model,remove) {
			var type = model.constructor,
				idProp = type && type.id,
				id = model.attr && model.attr(idProp),
				eq = id ? function(m) {
					return m instanceof type && m.attr(idProp) === id;
				} : function(m) {
					return m === model;
				}, m;
			_.each(modelStore,function(wrapper) {
				if(eq(wrapper.value)) {
					if(remove) {
						delete modelStore[wrapper.id];
					}
					m = wrapper;
				}
			});
			if(!remove && !m) {
				m = {
					id: modelIds++,
					value: model
				};
				modelStore[m.id] = m;
			}
			return m;
		}
		function elements(model,el) {
			var wrapper = lookupModel(model,true);
			if(wrapper) {
				return el.find('.'+LIST_BINDING+id).filter(function() {
					return $(this).data(ITEM_BINDING) === wrapper.id;
				});
			}
			return $([]);
		}
		return addHookup(function(el) {
			function add(ev,models) {
				_.each(models,function(model) {
					var config = {
						appendTo: el,
						before: findBefore(model,el,modelStore),
						item: $($.View.frag(lists[id].tmpl(model))).children()
					};
					el.trigger('beforeAdd'+ns,config);
					if(config.before) {
						config.before.before( config.item );
					} else {
						config.appendTo.append( config.item );
					}
					if(model.hookup) {
						model.hookup(config.item[0]);
					}
					var wrapper = lookupModel(model);
					config.item.
						data(ITEM_BINDING,wrapper.id).
						addClass(LIST_BINDING+id).
						trigger('add'+ns);
				});
			}
			function remove(ev,models) {
				_.each(models,function(model) {
					elements(model,el).remove();
				});
			}
			ctx.bind('add',add);
			ctx.bind('remove',remove);
			el.bind('destroyed',function() {
				ctx.unbind('add',add);
				ctx.unbind('remove',remove);
				delete lists[id];
			});
			// add all the existing models
			add(null,ctx);
		});
	});

	// just saves the item template for the current list
	Handlebars.registerHelper('bindItem',function(ctx,options) {
		lists[listId].tmpl = (options || ctx).fn;
		return '';
	});

	Handlebars.registerHelper('bindProp',function(ctx,options) {
		return bindMany.call(this,ctx,options,function(el,value,prop) {
			el.prop(prop,value);
		});
	});

	Handlebars.registerHelper('bindText',function(attr,options) {
		return bindOne.call(this,attr,options,function(el,text) {
			el.text(""+text);
		});
	});

	Handlebars.registerHelper('bindVal',function(attr,options) {
		var def = options && options.hash && options.hash['default'];
		return bindOne.call(this,attr,options,function(el,val) {
			var old = el.val();
			if(old !== val) {
				// the default value comes into play if val is undefined
				// or null (hence ==) because 0 or the empty string is OK
				/*jshint eqnull:true */
				el.val(""+((val == null && def != null) ? def : val));
			}
		});
	});

	Handlebars.registerHelper('bindSelect',function(attr,options) {
		return bindOne.call(this,attr,options,function(el,val) {
			el.find('option').filter(function() {
				return String($(this).val()) === String(val);
			}).prop('selected',true);
		});
	});

	// HACK have to overwrite hookupModel because it doesn't support multiple hookups
	Handlebars.registerHelper('hookupModel',function(ctx,options) {
		var model = ctx && ctx.bind && ctx || this;
		return addHookup(function(el) {
			model.hookup(el[0]);
		});
	});

	return {
		/**
		 * Hook for building your own live bindings.
		 * Usage:
		 addBindings.call(this,{key:'attribute'},function(el,attrValue,key) {
			// update el
			// attrValue is the bound value
			// key is the key you used in attrs
		 });
		 */
		addBindings: function(attrs,update,ctx) {
			/*jshint validthis:true */
			return bindMany.call(this,ctx || this,{hash:attrs},update);
		}
	};
});
<|endoftext|>


<commit_before>const expect = require('../unexpected-with-plugins');
const AssetGraph = require('../../lib/AssetGraph');
const pathModule = require('path');

describe('JavaScriptDynamicImport', function() {
  it('should detect a relation', function() {
    const javaScript = new AssetGraph().addAsset({
      type: 'JavaScript',
      url: 'https://example.com/',
      text: `
        import('./bar/quux.js');
      `
    });

    expect(javaScript.outgoingRelations, 'to satisfy', [
      {
        type: 'JavaScriptDynamicImport',
        href: './bar/quux.js',
        to: { url: 'https://example.com/bar/quux.js' }
      }
    ]);
  });

  it('should update the href of a relation', function() {
    const javaScript = new AssetGraph().addAsset({
      type: 'JavaScript',
      url: 'https://example.com/',
      text: `
        import('./bar/quux.js');
      `
    });

    javaScript.outgoingRelations[0].href = './blabla.js';
    javaScript.markDirty();
    expect(javaScript.text, 'to contain', "import('./blabla.js');");
  });

  it('should keep ./ in front of relative urls', async function() {
    const assetGraph = new AssetGraph({
      root: pathModule.resolve(
        __dirname,
        '../../testdata/relations/JavaScriptDynamicImport/relative/'
      )
    });
    const [javaScript] = await assetGraph.loadAssets('index.js');
    await assetGraph.populate();
    expect(javaScript.text, 'to contain', `import('./main.js');`);
    assetGraph.findAssets({ fileName: 'main.js' })[0].url = `${
      assetGraph.root
    }static/foobar.js`;
    expect(
      javaScript.text,
      'to contain',
      `import('./static/foobar.js');`
    );
  });

  it('should put ./ in front of the url when the hrefType is changed to relative', function() {
    const assetGraph = new AssetGraph();
    const javaScript = assetGraph.addAsset({
      type: 'JavaScript',
      url: `${assetGraph.root}index.js`,
      text: `
        import('${assetGraph.root}foo.js');
      `
    });

    javaScript.outgoingRelations[0].hrefType = 'relative';
    expect(javaScript.text, 'to contain', "import('./foo.js');");
  });

  it('should leave a "bare" package name alone when moving the file', function() {
    const assetGraph = new AssetGraph();
    const javaScript = assetGraph.addAsset({
      type: 'JavaScript',
      url: `${assetGraph.root}index.js`,
      text: `
        import('foo');
      `
    });

    javaScript.url = `${assetGraph.root}somewhere/else.js`;
    expect(javaScript.text, 'to contain', "import('foo');");
  });
});
<commit_msg>prettier --write test/relations/JavaScriptDynamicImport.js<commit_after>const expect = require('../unexpected-with-plugins');
const AssetGraph = require('../../lib/AssetGraph');
const pathModule = require('path');

describe('JavaScriptDynamicImport', function() {
  it('should detect a relation', function() {
    const javaScript = new AssetGraph().addAsset({
      type: 'JavaScript',
      url: 'https://example.com/',
      text: `
        import('./bar/quux.js');
      `
    });

    expect(javaScript.outgoingRelations, 'to satisfy', [
      {
        type: 'JavaScriptDynamicImport',
        href: './bar/quux.js',
        to: { url: 'https://example.com/bar/quux.js' }
      }
    ]);
  });

  it('should update the href of a relation', function() {
    const javaScript = new AssetGraph().addAsset({
      type: 'JavaScript',
      url: 'https://example.com/',
      text: `
        import('./bar/quux.js');
      `
    });

    javaScript.outgoingRelations[0].href = './blabla.js';
    javaScript.markDirty();
    expect(javaScript.text, 'to contain', "import('./blabla.js');");
  });

  it('should keep ./ in front of relative urls', async function() {
    const assetGraph = new AssetGraph({
      root: pathModule.resolve(
        __dirname,
        '../../testdata/relations/JavaScriptDynamicImport/relative/'
      )
    });
    const [javaScript] = await assetGraph.loadAssets('index.js');
    await assetGraph.populate();
    expect(javaScript.text, 'to contain', `import('./main.js');`);
    assetGraph.findAssets({
      fileName: 'main.js'
    })[0].url = `${assetGraph.root}static/foobar.js`;
    expect(javaScript.text, 'to contain', `import('./static/foobar.js');`);
  });

  it('should put ./ in front of the url when the hrefType is changed to relative', function() {
    const assetGraph = new AssetGraph();
    const javaScript = assetGraph.addAsset({
      type: 'JavaScript',
      url: `${assetGraph.root}index.js`,
      text: `
        import('${assetGraph.root}foo.js');
      `
    });

    javaScript.outgoingRelations[0].hrefType = 'relative';
    expect(javaScript.text, 'to contain', "import('./foo.js');");
  });

  it('should leave a "bare" package name alone when moving the file', function() {
    const assetGraph = new AssetGraph();
    const javaScript = assetGraph.addAsset({
      type: 'JavaScript',
      url: `${assetGraph.root}index.js`,
      text: `
        import('foo');
      `
    });

    javaScript.url = `${assetGraph.root}somewhere/else.js`;
    expect(javaScript.text, 'to contain', "import('foo');");
  });
});
<|endoftext|>


<commit_before>import _ from 'lodash'
import React from 'react'
import { Form } from 'stardust'
import numberToWord from '../../../../src/utils/numberToWord'

describe('Field', () => {
  it('has a label', () => {
    deprecatedRender(<Form.Field label='First Name' />)
      .findTag('label')
      .textContent.should.equal('First Name')
  })

  it('renders children', () => {
    deprecatedRender(<Form.Field>yo child</Form.Field>).assertText('yo child')
  })

  it('can specify a width', () => {
    _.each(_.range(1, 17), n => {
      deprecatedRender(<Form.Field width={n} />).findClass(`${numberToWord(n)} wide`)
    })
  })
})
<commit_msg>test(Field): conformance and renders children<commit_after>import _ from 'lodash'
import React from 'react'

import Form from 'src/collections/Form/Form'
import * as common from 'test/specs/commonTests'
import numberToWord from 'src/utils/numberToWord'

describe('Field', () => {
  common.isConformant(Form.Field)
  common.rendersChildren(Form.Field)

  it('has a label', () => {
    shallow(<Form.Field label='First Name' />)
      .find('label')
      .should.contain.text('First Name')
  })

  it('can specify a width', () => {
    _.each(_.range(1, 17), n => {
      shallow(<Form.Field width={n} />)
        .should.have.className(`${numberToWord(n)} wide`)
    })
  })
})
<|endoftext|>


<commit_before>describe('FinancialLinear Scale', function() {

	it('Should register the constructor with the scale service', function() {
		var Constructor = Chart.scaleService.getScaleConstructor('financialLinear');
		expect(Constructor).not.toBe(undefined);
		expect(typeof Constructor).toBe('function');
	});

	it('Should have the correct min/max values', function() {
		var chart = window.acquireChart({
			type: 'financial',
			data: {
				datasets: [{
					yAxisID: 'yScale0',
					data: [
						{t: 'April 01 2017', o: 70, h: 100, l: 30, c: 50},
						{t: 'April 02 2017', o: 60, h: 200, l: 40, c: 90},
					]
				}]
			},
			options: {
				scales: {
					yAxes: [{
						id: 'yScale0',
						type: 'financialLinear'
					}]
				}
			}
		});

		expect(chart.scales.yScale0.max).toBe(220);
		expect(chart.scales.yScale0.min).toBe(20);
	});

});
<commit_msg>Fix failing test<commit_after>describe('FinancialLinear Scale', function() {

	it('Should register the constructor with the scale service', function() {
		var Constructor = Chart.scaleService.getScaleConstructor('financialLinear');
		expect(Constructor).not.toBe(undefined);
		expect(typeof Constructor).toBe('function');
	});

	it('Should have the correct min/max values', function() {
		var chart = window.acquireChart({
			type: 'candlestick',
			data: {
				datasets: [{
					yAxisID: 'yScale0',
					data: [
						{t: 'April 01 2017', o: 70, h: 100, l: 30, c: 50},
						{t: 'April 02 2017', o: 60, h: 200, l: 40, c: 90},
					]
				}]
			},
			options: {
				scales: {
					yAxes: [{
						id: 'yScale0',
						type: 'financialLinear'
					}]
				}
			}
		});

		expect(chart.scales.yScale0.max).toBe(220);
		expect(chart.scales.yScale0.min).toBe(20);
	});

});
<|endoftext|>


<commit_before>'use strict'

const config = require('./config')
const express = require('express')
const http = require('http')

const childProcess = require('child_process')
const path = require('path')

const forks = {}
const uuidRegEx = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/

/**
 * @param {string} sessionId
 * @return {ChildProcess}
 */
function ensureFork (sessionId) {
  let child = forks[sessionId]
  if (child == null) {
    // uncomment next line for debugging support in the child process
    // process.execArgv.push('--inspect-brk=0')

    console.log('Parent creating new child process.')
    child = childProcess.fork(path.join(__dirname, 'forkIndex.js'), process.argv[2])

    const removeChild = () => {
      console.log(`Child ${child.pid} exit.`)
      delete forks[sessionId]
    }

    child.on('exit', removeChild)
    child.on('SIGINT', function () {
      console.log(`Child ${child.pid} received SIGINT.`)
      child.exit()
    })
    child.on('SIGTERM', function () {
      console.log(`Child ${child.pid} received SIGTERM.`)
      child.exit()
    })

    forks[sessionId] = child
  }
  return child
}

function run () {
  console.log('>>> Running in PRODUCTION mode <<<\n')
  express.static.mime.define({'application/wasm': ['wasm']})
  const app = express()
  app.use(express.static(path.join(__dirname, '../../browser/dist')))

  const server = http.createServer()
  server.on('request', app)
  server.setTimeout(config['http-server']['socket-timeout'])

  server.on('upgrade', (request, socket, head) => {
    console.log('Parent received websocket upgrade request. Will delegating to child process.')
    const pathElements = request.url.split('/')
    pathElements.shift() // empty element
    const sessionId = pathElements.shift()
    if (sessionId && uuidRegEx.test(sessionId)) {
      let child = ensureFork(sessionId)
      child.send([{
        headers: request.headers,
        method: request.method,
        pathElements: pathElements
      }, head], socket)
    }
  })

  const cleanUp = () => {
    console.log('Parent exit. Cleaning up child processes.')
    for (const grSessionId in forks) {
      const child = forks[grSessionId]
      if (child != null) {
        console.log(`Parent sending child ${child.pid} SIGKILL`)
        child.disconnect()
        child.kill('SIGKILL')
      }
    }
  }

  process.on('exit', cleanUp)
  process.on('SIGINT', () => {
    console.log('Parent received SIGINT')
    process.exit()
  })
  process.on('SIGTERM', () => {
    console.log('Parent received SIGTERM')
    process.exit()
  })

  server.listen(config['http-server']['port'])
}

function main () {
  process.on('uncaughtException', (error) => {
    console.error(error)
  })
  run()
}

main()
<commit_msg>don't pass on config argument if it's undefined<commit_after>'use strict'

const config = require('./config')
const express = require('express')
const http = require('http')

const childProcess = require('child_process')
const path = require('path')

const forks = {}
const uuidRegEx = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/

/**
 * @param {string} sessionId
 * @return {ChildProcess}
 */
function ensureFork (sessionId) {
  let child = forks[sessionId]
  if (child == null) {
    // uncomment next line for debugging support in the child process
    // process.execArgv.push('--inspect-brk=0')

    console.log('Parent creating new child process.')
    const configPath = process.argv[2]
    child = childProcess.fork(path.join(__dirname, 'forkIndex.js'), configPath == null ? [] : [`${configPath}`])

    const removeChild = () => {
      console.log(`Child ${child.pid} exit.`)
      delete forks[sessionId]
    }

    child.on('exit', removeChild)
    child.on('SIGINT', function () {
      console.log(`Child ${child.pid} received SIGINT.`)
      child.exit()
    })
    child.on('SIGTERM', function () {
      console.log(`Child ${child.pid} received SIGTERM.`)
      child.exit()
    })

    forks[sessionId] = child
  }
  return child
}

function run () {
  console.log('>>> Running in PRODUCTION mode <<<\n')
  express.static.mime.define({'application/wasm': ['wasm']})
  const app = express()
  app.use(express.static(path.join(__dirname, '../../browser/dist')))

  const server = http.createServer()
  server.on('request', app)
  server.setTimeout(config['http-server']['socket-timeout'])

  server.on('upgrade', (request, socket, head) => {
    console.log('Parent received websocket upgrade request. Will delegating to child process.')
    const pathElements = request.url.split('/')
    pathElements.shift() // empty element
    const sessionId = pathElements.shift()
    if (sessionId && uuidRegEx.test(sessionId)) {
      let child = ensureFork(sessionId)
      child.send([{
        headers: request.headers,
        method: request.method,
        pathElements: pathElements
      }, head], socket)
    }
  })

  const cleanUp = () => {
    console.log('Parent exit. Cleaning up child processes.')
    for (const grSessionId in forks) {
      const child = forks[grSessionId]
      if (child != null) {
        console.log(`Parent sending child ${child.pid} SIGKILL`)
        child.disconnect()
        child.kill('SIGKILL')
      }
    }
  }

  process.on('exit', cleanUp)
  process.on('SIGINT', () => {
    console.log('Parent received SIGINT')
    process.exit()
  })
  process.on('SIGTERM', () => {
    console.log('Parent received SIGTERM')
    process.exit()
  })

  server.listen(config['http-server']['port'])
}

function main () {
  process.on('uncaughtException', (error) => {
    console.error(error)
  })
  run()
}

main()
<|endoftext|>


<commit_before>$(function () {

  var $textarea = $('textarea').textcomplete({
    // emoji strategy
    emoji: {
      match: /(^|\s):(\w*)$/,
      search: function (term, callback) {
        var regexp = new RegExp('^' + term);
        callback($.map(emojies, function (emoji) {
          return regexp.test(emoji) ? emoji : null;
        }));
      },
      template: function (value) {
        return '' + value;
      },
      replace: function (value) {
        return '$1:' + value + ': ';
      },
      maxCount: 5
    }
  });

  var textarea = $textarea.get(0);

  textarea.value = ':a';
  textarea.selectionStart = textarea.selectionEnd = 3;
  textarea.focus();
  $textarea.keyup();
});
<commit_msg>Fixed emoji that can not be selected<commit_after>$(function () {

  var $textarea = $('textarea').textcomplete({
    // emoji strategy
    emoji: {
      match: /(^|\s):([\-+\w]*)$/,
      search: function (term, callback) {
        var regexp = new RegExp('^' + term.replace(/\+/g, '\\+'));
        callback($.map(emojies, function (emoji) {
          return regexp.test(emoji) ? emoji : null;
        }));
      },
      template: function (value) {
        return '' + value;
      },
      replace: function (value) {
        return '$1:' + value + ': ';
      },
      maxCount: 5
    }
  });

  var textarea = $textarea.get(0);

  textarea.value = ':a';
  textarea.selectionStart = textarea.selectionEnd = 3;
  textarea.focus();
  $textarea.keyup();
});
<|endoftext|>