mirror of https://gitee.com/bigwinds/arangodb
383 lines
13 KiB
JavaScript
383 lines
13 KiB
JavaScript
/* global describe, it, beforeEach */
|
|
'use strict';
|
|
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
// / @brief Spec for foxx repository
|
|
// /
|
|
// / @file
|
|
// /
|
|
// / DISCLAIMER
|
|
// /
|
|
// / Copyright 2014 ArangoDB GmbH, Cologne, Germany
|
|
// /
|
|
// / Licensed under the Apache License, Version 2.0 (the "License")
|
|
// / you may not use this file except in compliance with the License.
|
|
// / You may obtain a copy of the License at
|
|
// /
|
|
// / http://www.apache.org/licenses/LICENSE-2.0
|
|
// /
|
|
// / Unless required by applicable law or agreed to in writing, software
|
|
// / distributed under the License is distributed on an "AS IS" BASIS,
|
|
// / WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// / See the License for the specific language governing permissions and
|
|
// / limitations under the License.
|
|
// /
|
|
// / Copyright holder is ArangoDB GmbH, Cologne, Germany
|
|
// /
|
|
// / @author Lucas Dohmen
|
|
// / @author Copyright 2014, ArangoDB GmbH, Cologne, Germany
|
|
// / @author Copyright 2012, triAGENS GmbH, Cologne, Germany
|
|
// //////////////////////////////////////////////////////////////////////////////
|
|
|
|
const expect = require('chai').expect;
|
|
const sinon = require('sinon');
|
|
const FoxxRepository = require('@arangodb/foxx/legacy/repository').Repository;
|
|
const FoxxModel = require('@arangodb/foxx/legacy/model').Model;
|
|
|
|
describe('Repository', function () {
|
|
const prefix = 'myApp';
|
|
let collection;
|
|
let TestModel;
|
|
|
|
beforeEach(function () {
|
|
collection = {};
|
|
TestModel = FoxxModel.extend({
|
|
forDB() {
|
|
return {fancy: 1};
|
|
}
|
|
});
|
|
});
|
|
|
|
it('should initialize with collection only', function () {
|
|
const instance = new FoxxRepository(collection);
|
|
|
|
expect(instance.collection).to.equal(collection);
|
|
expect(instance.model).to.equal(FoxxModel);
|
|
});
|
|
|
|
it('should initialize with collection and model prototype', function () {
|
|
const instance = new FoxxRepository(collection, {
|
|
model: TestModel
|
|
});
|
|
|
|
expect(instance.collection).to.equal(collection);
|
|
expect(instance.model).to.equal(TestModel);
|
|
});
|
|
|
|
it('should initialize with collection and prefix', function () {
|
|
const instance = new FoxxRepository(collection, {
|
|
prefix: prefix
|
|
});
|
|
|
|
expect(instance.collection).to.equal(collection);
|
|
expect(instance.model).to.equal(FoxxModel);
|
|
expect(instance.prefix).to.equal(prefix);
|
|
});
|
|
|
|
it('should add a method with extend', function () {
|
|
const result = Symbol();
|
|
const testFn = sinon.spy(function () {
|
|
return result;
|
|
});
|
|
const TestRepository = FoxxRepository.extend({
|
|
test: testFn
|
|
});
|
|
|
|
const instance = new TestRepository(collection);
|
|
expect(testFn.called).to.equal(false);
|
|
expect(instance.test()).to.equal(result);
|
|
expect(testFn.called).to.equal(true);
|
|
});
|
|
});
|
|
|
|
describe('Repository Indexes', function () {
|
|
it('should create indexes on instantiation', function () {
|
|
const collection = {ensureIndex: sinon.spy()};
|
|
const indexes = Object.freeze([
|
|
{type: 'skiplist', xyz: 'abcdef'},
|
|
{type: 'geo', more: 'args'},
|
|
{type: 'foo', bar: 'qux'}
|
|
]);
|
|
const TestRepository = FoxxRepository.extend({
|
|
indexes: indexes
|
|
});
|
|
|
|
const rep = new TestRepository(collection);
|
|
expect(rep).to.be.an.instanceOf(TestRepository);
|
|
|
|
expect(collection.ensureIndex.callCount).to.equal(3);
|
|
expect(collection.ensureIndex.firstCall.calledWithExactly(indexes[0])).to.equal(true);
|
|
expect(collection.ensureIndex.secondCall.calledWithExactly(indexes[1])).to.equal(true);
|
|
expect(collection.ensureIndex.thirdCall.calledWithExactly(indexes[2])).to.equal(true);
|
|
});
|
|
|
|
it('should add skiplist methods to the prototype', function () {
|
|
expect(FoxxRepository.prototype).not.to.have.a.property('range');
|
|
const TestRepository = FoxxRepository.extend({
|
|
indexes: [
|
|
{type: 'skiplist'}
|
|
]
|
|
});
|
|
|
|
expect(TestRepository.prototype.range).to.be.a('function');
|
|
});
|
|
|
|
it('should add geo methods to the prototype', function () {
|
|
expect(FoxxRepository.prototype).not.to.have.a.property('near');
|
|
expect(FoxxRepository.prototype).not.to.have.a.property('within');
|
|
const TestRepository = FoxxRepository.extend({
|
|
indexes: [
|
|
{type: 'geo'}
|
|
]
|
|
});
|
|
expect(TestRepository.prototype.near).to.be.a('function');
|
|
expect(TestRepository.prototype.within).to.be.a('function');
|
|
});
|
|
|
|
it('should add fulltext methods to the prototype', function () {
|
|
expect(FoxxRepository.prototype).not.to.have.a.property('fulltext');
|
|
const TestRepository = FoxxRepository.extend({
|
|
indexes: [
|
|
{type: 'fulltext'}
|
|
]
|
|
});
|
|
expect(TestRepository.prototype.fulltext).to.be.a('function');
|
|
});
|
|
});
|
|
|
|
describe('Repository Methods', function () {
|
|
let collection;
|
|
let repository;
|
|
|
|
beforeEach(function () {
|
|
collection = {};
|
|
repository = new FoxxRepository(collection, {model: FoxxModel});
|
|
});
|
|
|
|
describe('for adding entries', function () {
|
|
it('should allow to save', function () {
|
|
const modelData = Symbol();
|
|
const idAndRev = Symbol();
|
|
const model = new FoxxModel(modelData);
|
|
|
|
collection.type = sinon.stub().returns(2);
|
|
collection.save = sinon.stub().returns(idAndRev);
|
|
model.forDB = sinon.stub().returns(modelData);
|
|
model.set = sinon.spy();
|
|
|
|
expect(repository.save(model)).to.equal(model);
|
|
expect(collection.save.callCount).to.equal(1);
|
|
expect(collection.save.calledWithExactly(modelData)).to.equal(true);
|
|
expect(model.forDB.callCount).to.equal(1);
|
|
expect(model.forDB.calledWithExactly()).to.equal(true);
|
|
expect(model.set.callCount).to.equal(1);
|
|
expect(model.set.calledWithExactly(idAndRev)).to.equal(true);
|
|
});
|
|
});
|
|
|
|
describe('for finding entries', function () {
|
|
it('should allow to find by ID', function () {
|
|
const data = Symbol();
|
|
const id = Symbol();
|
|
|
|
collection.document = sinon.stub().returns(data);
|
|
const model = repository.byId(id);
|
|
|
|
expect(model).to.be.an.instanceOf(FoxxModel);
|
|
expect(collection.document.callCount).to.equal(1);
|
|
expect(collection.document.calledWithExactly(id)).to.equal(true);
|
|
});
|
|
|
|
it('should find by example', function () {
|
|
const example = {color: 'red'};
|
|
const cursor = {toArray: sinon.stub().returns([Symbol()])};
|
|
collection.byExample = sinon.stub().returns(cursor);
|
|
|
|
const models = repository.byExample(example);
|
|
|
|
expect(models.length).to.equal(1);
|
|
expect(models[0]).to.be.an.instanceOf(FoxxModel);
|
|
expect(collection.byExample.callCount).to.equal(1);
|
|
expect(collection.byExample.calledWithExactly(example)).to.equal(true);
|
|
});
|
|
|
|
it('should find first by example', function () {
|
|
const example = {color: 'red'};
|
|
collection.firstExample = sinon.stub().returns(Symbol());
|
|
|
|
const model = repository.firstExample(example);
|
|
|
|
expect(model).to.be.an.instanceOf(FoxxModel);
|
|
expect(collection.firstExample.callCount).to.equal(1);
|
|
expect(collection.firstExample.calledWithExactly(example)).to.equal(true);
|
|
});
|
|
|
|
it('should find all', function () {
|
|
const cursor = {
|
|
skip: sinon.stub().returnsThis(),
|
|
limit: sinon.stub().returnsThis(),
|
|
toArray: sinon.stub().returns([Symbol()])
|
|
};
|
|
collection.all = sinon.stub().returns(cursor);
|
|
|
|
const models = repository.all({skip: 4, limit: 2});
|
|
expect(models.length).to.equal(1);
|
|
expect(models[0]).to.be.an.instanceOf(FoxxModel);
|
|
expect(cursor.skip.callCount).to.equal(1);
|
|
expect(cursor.skip.calledWithExactly(4)).to.equal(true);
|
|
expect(cursor.limit.callCount).to.equal(1);
|
|
expect(cursor.limit.calledWithExactly(2)).to.equal(true);
|
|
});
|
|
});
|
|
|
|
describe('for removing entries', function () {
|
|
it('should allow to remove a model', function () {
|
|
const model = new FoxxModel();
|
|
const id = Symbol();
|
|
model.get = sinon.stub().returns(id);
|
|
collection.remove = sinon.spy();
|
|
|
|
repository.remove(model);
|
|
|
|
expect(collection.remove.callCount).to.equal(1);
|
|
expect(collection.remove.calledWithExactly(id)).to.equal(true);
|
|
expect(model.get.callCount).to.equal(1);
|
|
expect(model.get.calledWithExactly('_id')).to.equal(true);
|
|
});
|
|
|
|
it('should allow to remove by ID', function () {
|
|
const id = Symbol();
|
|
collection.remove = sinon.spy();
|
|
|
|
repository.removeById(id);
|
|
|
|
expect(collection.remove.callCount).to.equal(1);
|
|
expect(collection.remove.calledWithExactly(id)).to.equal(true);
|
|
});
|
|
|
|
it('should allow to remove by example', function () {
|
|
const example = Symbol();
|
|
collection.removeByExample = sinon.spy();
|
|
|
|
repository.removeByExample(example);
|
|
|
|
expect(collection.removeByExample.callCount).to.equal(1);
|
|
expect(collection.removeByExample.calledWithExactly(example)).to.equal(true);
|
|
});
|
|
});
|
|
|
|
describe('for replacing entries', function () {
|
|
it('should allow to replace by model', function () {
|
|
const model = new FoxxModel();
|
|
const idAndRev = Symbol();
|
|
const id = Symbol();
|
|
const data = Symbol();
|
|
model.get = sinon.stub().returns(id);
|
|
model.forDB = sinon.stub().returns(data);
|
|
model.set = sinon.spy();
|
|
collection.replace = sinon.stub().returns(idAndRev);
|
|
|
|
const result = repository.replace(model);
|
|
|
|
expect(result).to.equal(model);
|
|
expect(model.set.callCount).to.equal(1);
|
|
expect(model.set.calledWithExactly(idAndRev)).to.equal(true);
|
|
expect(collection.replace.callCount).to.equal(1);
|
|
expect(collection.replace.calledWithExactly(id, data)).to.equal(true);
|
|
expect(model.get.callCount).to.equal(1);
|
|
expect(model.get.calledWithExactly('_id')).to.equal(true);
|
|
});
|
|
|
|
it('should allow to replace by ID', function () {
|
|
const model = new FoxxModel();
|
|
const idAndRev = Symbol();
|
|
const id = Symbol();
|
|
const data = Symbol();
|
|
|
|
model.forDB = sinon.stub().returns(data);
|
|
model.set = sinon.spy();
|
|
collection.replace = sinon.stub().returns(idAndRev);
|
|
|
|
const result = repository.replaceById(id, model);
|
|
|
|
expect(result).to.equal(model);
|
|
expect(model.set.callCount).to.equal(1);
|
|
expect(model.set.calledWithExactly(idAndRev)).to.equal(true);
|
|
expect(collection.replace.callCount).to.equal(1);
|
|
expect(collection.replace.calledWithExactly(id, data)).to.equal(true);
|
|
});
|
|
|
|
it('should replace by example', function () {
|
|
const example = Symbol();
|
|
const data = Symbol();
|
|
|
|
collection.replaceByExample = sinon.spy();
|
|
repository.replaceByExample(example, data);
|
|
|
|
expect(collection.replaceByExample.callCount).to.equal(1);
|
|
expect(collection.replaceByExample.calledWithExactly(example, data)).to.equal(true);
|
|
});
|
|
});
|
|
|
|
describe('for updating entries', function () {
|
|
it('should allow to update by model', function () {
|
|
const model = new FoxxModel();
|
|
const idAndRev = Symbol();
|
|
const id = Symbol();
|
|
const data = Symbol();
|
|
const updates = Symbol();
|
|
|
|
model.get = sinon.stub().returns(id);
|
|
model.forDB = sinon.stub().returns(data);
|
|
model.set = sinon.spy();
|
|
collection.update = sinon.stub().returns(idAndRev);
|
|
|
|
const result = repository.update(model, updates);
|
|
|
|
expect(result).to.equal(model);
|
|
expect(model.set.callCount).to.equal(2);
|
|
expect(model.set.firstCall.calledWithExactly(updates)).to.equal(true);
|
|
expect(model.set.secondCall.calledWithExactly(idAndRev)).to.equal(true);
|
|
expect(collection.update.callCount).to.equal(1);
|
|
expect(collection.update.calledWithExactly(id, updates)).to.equal(true);
|
|
expect(model.get.callCount).to.equal(1);
|
|
expect(model.get.calledWithExactly('_id')).to.equal(true);
|
|
});
|
|
|
|
it('should update by id', function () {
|
|
const id = Symbol();
|
|
const updates = Symbol();
|
|
const idAndRev = Symbol();
|
|
|
|
collection.update = sinon.stub().returns(idAndRev);
|
|
repository.updateById(id, updates);
|
|
|
|
expect(collection.update.callCount).to.equal(1);
|
|
expect(collection.update.calledWithExactly(id, updates)).to.equal(true);
|
|
});
|
|
|
|
it('should update by example', function () {
|
|
const example = Symbol();
|
|
const data = Symbol();
|
|
collection.updateByExample = sinon.spy();
|
|
|
|
repository.updateByExample(example, data);
|
|
|
|
expect(collection.updateByExample.callCount).to.equal(1);
|
|
expect(collection.updateByExample.calledWithExactly(example, data, undefined)).to.equal(true);
|
|
});
|
|
});
|
|
|
|
describe('for counting entries', function () {
|
|
it('should count all', function () {
|
|
const count = Symbol();
|
|
collection.count = sinon.stub().returns(count);
|
|
|
|
const result = repository.count();
|
|
|
|
expect(result).to.equal(count);
|
|
expect(collection.count.callCount).to.equal(1);
|
|
});
|
|
});
|
|
});
|