| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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. |
| */ |
| |
| /** |
| * @author Jorge Bay Gondra |
| */ |
| |
| import assert from 'assert'; |
| import { expect } from 'chai'; |
| import { Graph, Vertex } from '../../lib/structure/graph.js'; |
| import anon from '../../lib/process/anonymous-traversal.js'; |
| import { P, order, direction, Traverser, Traversal } from '../../lib/process/traversal.js'; |
| import { statics } from '../../lib/process/graph-traversal.js'; |
| const V = statics.V; |
| |
| import { TraversalStrategies } from '../../lib/process/traversal-strategy.js'; |
| import { RemoteConnection } from '../../lib/driver/remote-connection.js'; |
| |
| describe('Traversal', function () { |
| |
| |
| describe('#next()', function () { |
| it('should apply the strategies and return a Promise with the iterator item', function () { |
| const strategyMock = { |
| apply: function (traversal) { |
| traversal.results = [ new Traverser(1, 1), new Traverser(2, 1) ]; |
| return Promise.resolve(); |
| } |
| }; |
| const strategies = new TraversalStrategies(); |
| strategies.addStrategy(strategyMock); |
| const traversal = new Traversal(null, strategies, null); |
| return traversal.next() |
| .then(function (item) { |
| assert.strictEqual(item.value, 1); |
| assert.strictEqual(item.done, false); |
| return traversal.next(); |
| }) |
| .then(function (item) { |
| assert.strictEqual(item.value, 2); |
| assert.strictEqual(item.done, false); |
| return traversal.next(); |
| }) |
| .then(function (item) { |
| assert.strictEqual(item.value, null); |
| assert.strictEqual(item.done, true); |
| return traversal.next(); |
| }); |
| }); |
| |
| it('should support bulk', function () { |
| const strategyMock = { |
| apply: function (traversal) { |
| traversal.results = [ new Traverser(1, 2), new Traverser(2, 1) ]; |
| return Promise.resolve(); |
| } |
| }; |
| const strategies = new TraversalStrategies(); |
| strategies.addStrategy(strategyMock); |
| const traversal = new Traversal(null, strategies, null); |
| return traversal.next() |
| .then(function (item) { |
| assert.strictEqual(item.value, 1); |
| assert.strictEqual(item.done, false); |
| return traversal.next(); |
| }) |
| .then(function (item) { |
| assert.strictEqual(item.value, 1); |
| assert.strictEqual(item.done, false); |
| return traversal.next(); |
| }) |
| .then(function (item) { |
| assert.strictEqual(item.value, 2); |
| assert.strictEqual(item.done, false); |
| return traversal.next(); |
| }) |
| .then(function (item) { |
| assert.strictEqual(item.value, null); |
| assert.strictEqual(item.done, true); |
| return traversal.next(); |
| }); |
| }); |
| }); |
| |
| if (Symbol.asyncIterator) { |
| describe('@@asyncIterator', function () { |
| it('should expose the async iterator', function () { |
| const traversal = new Traversal(null, null, null); |
| assert.strictEqual(typeof traversal[Symbol.asyncIterator], 'function'); |
| }); |
| }); |
| } |
| |
| describe('#toList()', function () { |
| |
| it('should apply the strategies and return a Promise with an array', function () { |
| const strategyMock = { |
| apply: function (traversal) { |
| traversal.results = [ new Traverser('a', 1), new Traverser('b', 1) ]; |
| return Promise.resolve(); |
| } |
| }; |
| const strategies = new TraversalStrategies(); |
| strategies.addStrategy(strategyMock); |
| const traversal = new Traversal(null, strategies, null); |
| return traversal.toList().then(function (list) { |
| assert.ok(list); |
| assert.deepEqual(list, [ 'a', 'b' ]); |
| }); |
| }); |
| |
| it('should return an empty array when traversers is empty', function () { |
| const strategyMock = { |
| apply: function (traversal) { |
| traversal.results = []; |
| return Promise.resolve(); |
| } |
| }; |
| const strategies = new TraversalStrategies(); |
| strategies.addStrategy(strategyMock); |
| const traversal = new Traversal(null, strategies, null); |
| return traversal.toList().then(function (list) { |
| assert.ok(Array.isArray(list)); |
| assert.strictEqual(list.length, 0); |
| }); |
| }); |
| |
| it('should support bulk', function () { |
| const strategyMock = { |
| apply: function (traversal) { |
| traversal.results = [ new Traverser(1, 1), new Traverser(2, 3), new Traverser(3, 2), |
| new Traverser(4, 1) ]; |
| return Promise.resolve(); |
| } |
| }; |
| const strategies = new TraversalStrategies(); |
| strategies.addStrategy(strategyMock); |
| const traversal = new Traversal(null, strategies, null); |
| return traversal.toList() |
| .then(list => { |
| expect(list).to.have.members([1, 2, 2, 2, 3, 3, 4]); |
| }); |
| }); |
| }); |
| |
| describe('#iterate()', function () { |
| it('should apply the strategies and return a Promise', function () { |
| let applied = false; |
| const strategyMock = { |
| apply: function (traversal) { |
| applied = true; |
| traversal.results = [ new Traverser('a', 1), new Traverser('b', 1) ]; |
| return Promise.resolve(); |
| } |
| }; |
| const strategies = new TraversalStrategies(); |
| strategies.addStrategy(strategyMock); |
| const traversal = new Traversal(null, strategies); |
| return traversal.iterate().then(() => { |
| assert.strictEqual(applied, true); |
| }); |
| }); |
| }); |
| |
| describe('P#toString()', function () { |
| it('convert to string representation with P', function () { |
| assert.strictEqual(P.gt(18).toString(), 'gt(18)'); |
| }); |
| |
| it('convert to string representation with P.within', function () { |
| assert.strictEqual(P.within('a', 'b').toString(), "within(['a', 'b'])"); |
| }); |
| |
| it('convert to string representation with P.within array', function () { |
| assert.strictEqual(P.within(['a', 'b']).toString(), "within(['a', 'b'])"); |
| }); |
| }); |
| |
| describe("build", function() { |
| it('should only allow anonymous child traversals', function() { |
| const g = anon.traversal().with_(new Graph()); |
| assert.doesNotThrow(function() { |
| g.V(0).addE("self").to(V(1)) |
| }); |
| |
| assert.throws(function() { |
| g.V(0).addE("self").to(g.V(1)) |
| }); |
| }) |
| }); |
| |
| // TODO:: Re-enable after transactions |
| // describe('child transactions', function() { |
| // it('should not support child transactions', function() { |
| // const g = anon.traversal().with_(new MockRemoteConnection()); |
| // const tx = g.tx(); |
| // assert.throws(function() { |
| // tx.begin().tx(); |
| // }); |
| // }); |
| // }); |
| // |
| // describe('not opened transactions', function() { |
| // it('should not allow commit for not opened transactions', async function() { |
| // const g = anon.traversal().withRemote(new MockRemoteConnection()); |
| // const tx = g.tx(); |
| // try { |
| // await tx.commit(); |
| // assert.fail("should throw error"); |
| // } catch (err) { |
| // assert.strictEqual('Cannot commit a transaction that is not started', err.message); |
| // } |
| // }); |
| // it('should not allow rollback for not opened transactions', async function() { |
| // const g = anon.traversal().withRemote(new MockRemoteConnection()); |
| // const tx = g.tx(); |
| // try { |
| // await tx.rollback(); |
| // assert.fail("should throw error"); |
| // } catch (err) { |
| // assert.strictEqual('Cannot rollback a transaction that is not started', err.message); |
| // } |
| // }); |
| // }); |
| // |
| // describe('tx#begin()', function() { |
| // it("should not allow a transaction to begin more than once", function() { |
| // const g = anon.traversal().with_(new MockRemoteConnection()); |
| // const tx = g.tx(); |
| // tx.begin(); |
| // assert.throws(function () { |
| // tx.begin(); |
| // }); |
| // }); |
| // }); |
| |
| |
| }); |
| |
| class MockRemoteConnection extends RemoteConnection { |
| constructor(bound = false) { |
| super('http://localhost:9998/gremlin'); |
| this._bound = bound; |
| } |
| |
| get isSessionBound() { |
| return this._bound; |
| } |
| |
| submit(gremlinLang) { |
| return Promise.resolve(undefined); |
| } |
| |
| createSession() { |
| return new MockRemoteConnection(true); |
| } |
| } |