// TODO: This file was created by bulk-decaffeinate. // Sanity-check the conversion and remove this comment. import _ from "lodash" import chai from "chai" const { assert } = chai function error(err: any) { console.log(err) return assert.fail(JSON.stringify(err)) } // Runs queries on @col which must be a collection (with a:, b:, c:, geo:, stringarr: ) // When present: // c.arrstr is an array of string values // c.arrint is an array of integer values // @reset(done) must truncate the collection export default function () { before(function (this: any) { // Test a filter to return specified rows (in order) return (this.testFilter = function (filter: any, ids: any, done: any) { return this.col.find(filter, { sort: ["_id"] }).fetch(function (results: any) { assert.deepEqual(_.map(results, "_id"), ids) done() }) }) }) context("With sample rows", function () { beforeEach(function (done: any) { return this.reset(() => { return this.col.upsert({ _id: "1", a: "Alice", b: 1, c: { d: 1, e: 2 } }, () => { return this.col.upsert({ _id: "2", a: "Charlie", b: 2, c: { d: 2, e: 3 } }, () => { return this.col.upsert({ _id: "3", a: "Bob", b: 3 }, () => done()) }) }) }) }) it("finds all rows", function (done: any) { return this.col.find({}).fetch(function (results: any) { assert.equal(results.length, 3) done() }) }) it("finds all rows (promise)", async function () { const results = await this.col.find({}).fetch() assert.equal(results.length, 3) }) it("finds all rows with options", function (done: any) { return this.col.find({}, {}).fetch(function (results: any) { assert.equal(3, results.length) done() }) }) it("finds all rows with options (promise)", async function () { const results = await this.col.find({}, {}).fetch() assert.equal(3, results.length) }) it("filters by id", function (done: any) { return this.testFilter({ _id: "1" }, ["1"], done) }) it("filters by string", function (done: any) { return this.testFilter({ a: "Alice" }, ["1"], done) }) it("filters by $in string", function (done: any) { return this.testFilter({ a: { $in: ["Alice", "Charlie"] } }, ["1", "2"], done) }) it("filters by number", function (done: any) { return this.testFilter({ b: 2 }, ["2"], done) }) it("filters by $in number", function (done: any) { return this.testFilter({ b: { $in: [2, 3] } }, ["2", "3"], done) }) it("filters by $regex", function (done: any) { return this.testFilter({ a: { $regex: "li" } }, ["1", "2"], done) }) it("filters by $regex case-sensitive", function (done: any) { return this.testFilter({ a: { $regex: "A" } }, ["1"], done) }) it("filters by $regex case-insensitive", function (done: any) { return this.testFilter({ a: { $regex: "A", $options: "i" } }, ["1", "2"], done) }) it("filters by $or", function (done: any) { return this.testFilter({ $or: [{ b: 1 }, { b: 2 }] }, ["1", "2"], done) }) it("filters by path", function (done: any) { return this.testFilter({ "c.d": 2 }, ["2"], done) }) it("filters by $ne", function (done: any) { return this.testFilter({ b: { $ne: 2 } }, ["1", "3"], done) }) it("filters by $gt", function (done: any) { return this.testFilter({ b: { $gt: 1 } }, ["2", "3"], done) }) it("filters by $lt", function (done: any) { return this.testFilter({ b: { $lt: 3 } }, ["1", "2"], done) }) it("filters by $gte", function (done: any) { return this.testFilter({ b: { $gte: 2 } }, ["2", "3"], done) }) it("filters by $lte", function (done: any) { return this.testFilter({ b: { $lte: 2 } }, ["1", "2"], done) }) it("filters by $not", function (done: any) { return this.testFilter({ b: { $not: { $lt: 3 } } }, ["3"], done) }) it("filters by $or", function (done: any) { return this.testFilter({ $or: [{ b: 3 }, { b: 1 }] }, ["1", "3"], done) }) it("filters by $exists: true", function (done: any) { return this.testFilter({ c: { $exists: true } }, ["1", "2"], done) }) it("filters by $exists: false", function (done: any) { return this.testFilter({ c: { $exists: false } }, ["3"], done) }) it("includes fields", function (done: any) { return this.col.find({ _id: "1" }, { fields: { a: 1 } }).fetch(function (results: any) { assert.deepEqual(results[0], { _id: "1", a: "Alice" }) done() }) }) it("includes subfields", function (done: any) { return this.col.find({ _id: "1" }, { fields: { "c.d": 1 } }).fetch(function (results: any) { assert.deepEqual(results[0], { _id: "1", c: { d: 1 } }) done() }) }) it("ignores non-existent subfields", function (done: any) { return this.col.find({ _id: "1" }, { fields: { "x.y": 1 } }).fetch(function (results: any) { assert.deepEqual(results[0], { _id: "1" }) done() }) }) it("excludes fields", function (done: any) { return this.col.find({ _id: "1" }, { fields: { a: 0 } }).fetch(function (results: any) { assert.isUndefined(results[0].a) assert.equal(results[0].b, 1) done() }) }) it("excludes subfields", function (done: any) { return this.col.find({ _id: "1" }, { fields: { "c.d": 0 } }).fetch(function (results: any) { assert.deepEqual(results[0].c, { e: 2 }) done() }) }) it("finds one row", function (done: any) { return this.col.findOne({ _id: "2" }, function (result: any) { assert.equal("Charlie", result.a) done() }) }) it("finds one row (promise)", async function () { const result = await this.col.findOne({ _id: "2" }) assert.equal("Charlie", result.a) }) it("removes item", function (done: any) { return this.col.remove( "2", () => { return this.col.find({}).fetch(function (results: any) { let needle, needle1 let result assert.equal(2, results.length) assert( ((needle = "1"), (() => { const result1 = [] for (result of results) { result1.push(result._id) } return result1 })().includes(needle)) ) assert( ((needle1 = "2"), !(() => { const result2 = [] for (result of results) { result2.push(result._id) } return result2 })().includes(needle1)) ) done() }, error) }, error ) }) it("removes item (promise)", async function () { await this.col.remove("2") const results = await this.col.find({}).fetch() assert.equal(2, results.length) let needle, needle1 let result assert( ((needle = "1"), (() => { const result1 = [] for (result of results) { result1.push(result._id) } return result1 })().includes(needle)) ) assert( ((needle1 = "2"), !(() => { const result2 = [] for (result of results) { result2.push(result._id) } return result2 })().includes(needle1)) ) }) it("removes non-existent item", function (done: any) { return this.col.remove("999", () => { return this.col.find({}).fetch(function (results: any) { assert.equal(3, results.length) done() }) }) }) it("sorts ascending", function (done: any) { return this.col.find({}, { sort: ["a"] }).fetch(function (results: any) { assert.deepEqual(_.map(results, "_id"), ["1", "3", "2"]) done() }) }) it("sorts descending", function (done: any) { return this.col.find({}, { sort: [["a", "desc"]] }).fetch(function (results: any) { assert.deepEqual(_.map(results, "_id"), ["2", "3", "1"]) done() }) }) it("limits", function (done: any) { return this.col.find({}, { sort: ["a"], limit: 2 }).fetch(function (results: any) { assert.deepEqual(_.map(results, "_id"), ["1", "3"]) done() }) }) it("skips", function (done: any) { return this.col.find({}, { sort: ["a"], skip: 2 }).fetch(function (results: any) { assert.deepEqual(_.map(results, "_id"), ["2"]) done() }) }) // MemoryDb is much faster if we relax this constraint it("fetches independent copies", function (done: any) { return this.col.findOne({ _id: "2" }, (result1: any) => { return this.col.findOne({ _id: "2" }, function (result2: any) { assert(result1 !== result2) done() }) }) }) // MemoryDb is much faster if we relax this constraint it("upsert keeps independent copies", function (done: any) { const doc: any = { _id: "2" } return this.col.upsert(doc, (item: any) => { doc.a = "xyz" item.a = "xyz" return this.col.findOne({ _id: "2" }, function (doc2: any) { assert(doc !== doc2) assert(doc2.a !== "xyz") done() }) }) }) // MemoryDb is much faster if we relax this constraint it("upsert keeps independent copies (promise)", async function () { const doc: any = { _id: "2" } const item = await this.col.upsert(doc) doc.a = "xyz" item.a = "xyz" const doc2 = await this.col.findOne({ _id: "2" }) assert(doc !== doc2) assert(doc2.a !== "xyz") }) it("upsert returns doc", function (done: any) { const doc: any = { _id: "2" } this.col.upsert(doc, (item: any) => { assert.equal(item._id, "2") done() }, () => { assert.fail() }) }) it("upsert returns doc (promise)", async function () { const doc: any = { _id: "2" } const item = await this.col.upsert(doc) assert.equal(item._id, "2") }) it("adds _id to rows", function (done: any) { return this.col.upsert({ a: "1" }, function (item: any) { assert.property(item, "_id") assert.lengthOf(item._id, 32) done() }) }) it("returns array if called with array", function (done: any) { return this.col.upsert([{ a: "1" }], function (items: any) { assert.equal(items[0].a, "1") done() }) }) it("updates by id", function (done: any) { return this.col.upsert({ _id: "1", a: "1" }, (item: any) => { return this.col.upsert({ _id: "1", a: "2", b: 1 }, (item: any) => { assert.equal(item.a, "2") return this.col.find({ _id: "1" }).fetch(function (results: any) { assert.equal(1, results.length, "Should be only one document") done() }) }) }) }) it("call upsert with upserted row", function (done: any) { return this.col.upsert({ _id: "1", a: "1" }, function (item: any) { assert.equal(item._id, "1") assert.equal(item.a, "1") done() }) }) }) it("upserts multiple rows", function (done: any) { this.timeout(10000) return this.reset(() => { const docs = [] for (let i = 0; i < 100; i++) { docs.push({ b: i }) } return this.col.upsert( docs, () => { return this.col.find({}).fetch(function (results: any) { assert.equal(results.length, 100) done() }, error) }, error ) }) }) it("upserts multiple rows (promise)", function (done: any) { this.timeout(10000) return this.reset(async () => { const docs = [] for (let i = 0; i < 100; i++) { docs.push({ b: i }) } await this.col.upsert(docs) const results = await this.col.find({}).fetch() assert.equal(results.length, 100) done() }) }) context("With sample with capitalization", function () { beforeEach(function (done: any) { return this.reset(() => { return this.col.upsert({ _id: "1", a: "Alice", b: 1, c: { d: 1, e: 2 } }, () => { return this.col.upsert({ _id: "2", a: "AZ", b: 2, c: { d: 2, e: 3 } }, () => done()) }) }) }) it("finds sorts in Javascript order", function (done: any) { return this.col.find({}, { sort: ["a"] }).fetch(function (results: any) { assert.deepEqual(_.map(results, "_id"), ["2", "1"]) done() }) }) }) context("With integer array in json rows", function () { beforeEach(function (done: any) { return this.reset(() => { return this.col.upsert({ _id: "1", c: { arrint: [1, 2] } }, () => { return this.col.upsert({ _id: "2", c: { arrint: [2, 3] } }, () => { return this.col.upsert({ _id: "3", c: { arrint: [1, 3] } }, () => done()) }) }) }) }) it("filters by $in", function (done: any) { return this.testFilter({ "c.arrint": { $in: [3] } }, ["2", "3"], done) }) it("filters by list $in with multiple", function (done: any) { return this.testFilter({ "c.arrint": { $in: [1, 3] } }, ["1", "2", "3"], done) }) }) context("With object array rows", function () { beforeEach(function (done: any) { return this.reset(() => { return this.col.upsert( { _id: "1", c: [ { x: 1, y: 1 }, { x: 1, y: 2 } ] }, () => { return this.col.upsert({ _id: "2", c: [{ x: 2, y: 1 }] }, () => { return this.col.upsert({ _id: "3", c: [{ x: 2, y: 2 }] }, () => done()) }) } ) }) }) it("filters by $elemMatch", function (done: any) { return this.testFilter({ c: { $elemMatch: { y: 1 } } }, ["1", "2"], () => { return this.testFilter({ c: { $elemMatch: { x: 1 } } }, ["1"], done) }) }) }) context("With array rows with inner string arrays", function () { beforeEach(function (done: any) { return this.reset(() => { return this.col.upsert({ _id: "1", c: [{ arrstr: ["a", "b"] }, { arrstr: ["b", "c"] }] }, () => { return this.col.upsert({ _id: "2", c: [{ arrstr: ["b"] }] }, () => { return this.col.upsert({ _id: "3", c: [{ arrstr: ["c", "d"] }, { arrstr: ["e", "f"] }] }, () => done()) }) }) }) }) it("filters by $elemMatch", function (done: any) { return this.testFilter({ c: { $elemMatch: { arrstr: { $in: ["b"] } } } }, ["1", "2"], () => { return this.testFilter({ c: { $elemMatch: { arrstr: { $in: ["d", "e"] } } } }, ["3"], done) }) }) }) context("With text array rows", function () { beforeEach(function (done: any) { return this.reset(() => { return this.col.upsert( { _id: "1", textarr: ["a", "b"] }, () => { return this.col.upsert( { _id: "2", textarr: ["b", "c"] }, () => { return this.col.upsert({ _id: "3", textarr: ["c", "d"] }, () => done(), error) }, error ) }, error ) }) }) it("filters by $in", function (done: any) { return this.testFilter({ textarr: { $in: ["b"] } }, ["1", "2"], done) }) it("filters by direct reference", function (done: any) { return this.testFilter({ textarr: "b" }, ["1", "2"], done) }) it("filters by both item and complete array", function (done: any) { return this.testFilter({ textarr: { $in: ["a", ["b", "c"]] } }, ["1", "2"], done) }) }) const geopoint = (lng: number, lat: number) => ({ type: "Point", coordinates: [lng, lat] }) const geoline = (lng1: number, lat1: number, lng2: number, lat2: number) => ({ type: "LineString", coordinates: [[lng1, lat1], [lng2, lat2]] }) context("With geolocated rows", function () { beforeEach(function (done: any) { this.reset(() => { this.col.upsert({ _id: "1", geo: geopoint(90, 45) }, () => { this.col.upsert({ _id: "2", geo: geopoint(90, 46) }, () => { this.col.upsert({ _id: "3", geo: geopoint(91, 45) }, () => { this.col.upsert({ _id: "4", geo: geopoint(91, 46) }, () => done()) }) }) }) }) }) it("finds points near", function (done: any) { const selector = { geo: { $near: { $geometry: geopoint(90, 45) } } } this.col.find(selector).fetch(function (results: any) { assert.deepEqual(_.map(results, "_id"), ["1", "3", "2", "4"]) done() }) }) it("finds points near maxDistance", function (done: any) { const selector = { geo: { $near: { $geometry: geopoint(90, 45), $maxDistance: 111180 } } } return this.col.find(selector).fetch(function (results: any) { assert.deepEqual(_.map(results, "_id"), ["1", "3"]) done() }) }) it("finds points near maxDistance just above", function (done: any) { const selector = { geo: { $near: { $geometry: geopoint(90, 45), $maxDistance: 111410 } } } return this.col.find(selector).fetch(function (results: any) { assert.deepEqual(_.map(results, "_id"), ["1", "3", "2"]) done() }) }) it("finds points within simple box", function (done: any) { const selector = { geo: { $geoIntersects: { $geometry: { type: "Polygon", coordinates: [ [ [89.5, 45.5], [89.5, 46.5], [90.5, 46.5], [90.5, 45.5], [89.5, 45.5] ] ] } } } } return this.col.find(selector).fetch(function (results: any) { assert.deepEqual(_.map(results, "_id"), ["2"]) done() }) }) it("finds points within big box", function (done: any) { const selector = { geo: { $geoIntersects: { $geometry: { type: "Polygon", coordinates: [ [ [0, -89], [0, 89], [179, 89], [179, -89], [0, -89] ] ] } } } } return this.col.find(selector, { sort: ["_id"] }).fetch(function (results: any) { assert.deepEqual(_.map(results, "_id"), ["1", "2", "3", "4"]) done() }) }) it("handles undefined", function (done: any) { const selector = { geo: { $geoIntersects: { $geometry: { type: "Polygon", coordinates: [ [ [89.5, 45.5], [89.5, 46.5], [90.5, 46.5], [90.5, 45.5], [89.5, 45.5] ] ] } } } } return this.col.upsert({ _id: 5 }, () => { return this.col.find(selector).fetch(function (results: any) { assert.deepEqual(_.map(results, "_id"), ["2"]) done() }) }) }) }) context("With rows that are lines and points", function () { beforeEach(function (done: any) { this.reset(() => { this.col.upsert({ _id: "1", geo: geopoint(1, 0) }, () => { this.col.upsert({ _id: "2", geo: geoline(0, 1, 0, -1) }, () => { this.col.upsert({ _id: "3", geo: geoline(10, 1, 10, -1) }, () => done()) }) }) }) }) it("finds near point", function (done: any) { const selector = { geo: { $near: { $geometry: geopoint(1, 0) } } } this.col.find(selector).fetch(function (results: any) { assert.deepEqual(_.map(results, "_id"), ["1", "2", "3"]) done() }) }) it("finds points near maxDistance to exclude #3", function (done: any) { const selector = { geo: { $near: { $geometry: geopoint(1, 0), $maxDistance: 200000 } } } this.col.find(selector).fetch(function (results: any) { assert.deepEqual(_.map(results, "_id"), ["1", "2"]) done() }) }) }) context("With polygon rows", function () { const polygon = (coords: any) => ({ type: "Polygon", coordinates: coords }) beforeEach(function (done: any) { this.reset(() => { this.col.upsert( { _id: "1", geo: polygon([ [ [0, 0], [1, 0], [1, 1], [0, 1], [0, 0] ] ]) }, () => { return this.col.upsert( { _id: "2", geo: polygon([ [ [10, 10], [11, 10], [11, 11], [10, 11], [10, 10] ] ]) }, () => { done() } ) } ) }) }) it("finds polygons that intersect simple box", function (done: any) { const selector = { geo: { $geoIntersects: { $geometry: polygon([ [ [0, 0], [2, 0], [2, 2], [0, 2], [0, 0] ] ]) } } } return this.col.find(selector).fetch(function (results: any) { assert.deepEqual(_.map(results, "_id"), ["1"]) done() }) }) it("finds polygons that intersect large box", function (done: any) { const selector = { geo: { $geoIntersects: { $geometry: polygon([ [ [0, 0], [12, 0], [12, 12], [0, 12], [0, 0] ] ]) } } } return this.col.find(selector).fetch(function (results: any) { assert.deepEqual(_.map(results, "_id"), ["1", "2"]) done() }) }) }) context("With multipolygon rows", function () { const polygon = (coords: any) => ({ type: "Polygon", coordinates: coords }) const multipolygon = (coords: any) => ({ type: "MultiPolygon", coordinates: coords }) beforeEach(function (done: any) { return this.col.upsert( { _id: "1", geo: multipolygon([ [ [ [0, 0], [1, 0], [1, 1], [0, 1], [0, 0] ] ] ]) }, () => { return this.col.upsert( { _id: "2", geo: multipolygon([ [ [ [10, 10], [11, 10], [11, 11], [10, 11], [10, 10] ] ] ]) }, () => { done() } ) } ) }) it("finds polygons that intersect simple box", function (done: any) { const selector = { geo: { $geoIntersects: { $geometry: polygon([ [ [0, 0], [2, 0], [2, 2], [0, 2], [0, 0] ] ]) } } } return this.col.find(selector).fetch(function (results: any) { assert.deepEqual(_.map(results, "_id"), ["1"]) done() }) }) it("finds polygons that intersect large box", function (done: any) { const selector = { geo: { $geoIntersects: { $geometry: polygon([ [ [0, 0], [12, 0], [12, 12], [0, 12], [0, 0] ] ]) } } } return this.col.find(selector).fetch(function (results: any) { assert.deepEqual(_.map(results, "_id"), ["1", "2"]) done() }) }) }) return context("With multilinestring rows", function () { const polygon = (coords: any) => ({ type: "Polygon", coordinates: coords }) beforeEach(function (done: any) { const linestring = { type: "MultiLineString", coordinates: [ [ [0, 0], [0, 1] ], [ [0, 0], [1, 0] ] ] } return this.col.upsert({ _id: "1", geo: linestring }, () => { done() }) }) it("finds that that intersect simple box", function (done: any) { const selector = { geo: { $geoIntersects: { $geometry: polygon([ [ [0, 0], [2, 0], [2, 2], [0, 2], [0, 0] ] ]) } } } return this.col.find(selector).fetch(function (results: any) { assert.deepEqual(_.map(results, "_id"), ["1"]) done() }) }) it("finds that that doesn't intersect simple box", function (done: any) { const selector = { geo: { $geoIntersects: { $geometry: polygon([ [ [2, 2], [3, 2], [3, 3], [2, 3], [2, 2] ] ]) } } } return this.col.find(selector).fetch(function (results: any) { assert.deepEqual(_.map(results, "_id"), []) done() }) }) }) }