kalisio/krawler

View on GitHub
test/hooks.mongo.test.js

Summary

Maintainability
A
0 mins
Test Coverage
import _ from 'lodash'
import chai from 'chai'
import chailint from 'chai-lint'
import path, { dirname } from 'path'
import fs from 'fs-extra'
import fsStore from 'fs-blob-store'
import { hooks as pluginHooks } from '../lib/index.js'
import { fileURLToPath } from 'url'
 
const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)
const { util, expect } = chai
 
describe('krawler:hooks:mongo', () => {
const inputStore = fsStore({ path: path.join(__dirname, 'data') })
const outputStore = fsStore({ path: path.join(__dirname, 'output') })
let geojson
 
before(() => {
chailint(chai, util)
geojson = fs.readJsonSync(path.join(inputStore.path, 'geojson.json'))
// Add invalid data breaking the unique index rule to check for error management
geojson.features.unshift(_.cloneDeep(geojson.features[0]))
geojson.features.push(_.cloneDeep(geojson.features[0]))
})
 
const mongoOptions = {
url: 'mongodb://127.0.0.1:27017/krawler-test'
}
 
const mongoHook = {
type: 'before',
data: {},
params: {}
}
 
it('connect to MongoDB', async () => {
await pluginHooks.connectMongo(mongoOptions)(mongoHook)
expect(mongoHook.data.client).toExist()
expect(mongoHook.data.client.db).toExist()
expect(mongoHook.data.client.isConnected()).beTrue()
})
// Let enough time to proceed
.timeout(5000)
 
it('connect to MongoDB again', async () => {
const result = await pluginHooks.connectMongo(mongoOptions)(mongoHook).then(ok => ok, no => no)
expect(result).to.be.equal(mongoHook)
})
 
it('creates MongoDB collection', async () => {
await pluginHooks.createMongoCollection({
collection: 'geojson',
indices: [{ geometry: '2dsphere' }, [{ id: 1 }, { unique: true }]]
})(mongoHook)
const collections = await mongoHook.data.client.db.listCollections({ name: 'geojson' }).toArray()
expect(collections.length === 1).beTrue()
})
// Let enough time to proceed
.timeout(5000)
 
it('writes MongoDB collection', async () => {
mongoHook.type = 'after'
mongoHook.result = mongoHook.data
mongoHook.result.data = geojson
try {
await pluginHooks.writeMongoCollection({
collection: 'geojson',
// Ensure we use multiple chunks for testing purpose
chunkSize: 2,
transform: {
omit: ['properties.prop2'],
inPlace: false
}
})(mongoHook)
} catch (error) {
expect(error).toExist()
// console.log(error)
expect(error.writeErrors).toExist()
expect(error.writeErrors.length).to.equal(2)
expect(error.result).toExist()
expect(error.result.insertedIds).toExist()
expect(error.result.insertedIds.length).to.equal(3)
expect(error.result.nInserted).to.equal(1)
// error.writeErrors.forEach(data => console.log(data))
expect(error.name).to.equal('BulkWriteError')
}
const collection = mongoHook.data.client.db.collection('geojson')
let results = await collection.find({}).toArray()
expect(results.length).to.equal(3)
results = await collection.find({
geometry: { $near: { $geometry: { type: 'Point', coordinates: [102, 0.5] }, $maxDistance: 5000 } }
}).toArray()
expect(results.length).to.equal(1)
expect(results[0].properties).toExist()
expect(results[0].properties.prop0).to.equal('value0')
expect(results[0].properties.prop2).beUndefined()
})
// Let enough time to proceed
.timeout(5000)
 
it('reads MongoDB collection', async () => {
await pluginHooks.readMongoCollection({
collection: 'geojson',
query: {
geometry: { $near: { $geometry: { type: 'Point', coordinates: [102, 0.5] }, $maxDistance: 500000 } }
},
project: { properties: 1 },
skip: 1,
limit: 2,
dataPath: 'result.data'
})(mongoHook)
const results = mongoHook.result.data
expect(results.length).to.equal(2)
expect(results[0].geometry).beUndefined()
expect(results[0].properties).toExist()
expect(results[0].properties.prop0).to.equal('value0')
expect(results[0].properties.prop1).toExist()
})
// Let enough time to proceed
.timeout(5000)
 
it('updates MongoDB collection', async () => {
mongoHook.type = 'after'
mongoHook.result.data = {
type: 'FeatureCollection',
features: geojson.features.map(feature => {
delete feature.geometry
delete feature.type
if (feature.id < 3) feature.properties = { prop0: 'value1' }
return feature
})
}
await pluginHooks.updateMongoCollection({
collection: 'geojson',
filter: { id: '<%= id %>' }
})(mongoHook)
const collection = mongoHook.data.client.db.collection('geojson')
const results = await collection.find({}).toArray()
expect(results.length).to.equal(3)
results.forEach(result => {
expect(result.properties).toExist()
if (result.id < 3) expect(result.properties.prop0).to.equal('value1')
else expect(result.properties.prop0).to.equal('value0')
})
})
// Let enough time to proceed
.timeout(5000)
 
it('create MongoDB aggregation', async () => {
await pluginHooks.createMongoAggregation({
collection: 'geojson',
pipeline: {
$group: {
_id: '$geometry.type',
num: { $sum: 1 }
}
},
dataPath: 'result.data'
})(mongoHook)
const results = mongoHook.result.data
expect(results.length).to.equal(3)
expect(results[0].num).to.equal(1)
expect(results[1].num).to.equal(1)
expect(results[2].num).to.equal(1)
})
// Let enough time to proceed
.timeout(5000)
 
it('deletes MongoDB collection', async () => {
await pluginHooks.deleteMongoCollection({ collection: 'geojson', filter: { 'geometry.type': 'Point' } })(mongoHook)
const collection = mongoHook.data.client.db.collection('geojson')
const results = await collection.find({ 'geometry.type': 'Point' }).toArray()
expect(results.length).to.equal(0)
})
// Let enough time to proceed
.timeout(5000)
 
it('drops MongoDB collection', async () => {
await pluginHooks.dropMongoCollection({ collection: 'geojson' })(mongoHook)
const collections = await mongoHook.data.client.db.listCollections({ name: 'geojson' }).toArray()
expect(collections.length === 0).beTrue()
})
// Let enough time to proceed
.timeout(5000)
 
it('creates MongoDB bucket', async () => {
await pluginHooks.createMongoBucket({ bucket: 'data' })(mongoHook)
})
// Let enough time to proceed
.timeout(5000)
 
it('writes MongoDB bucket', async () => {
mongoHook.result.store = inputStore
await pluginHooks.writeMongoBucket({ bucket: 'data', metadata: { x: 'y' }, key: 'geojson.json' })(mongoHook)
const collection = mongoHook.data.client.db.collection('data.files')
const results = await collection.find({ filename: 'geojson.json' }).toArray()
expect(results.length).to.equal(1)
expect(results[0].metadata).toExist()
expect(results[0].metadata.x).to.equal('y')
})
// Let enough time to proceed
.timeout(5000)
 
it('reads MongoDB bucket', async () => {
mongoHook.result.store = outputStore
await pluginHooks.readMongoBucket({ bucket: 'data', key: 'geojson.json' })(mongoHook)
expect(fs.existsSync(path.join(outputStore.path, 'geojson.json'))).beTrue()
})
// Let enough time to proceed
.timeout(5000)
 
it('deletes MongoDB bucket', async () => {
await pluginHooks.deleteMongoBucket({ bucket: 'data', key: 'geojson.json' })(mongoHook)
const collection = mongoHook.data.client.db.collection('data.files')
const results = await collection.find({ filename: 'geojson.json' }).toArray()
expect(results.length).to.equal(0)
})
// Let enough time to proceed
.timeout(5000)
 
it('drops MongoDB bucket', async () => {
await pluginHooks.dropMongoBucket({ bucket: 'data' })(mongoHook)
let collections = await mongoHook.data.client.db.listCollections({ name: 'data.files' }).toArray()
expect(collections.length === 0).beTrue()
collections = await mongoHook.data.client.db.listCollections({ name: 'data.chuncks' }).toArray()
expect(collections.length === 0).beTrue()
})
// Let enough time to proceed
.timeout(5000)
 
it('disconnect from MongoDB', async () => {
// Cleanup
await mongoHook.data.client.db.dropDatabase()
await pluginHooks.disconnectMongo()(mongoHook)
expect(mongoHook.data.client).beUndefined()
})
// Let enough time to proceed
.timeout(5000)
 
it('disconnect from MongoDB again', async () => {
const result = await pluginHooks.disconnectMongo()(mongoHook).then(ok => ok, no => no)
expect(result).to.be.equal(mongoHook)
})
})