function synonyms(t) {
  index.saveObject({objectID: 'synonyms-test', name: '589 Howard St., San Francisco'})
    .then(get('taskID'))
    .then(index.waitTask)
    .then(function() {
      return index.batchSynonyms([{
        objectID: 'city',
        type: 'synonym',
        synonyms: ['San Francisco', 'SF']
      }, {
        objectID: 'street',
        type: 'altCorrection1',
        word: 'Street',
        corrections: ['St']
      }]);
    })
    .then(get('taskID'))
    .then(index.waitTask)
    .then(_.bind(t.pass, t, 'we batch added synonyms'))
    .then(_.partial(index.searchSynonyms, {query: ''}))
    .then(function(res) {
      t.equal(res.hits.length, 2);
    })
    .then(_.partial(index.getSynonym, 'city'))
    .then(function(synonym) {
      t.equal('city', synonym.objectID);
    })
    .then(_.partial(index.search, 'Howard Street SF'))
    .then(function(res) {
      t.equal(1, res.hits.length);
      t.equal('synonyms-test', res.hits[0].objectID);
    })
    .then(_.partial(index.deleteSynonym, 'city'))
    .then(get('taskID'))
    .then(index.waitTask)
    .then(function() {
      return index.searchSynonyms({query: '', type: 'altCorrection1'});
    })
    .then(function(res) {
      t.equal(1, res.hits.length);
      t.equal('street', res.hits[0].objectID);
    })
    .then(index.clearSynonyms)
    .then(get('taskID'))
    .then(index.waitTask)
    .then(function() {
      return index.searchSynonyms();
    })
    .then(function(res) {
      t.equal(0, res.hits.length);
    })
    .then(function() {t.end();})
    .then(noop, _.bind(t.error, t));
}
function browseFrom(t) {
  t.plan(7);

  var firstHits;

  index.browse({hitsPerPage: 2})
    .then(function(content) {
      t.equal(
        content.hits.length,
        2,
        'We received two hits'
      );

      t.ok(content.cursor, 'We have a cursor');
      t.equal(content.page, 0, 'We are on the first page');
      firstHits = content.hits;
      return index.browseFrom(content.cursor);
    })
    .then(function(content) {
      t.equal(
        content.hits.length,
        2,
        'We received two more hits'
      );
      t.equal(content.page, 1, 'We are on the second page');
      t.ok(content.cursor, 'We have a new cursor');
      t.notDeepEqual(
        _.sortBy(content.hits, 'objectID'),
        _.sortBy(firstHits, 'objectID'),
        'Received hits are different'
      );
    })
    .then(noop, _.bind(t.error, t));
}
  server.listen(0, function() {
    var tunnel = require('tunnel-agent');

    var agentSettings = {
      proxy: {
        host: server.address().host,
        port: server.address().port
      }
    };

    var proxyClient = algoliasearch(appId, apiKey, {
      httpAgent: tunnel.httpsOverHttp(agentSettings)
    });
    var proxyIndex = proxyClient.initIndex(indexName);
    proxyIndex
      .browse()
      .then(end)
      .then(null, _.bind(t.error, t));

    function end(content) {
      server.close();
      proxyClient.destroy();
      t.ok(content.hits.length, 'We got some content');
    }
  });
function browseAll(t) {
  // 5 `result` events
  // 1 `end` event
  t.plan(11);

  var browsedObjects = [];

  var browser = index.browseAll({
    hitsPerPage: 10
  });

  browser.on('result', function(content) {
    browsedObjects = browsedObjects.concat(content.hits);
    t.equal(content.hits.length, 10);
    t.pass('We received a result event');
  });

  browser.on('end', function() {
    t.deepEqual(
      _.sortBy(browsedObjects, 'objectID'),
      _.sortBy(objects, 'objectID'),
      'Remote hits matches'
    );
  });

  browser.on('error', _.bind(t.fail, t));
}
mixins.collect = function (key, ...args) {
  const collectedValues = [];

  this.emit(PROVIDE_PREFIX + key,
      _.bind(collectedValues.push, collectedValues), args);

  return _.reject(collectedValues, _.isUndefined);
};
function deleteIndex(t) {
  t.plan(1);

  client.deleteIndex(indexName)
    .then(get('taskID'))
    .then(index.waitTask)
    .then(get('status'))
    .then(_.partialRight(t.equal, 'published', 'Index was deleted'))
    .then(noop, _.bind(t.error, t));
}
function saveObjects(t) {
  t.plan(1);

  index.saveObjects(objects)
    .then(get('taskID'))
    .then(index.waitTask)
    .then(get('status'))
    .then(_.partialRight(t.equal, 'published', 'Objects were saved'))
    .then(noop, _.bind(t.error, t));
}
function getObject(t) {
  t.plan(3);

  index.getObject(objects[0].objectID)
    .then(function(object) {
      t.notEqual(object, objects[0], 'Objects references are different');
      t.notEqual(object.isModified, 'yes', 'Object was not yet modified');
      t.deepEqual(object, objects[0], 'Objects have the same content');
    })
    .then(noop, _.bind(t.error, t));
}
function searchForFacetValues(t) {
  t.plan(1);

  index
    .searchForFacetValues({facetName: 'category', facetQuery: 'a'})
    .then(get('facetHits'))
    .then(function(facetHits) {
      t.ok(facetHits.length, 'We got some facet hits');
    })
    .then(noop, _.bind(t.error, t));
}
function setSettings(t) {
  t.plan(1);

  index
    .setSettings({attributesForFaceting: ['searchable(category)']})
    .then(get('taskID'))
    .then(index.waitTask)
    .then(get('status'))
    .then(_.partialRight(t.equal, 'published', 'Settings were updated'))
    .then(noop, _.bind(t.error, t));
}
Beispiel #11
0
function clearIndex(t) {
  t.plan(1);

  index.clearIndex()
    // clear index
    .then(get('taskID'))
    .then(index.waitTask)
    .then(get('status'))
    .then(_.partialRight(t.equal, 'published', 'Index was cleared'))
    // we do not use .catch since it's a reserved word in IE8
    // https://github.com/jakearchibald/es6-promise/issues/20
    .then(noop, _.bind(t.error, t));
}
Beispiel #12
0
function browse(t) {
  t.plan(1);

  // check objects are matching
  index.browse(0)
    .then(function(content) {
      t.deepEqual(
        _.sortBy(content.hits, 'objectID'),
        _.sortBy(objects, 'objectID'),
        'Remote hits matches'
      );
    })
    .then(noop, _.bind(t.error, t));
}
Beispiel #13
0
function saveObject(t) {
  t.plan(2);

  var modifiedObject = _.assign({}, objects[0], {isModified: 'yes'});

  index.saveObject(modifiedObject)
    .then(get('taskID'))
    .then(index.waitTask)
    .then(get('status'))
    .then(_.partialRight(t.equal, 'published', 'Object was saved'))
    .then(_.partial(index.getObject, objects[0].objectID))
    .then(function(object) {
      t.equal(object.isModified, 'yes', 'Object was modified');
    })
    .then(noop, _.bind(t.error, t));
}
    }, (subject, mapName) => {

    if (!subject) {
      return;
    }

    const eventMap = this[mapName];

    if (eventMap) {
      // Inherit the parent object's event map, if there is one.
      const childEventMap = eventMap;
      const ctorProto = this.constructor.prototype;

      if (ctorProto[mapName]) {
        // Temporarily delete the key so the next analogous key on the
        // prototype chain is accessible.
        delete ctorProto[mapName];

        // Grab the inherited map.
        const baseEventMap = this[mapName];

        // Augment the child's map with the parent's.
        ctorProto[mapName] = _.defaults(childEventMap, baseEventMap);
      }
    }

    for (const key in eventMap) {
      let method = eventMap[key];
      if (!_.isFunction(method)) {
        method = this[eventMap[key]];
      }

      if (!method) {
        new Error('Method "' + method + '" not found for ' + this.toString());
      }

      const match = key.match(delegateEventSplitter);
      const eventName = match[1];
      const boundMethod = _.bind(method, this);

      if (isLateralus(this) && isLateralus(subject)) {
        this.on(eventName, boundMethod);
      } else {
        this.listenTo(subject, eventName, boundMethod);
      }
    }
  });
