Commit 162eb347 authored by Simon Breiter's avatar Simon Breiter
Browse files

feat: wip

parent 48ef1f83
Pipeline #394161518 passed with stages
in 3 minutes and 41 seconds
const util = require('util')
const { ObjectId } = require('mongodb')
const initializeDatabases = require('./index')
describe('basic db operations', () => {
let connection, db
beforeAll(async () => {
connection = await initializeDatabases()
})
afterAll(async () => {
await connection.close()
})
beforeEach(async () => {
db = await connection.db('test')
})
afterEach(async () => {
await db.dropDatabase()
})
test('it should list all databases', async () => {
const expected = ['admin', 'config', 'local']
const dbAdmin = db.admin()
const databasesObj = await dbAdmin.listDatabases()
const databaseNames = databasesObj['databases'].map(el => el['name'])
expect(databaseNames).toEqual(expected)
})
test('it should create a collection and find one document', async () => {
const collection = db.collection('documents')
const document = {
_id: 1,
a: 1
}
await collection.insertOne(document)
expect((await collection.find(document).toArray()).length).toBe(1)
expect(await collection.findOne(document)).toEqual(document)
})
test('it should create a collection and some documents', async () => {
let a, b, c
const collection = db.collection('documents')
const documents = [
{
_id: 1,
a: 1
},
{
_id: 2,
a: 2
},
{
_id: 3,
a: 3
}
]
const expectedDocuments = [
{ _id: 1, a: 1 },
{ _id: 2, a: 2 },
{ _id: 3, a: 3 }
]
await collection.insertMany(documents)
a = await collection.find({ a: 3 }).toArray()
b = await collection.find({ a: 1 }).toArray()
c = await collection.find({ a: 4 }).toArray()
expect((await collection.find({ a: 3 }).toArray()).length).toBe(1)
expect((await collection.find({ a: 1 }).toArray()).length).toBe(1)
expect((await collection.find({ a: 4 }).toArray()).length).not.toBe(1)
expect(await collection.find({}).toArray()).toEqual(expectedDocuments)
})
test('it should update a single document', async () => {
const collection = db.collection('documents')
const id = ObjectId()
const mock = { _id: id, a: 1 }
await collection.insertOne(mock)
await collection.updateOne(mock, { $set: { b: 1 } })
expect(await collection.findOne({ _id: id })).toEqual({
_id: id,
a: 1,
b: 1
})
})
test('it should update many document', async () => {
const collection = db.collection('documents')
const mock = [
{ _id: 1, a: true },
{ _id: 2, a: false },
{ _id: 3, a: false }
]
const mock2 = [
{ _id: 1, a: true },
{ _id: 2, a: true },
{ _id: 3, a: true }
]
await collection.insertMany(mock)
await collection.updateMany({ a: false }, { $set: { a: true } })
expect(await collection.find({}).toArray()).toEqual(mock2)
})
test('it should match an array', async () => {
const collection = db.collection('documents')
const mock = [
{ _id: ObjectId(), a: [1, 2] },
{ _id: ObjectId(), a: [2, 3] },
{ _id: ObjectId(), a: [3, 4] }
]
await collection.insertMany(mock)
expect(
await collection.findOne({
a: [1, 2]
})
).toEqual(mock[0])
})
test('it should delete documents', async () => {
const collection = db.collection('documents')
const mock = [
{ _id: ObjectId(), a: true },
{ _id: ObjectId(), a: false },
{ _id: ObjectId(), a: false }
]
await collection.insertMany(mock)
await collection.deleteMany({ a: false })
expect(
await collection
.find({
a: true
})
.toArray()
).toEqual([mock[0]])
})
test('it should limit documents', async () => {
let a
const collection = db.collection('documents')
const mock = [
{ _id: ObjectId(), a: true },
{ _id: ObjectId(), a: false },
{ _id: ObjectId(), a: false }
]
await collection.insertMany(mock)
a = await collection
.find({})
.limit(2)
.toArray()
expect(a.length).toEqual(2)
})
test('it should validate documents', async () => {
await db.createCollection('students', {
validator: {
$jsonSchema: {
bsonType: 'object',
required: [
'name',
'year',
'major',
'gpa',
'address.city',
'address.street'
],
properties: {
name: {
bsonType: 'string',
description: 'must be a string and is required'
},
gender: {
bsonType: 'string',
description: 'must be a string and is not required'
},
year: {
bsonType: 'int',
minimum: 2017,
maximum: 3017,
exclusiveMaximum: false,
description:
'must be an integer in [ 2017, 3017 ] and is required'
},
major: {
enum: ['Math', 'English', 'Computer Science', 'History', null],
description: 'can only be one of the enum values and is required'
},
gpa: {
bsonType: ['double'],
minimum: 0,
description: 'must be a double and is required'
},
'address.city': {
bsonType: 'string',
description: 'must be a string and is required'
},
'address.street': {
bsonType: 'string',
description: 'must be a string and is required'
}
}
}
}
})
const mockObjId = ObjectId()
const mock = {
_id: mockObjId,
name: 'Muster',
gender: 'male',
year: 2019,
major: 'Math',
gpa: 1.2,
address: {
city: 'Winterthur',
street: 'Bahnhofstrasse'
}
}
const mock2ObjId = ObjectId()
const mock2 = {
_id: mock2ObjId,
gender: 'male',
year: 2019,
major: 'Math',
gpa: -1,
address: {
city: 'Winterthur',
street: 'Bahnhofstrasse'
}
}
await db.collection('students').insertOne(mock)
expect(
await db.collection('students').findOne({
_id: mock._id
})
).toEqual(mock)
try {
await db.collection('students').insertOne(mock2)
} catch (e) {
expect({ name: e.name, errmsg: e.errmsg }).toEqual({
name: 'MongoServerError',
errmsg: 'Document failed validation'
})
// Improved error messages in MongoDB 5.0 https://www.mongodb.com/developer/article/mongodb-5-0-schema-validation/
// console.log(util.inspect(e.errInfo, false, null, true))
const schemaRulesNotSatisfied = [
{
operatorName: 'properties',
propertiesNotSatisfied: [
{
propertyName: 'gpa',
details: [
{
operatorName: 'minimum',
specifiedAs: { minimum: 0 },
reason: 'comparison failed',
consideredValue: -1
},
{
operatorName: 'bsonType',
specifiedAs: { bsonType: ['double'] },
reason: 'type did not match',
consideredValue: -1,
consideredType: 'int'
}
]
}
]
},
{
operatorName: 'required',
specifiedAs: {
required: [
'name',
'year',
'major',
'gpa',
'address.city',
'address.street'
]
},
missingProperties: ['name']
}
]
expect(e.errInfo.details.schemaRulesNotSatisfied).toStrictEqual(
schemaRulesNotSatisfied
)
}
})
test('it should create multiple collections', async () => {
await db.createCollection('foo')
await db.createCollection('bar')
await db.createCollection('baz')
const collections = (await db.listCollections().toArray()).map(
collection => {
return collection.name
}
)
expect(await collections).toEqual(
expect.arrayContaining(['bar', 'baz', 'foo'])
)
})
test('it should aggregate data', async () => {
const users = await db.collection('users')
const posts = await db.collection('posts')
const userMocks = [
{ _id: 1, name: 'foo1', password: 'bar1' },
{ _id: 2, name: 'foo2', password: 'bar2' },
{ _id: 3, name: 'foo3', password: 'bar3' }
]
const postMocks = [
{ _id: 4, title: 'foo', user: 1 },
{ _id: 5, title: 'bar', user: 2 },
{ _id: 6, title: 'baz', user: 3 }
]
const expectedData = [
{
_id: 4,
title: 'foo',
user: [
{
_id: 1,
name: 'foo1',
password: 'bar1'
}
]
},
{
_id: 5,
title: 'bar',
user: [
{
_id: 2,
name: 'foo2',
password: 'bar2'
}
]
},
{
_id: 6,
title: 'baz',
user: [
{
_id: 3,
name: 'foo3',
password: 'bar3'
}
]
}
]
await users.insertMany(userMocks)
await posts.insertMany(postMocks)
expect(
await posts
.aggregate([
{
$lookup: {
from: 'users',
localField: 'user',
foreignField: '_id',
as: 'user'
}
}
])
.toArray()
).toEqual(expectedData)
})
})
const { graphqlHTTP } = require('express-graphql')
const { buildSchema } = require('../graphql/schema')
const createUsersRoute = require('./users')
module.exports = function (app, dbConnection) {
const db = dbConnection.db('test')
const users = db.collection('users')
app.get('/users', async (req, res) => {
try {
const allUsers = await users.find({}).toArray()
res.send(allUsers)
} catch (e) {
console.error(e)
}
})
app.post('/users', async (req, res) => {
try {
await users.insertOne(req.body)
res.json({
message: 'User created!'
})
} catch (e) {
console.error(e)
}
})
async function createRoutes (app, dbConnection) {
app.use('/users', createUsersRoute(dbConnection))
// TODO: Use GraphQL to query buckets
// app.use(
......@@ -44,3 +24,5 @@ module.exports = function (app, dbConnection) {
return { app, dbConnection }
}
module.exports = createRoutes
const express = require('express')
function createUsersRoute (dbConnection) {
const router = express.Router()
const db = dbConnection.db('test')
const users = db.collection('users')
router
.route('/')
.get(async (req, res) => {
try {
const allUsers = await users.find({}).toArray()
res.send(allUsers)
} catch (e) {
console.error(e)
}
})
.post(async (req, res) => {
try {
await users.insertOne(req.body)
res.json({
message: 'User created!'
})
} catch (e) {
console.error(e)
}
})
return router
}
module.exports = createUsersRoute
......@@ -9,7 +9,9 @@ let app = express()
app.use(bodyParser.json())
app.use(identifyUser)
module.exports = async function () {
async function createServer () {
const dbConnection = await initializeDatabases()
return createRoutes(app, dbConnection)
}
module.exports = createServer
......@@ -22,7 +22,7 @@ afterEach(async () => {
await db.dropDatabase()
})
test('simple post request of users', done => {
test('Create a single users', done => {
request(app)
.post('/users')
.send({ name: 'simon' })
......@@ -34,7 +34,7 @@ test('simple post request of users', done => {
})
})
test('Create multiple users and receive a list of them', done => {
test('Get all users', done => {
async.series([
cb =>
request(app)
......@@ -80,3 +80,15 @@ test('Create multiple users and receive a list of them', done => {
})
])
})
// test('Create a single users', done => {
// request(app)
// .get('/users')
// // .send({ name: 'simon' })
// .expect('Content-Type', /json/)
// .expect(200)
// .then(response => {
// expect(response.body).toEqual({ message: 'User created!' })
// done()
// })
// })
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment