|
|
@@ -0,0 +1,235 @@
|
|
|
+
|
|
|
+var assert = require("assert"),
|
|
|
+DocumentSource = require("../../../../lib/pipeline/documentSources/DocumentSource"),
|
|
|
+ProjectDocumentSource = require("../../../../lib/pipeline/documentSources/ProjectDocumentSource"),
|
|
|
+CursorDocumentSource = require("../../../../lib/pipeline/documentsources/CursorDocumentSource"),
|
|
|
+Cursor = require("../../../../lib/Cursor");
|
|
|
+
|
|
|
+//HELPERS
|
|
|
+var assertExhausted = function assertExhausted(pds) {
|
|
|
+ assert.ok(pds.eof());
|
|
|
+ assert.ok(!pds.advance());
|
|
|
+};
|
|
|
+
|
|
|
+/**
|
|
|
+* Tests if the given rep is the same as what the pds resolves to as JSON.
|
|
|
+* MUST CALL WITH A PDS AS THIS (e.g. checkJsonRepresentation.call(this, rep) where this is a PDS)
|
|
|
+**/
|
|
|
+var checkJsonRepresentation = function checkJsonRepresentation(self, rep) {
|
|
|
+ var pdsRep = {};
|
|
|
+ self.sourceToJson(pdsRep, true);
|
|
|
+ assert.deepEqual(pdsRep, rep);
|
|
|
+};
|
|
|
+
|
|
|
+var createProject = function createProject(projection) {
|
|
|
+ //let projection be optional
|
|
|
+ if(!projection){
|
|
|
+ projection = {a:true};
|
|
|
+ }
|
|
|
+ var spec = {"$project": projection},
|
|
|
+ specElement = projection,
|
|
|
+ pds = new ProjectDocumentSource(),
|
|
|
+ project = pds.createFromJson(specElement);
|
|
|
+ checkJsonRepresentation(project, spec);
|
|
|
+ return project;
|
|
|
+};
|
|
|
+
|
|
|
+//TESTS
|
|
|
+module.exports = {
|
|
|
+
|
|
|
+ "ProjectDocumentSource": {
|
|
|
+
|
|
|
+ "constructor()": {
|
|
|
+
|
|
|
+ "should throw Error when constructing with args": function testConstructor(){
|
|
|
+ assert.throws(function(){
|
|
|
+ new ProjectDocumentSource({ctx: [1,2]});
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ "#getSourceName()": {
|
|
|
+
|
|
|
+ "should return the correct source name; $project": function testSourceName(){
|
|
|
+ var pds = new ProjectDocumentSource();
|
|
|
+ assert.strictEqual(pds.getSourceName(), "$project");
|
|
|
+ }
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ "#eof()": {
|
|
|
+
|
|
|
+ "should return same as this.pSource.eof": function testEOF(){
|
|
|
+ var pds = new ProjectDocumentSource();
|
|
|
+ pds.setSource({
|
|
|
+ eof: function eof() {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ assert.ok(pds.eof());
|
|
|
+ },
|
|
|
+
|
|
|
+ "should return !eof == true when a document is still in cursor": function testNotEOFTrueIfDocPresent() {
|
|
|
+ var cwc = new CursorDocumentSource.CursorWithContext();
|
|
|
+ cwc._cursor = new Cursor( [{a: 1}] );
|
|
|
+ var cds = new CursorDocumentSource(cwc);
|
|
|
+ var pds = new ProjectDocumentSource();
|
|
|
+ pds.setSource(cds);
|
|
|
+ assert.ok(!pds.eof());
|
|
|
+ }
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ "#advance()": {
|
|
|
+
|
|
|
+ "should return same as this.psource.advance": function testCallsThisPSourceAdvance() {
|
|
|
+ var pds = new ProjectDocumentSource();
|
|
|
+ pds.setSource({
|
|
|
+ advance: function advance() {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ assert.ok(pds.advance());
|
|
|
+ },
|
|
|
+
|
|
|
+ /*
|
|
|
+ "can retrieve values from the project when advance is first function call": function testAdvanceFirst() {
|
|
|
+ var cwc = new CursorDocumentSource.CursorWithContext();
|
|
|
+ var input = [{_id: 0, a: 1}, {_id: 1, a: 2}];
|
|
|
+ cwc._cursor = new Cursor( input );
|
|
|
+ var cds = new CursorDocumentSource(cwc);
|
|
|
+ var pds = createProject();
|
|
|
+ pds.setSource(cds);
|
|
|
+ assert.ok(pds.advance());
|
|
|
+ assert.equal(2, pds.getCurrent().a);
|
|
|
+ }
|
|
|
+ */
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ /* TODO : copy mongo tests, they will probably be more involved */
|
|
|
+ "#getCurrent()": {
|
|
|
+
|
|
|
+ /*
|
|
|
+ "should work when getCurrent is the first function call": function getCurrentCalledFirst() {
|
|
|
+ var cwc = new CursorDocumentSource.CursorWithContext();
|
|
|
+ var input = [{_id: 0, a: 1}];
|
|
|
+ cwc._cursor = new Cursor( input );
|
|
|
+ var cds = new CursorDocumentSource(cwc);
|
|
|
+ var pds = createProject();
|
|
|
+ pds.setSource(cds);
|
|
|
+ assert.ok(pds.getCurrent());
|
|
|
+ assert.equal(1, pds.getCurrent().a);
|
|
|
+ }
|
|
|
+ */
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ "combined": {
|
|
|
+
|
|
|
+ /*
|
|
|
+ "The a and c.d fields are included but the b field is not": function testFullProject1() {
|
|
|
+ var cwc = new CursorDocumentSource.CursorWithContext();
|
|
|
+ var input = [{_id:0,a:1,b:1,c:{d:1}}];
|
|
|
+ cwc._cursor = new Cursor( input );
|
|
|
+ var cds = new CursorDocumentSource(cwc);
|
|
|
+ var pds = createProject({a:true, c:{d:true}});
|
|
|
+ pds.setSource(cds);
|
|
|
+ assert.ok(pds.getCurrent());
|
|
|
+ assert.equal(1, pds.getCurrent().a);
|
|
|
+ assert.ok(!pds.getCurrent().b);
|
|
|
+ assert.equal(0, pds.getCurrent()._id);
|
|
|
+ assert.equal(1, pds.getCurrent().c.d);
|
|
|
+ },
|
|
|
+
|
|
|
+ "Two documents": function testTwoDocumentsProject() {
|
|
|
+ var cwc = new CursorDocumentSource.CursorWithContext();
|
|
|
+ var input = [{a:1, b:2}, {a:3, b:4}];
|
|
|
+ cwc._cursor = new Cursor( input );
|
|
|
+ var cds = new CursorDocumentSource(cwc);
|
|
|
+ var pds = createProject({a:true, c:{d:true}});
|
|
|
+ pds.setSource(cds);
|
|
|
+ assert.ok(!pds.eof());
|
|
|
+ assert.equal(1, pds.getCurrent().a);
|
|
|
+ assert.ok(!pds.getCurrent().b);
|
|
|
+ assert.equal(0, pds.getCurrent()._id);
|
|
|
+ assert.equal(1, pds.getCurrent().c.d);
|
|
|
+ assert.ok(pds.advance());
|
|
|
+ assert.ok(!pds.eof());
|
|
|
+ assert.equal(3, pds.getCurrent().a);
|
|
|
+ assert.ok(!pds.getCurrent().b);
|
|
|
+ assert.ok(!project.advance());
|
|
|
+ assertExhausted(pds);
|
|
|
+ }
|
|
|
+ */
|
|
|
+ },
|
|
|
+
|
|
|
+ "#optimize()": {
|
|
|
+
|
|
|
+ "Optimize the projection": function optimizeProject() {
|
|
|
+ var pds = createProject({a:{$and: [true]}});
|
|
|
+ pds.optimize();
|
|
|
+ checkJsonRepresentation(pds, {$project:{a:{$const:true}}});
|
|
|
+ }
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ "#createFromJson()": {
|
|
|
+
|
|
|
+ "should error if called with non-object": function testNonObjectPassed() {
|
|
|
+ //String as arg
|
|
|
+ assert.throws(function() {
|
|
|
+ var pds = createProject("not an object");
|
|
|
+ });
|
|
|
+ //Date as arg
|
|
|
+ assert.throws(function() {
|
|
|
+ var pds = createProject(new Date());
|
|
|
+ });
|
|
|
+ //Array as arg
|
|
|
+ assert.throws(function() {
|
|
|
+ var pds = createProject([]);
|
|
|
+ });
|
|
|
+ //Empty args
|
|
|
+ assert.throws(function() {
|
|
|
+ var pds = new ProjectDocumentSource();
|
|
|
+ pds = pds.createFromJson();
|
|
|
+ });
|
|
|
+ //Top level operator
|
|
|
+ assert.throws(function() {
|
|
|
+ var pds = createProject({$add: []});
|
|
|
+ });
|
|
|
+ //Invalid spec
|
|
|
+ assert.throws(function() {
|
|
|
+ var pds = createProject({a:{$invalidOperator:1}});
|
|
|
+ });
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ "#getDependencies()": {
|
|
|
+
|
|
|
+ /*
|
|
|
+ "should return a new ProjectDocumentSource object from an input object": function createTest(){
|
|
|
+ var cwc = new CursorDocumentSource.CursorWithContext();
|
|
|
+ var input = [{a:true,x:'$b',y:{$and:['$c','$d']}}];
|
|
|
+ var pds = createProject(input);
|
|
|
+ var dependencies = {};
|
|
|
+ assert.equals(DocumentSource.GetDepsReturn.EXHAUSTIVE, pds.getDependencies(dependencies));
|
|
|
+ assert.equals(5, dependencies.length);
|
|
|
+ assert.ok(dependencies._id);
|
|
|
+ assert.ok(dependencies.a);
|
|
|
+ assert.ok(dependencies.b);
|
|
|
+ assert.ok(dependencies.c);
|
|
|
+ assert.ok(dependencies.d);
|
|
|
+ }
|
|
|
+ */
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+};
|
|
|
+
|
|
|
+if (!module.parent)(new(require("mocha"))()).ui("exports").reporter("spec").addFile(__filename).run(process.exit);
|