mixins.amplify = function (emitter, eventName) {
  this.listenTo(emitter, eventName, _.bind(this.emit, this, eventName));
};
/**
 * The constructor for this method should not be called directly.  Instead, use
 * the `{@link Lateralus.mixins#addComponent}` mixin method:
 *
 *     const App = Lateralus.beget(function () {
 *       Lateralus.apply(this, arguments);
 *     });
 *
 *     const app = new App(document.getElementById('app'));
 *     const component = app.addComponent(Lateralus.Component);
 *
 *     console.log(component instanceof Lateralus.Component); // true
 * @class Lateralus.Component
 * @param {Lateralus} lateralus
 * @param {Object} options Values to attach to this `{@link
 * Lateralus.Component}` instance.  This object also get passed to the `{@link
 * Lateralus.Component.initialize}` method, if one is defined.
 * @param {Object} [options.modelAttributes] Any attributes to pre-populate
 * the `{@link Lateralus.Component.Model}`
 * instance with, if there is one.
 * @param {Object} [options.modelOptions] Any parameters to pass to the
 * `{@link Lateralus.Component.Model}`
 * instance, if there is one.
 * @param {Object} viewOptions The `options` Object to pass to the
 * `{@link Lateralus.Component.View}`
 * constructor.
 * @param {Lateralus.Component} [opt_parentComponent] The parent component of
 * this component, if any.
 * @mixes http://backbonejs.org/#Events
 * @mixes Lateralus.mixins
 * @constructs Lateralus.Component
 */
function Component (lateralus, options, viewOptions, opt_parentComponent) {

  /**
   * A reference to the central {@link Lateralus} instance.
   * @member Lateralus.Component#lateralus
   * @type {Lateralus}
   * @final
   */
  this.lateralus = lateralus;

  /**
   * If a `{@link Lateralus.Component}` has `mixins` defined on its `prototype`
   * before it is instantiated, the objects within `mixins` will be merged into
   * this `{@link  "Lateralus.Component}` at instantiation-time with `{@link
   * Lateralus.Component/mixin}`.
   * @property mixins
   * @type {Object|Array<Object>|undefined}
   * @default undefined
   */
  if (this.mixins) {
    _.each(this.mixins, _.bind(this.mixin, this));
  }

  if (opt_parentComponent) {
    /**
     * If this is a subcomponent of another `{@link Lateralus.Component}`, this
     * property is a reference to the parent `{@link Lateralus.Component}`.
     * @member Lateralus.Component#parentComponent
     * @type {Lateralus.Component|undefined}
     * @default undefined
     */
    this.parentComponent = opt_parentComponent;
  }

  /**
   * The `{@link Lateralus.Component.View}` constructor to use, if any.  If
   * this `{@link Lateralus.Component}` is intended to render to the DOM,
   * `View` should be defined on the `prototype` before instantiating:
   *
   *     const ExtendedComponent = Lateralus.Component.extend({
   *       name: 'extended',
   *       View: Lateralus.Component.View,
   *       template: '<div></div>'
   *     });
   * @member Lateralus.Component#View
   * @type {Lateralus.Component.View|undefined}
   * @default undefined
   */
  if (this.View) {
    const augmentedViewOptions = viewOptions;

    // A model instance provided to addComponent takes precendence over the
    // prototype property.
    if (this.Model && !viewOptions.model) {

      options.modelOptions = _.extend(options.modelOptions || {}, {
        lateralus: lateralus,
        component: this
      });

      this.model = new this.Model(
        options.modelAttributes,
        options.modelOptions
      );

      augmentedViewOptions.model = this.model;
    }

    /**
     * If `{@link Lateralus.Component.View}` is defined, this is an instance of
     * that constructor.
     * @member Lateralus.Component#view
     * @type {Lateralus.Component.View|undefined}
     * @default undefined
     */
    this.view = new this.View(
        lateralus,
        this,
        augmentedViewOptions
      );
  }

  _.extend(this, options);

  /**
   * A method to be called when this `{@link Lateralus.Component}` has been set
   * up.
   * @member Lateralus.Component#initialize
   * @type {Function|undefined}
   * @default undefined
   */
  if (this.initialize) {
    this.initialize(options);
  }

  this.delegateLateralusEvents();
}