Skip to content

Commit

Permalink
fix(db): fix mongoose unique indexes, add tests [#56]
Browse files Browse the repository at this point in the history
  • Loading branch information
Drapegnik committed Aug 31, 2019
1 parent 6e099fd commit e2d9cf7
Show file tree
Hide file tree
Showing 8 changed files with 137 additions and 19 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
"mailchimp-api-v3": "^1.12.1",
"md5": "^2.2.1",
"module-alias": "^2.1.0",
"mongoose": "^5.4.3",
"mongoose": "^5.6.11",
"morgan": "^1.9.1",
"multer": "^2.0.0-alpha.6",
"node-http-error": "^2.0.0",
Expand Down
22 changes: 21 additions & 1 deletion src/api/article/collection/model.tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@ describe('ArticleCollection model', () => {
imageUrl: 'https://collection.jpg',
};

before(dropData);
before(async function() {
this.timeout(5000);
await dropData();
ArticleCollection.ensureIndexes();
});

it('should fail to save collection | no slug', async () => {
const errorHandler = spy(({ message }) => {
Expand All @@ -27,4 +31,20 @@ describe('ArticleCollection model', () => {

expect(errorHandler).to.have.been.called();
});

it('should fail to save collection | dup slug', async () => {
const errorHandler = spy(({ message }) => {
expect(message).to.not.empty();
expect(message).to.includes('duplicate key');
});

const collection = { ...data, slug: 'col-slug' };
await ArticleCollection(collection).save();
await ArticleCollection(collection)
.save()
.catch(errorHandler);

expect(errorHandler).to.have.been.called();
await ArticleCollection.find({}).then(collections => expect(collections).to.have.length(1));
});
});
18 changes: 18 additions & 0 deletions src/api/article/localized/model.tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ describe('LocalizedArticle model', () => {
this.timeout(5000);
await dropData();

LocalizedArticle.ensureIndexes();

await addAdminUser();
const metadata = await defaultObjectMetadata();
data = {
Expand Down Expand Up @@ -63,4 +65,20 @@ describe('LocalizedArticle model', () => {

expect(errorHandler).to.have.been.called();
});

it('should fail to save article | dup slug', async () => {
const errorHandler = spy(({ message }) => {
expect(message).to.not.empty();
expect(message).to.includes('duplicate key');
});

const article = { ...data, locale: 'be' };
await LocalizedArticle(article).save();
await LocalizedArticle(article)
.save()
.catch(errorHandler);

expect(errorHandler).to.have.been.called();
await LocalizedArticle.find({}).then(articles => expect(articles).to.have.length(1));
});
});
39 changes: 39 additions & 0 deletions src/api/storage/model.tests.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import 'db/connect';

import { expect, dropData, spy, defaultObjectMetadata, addAdminUser } from 'utils/testing';

import { StorageEntity } from './model';

describe('StorageEntity model', () => {
let data;

before(async function() {
this.timeout(5000);

await dropData();
StorageEntity.ensureIndexes();

await addAdminUser();
const metadata = await defaultObjectMetadata();
data = {
key: 'doc-key',
document: {},
metadata,
};
});

it('should fail to save doc | dup key', async () => {
const errorHandler = spy(({ message }) => {
expect(message).to.not.empty();
expect(message).to.includes('duplicate key');
});

await StorageEntity(data).save();
await StorageEntity(data)
.save()
.catch(errorHandler);

expect(errorHandler).to.have.been.called();
await StorageEntity.find({}).then(docs => expect(docs).to.have.length(1));
});
});
26 changes: 26 additions & 0 deletions src/api/tag/model.tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ describe('Tag model', () => {
this.timeout(5000);
await dropData();

Tag.ensureIndexes();

await loginTestAdmin();
metadata = await defaultObjectMetadata();

Expand Down Expand Up @@ -72,6 +74,30 @@ describe('Tag model', () => {
expect(errorHandler).to.have.been.called();
});

it('should fail to save tag | dup slug', async () => {
const errorHandler = spy(({ message }) => {
expect(message).to.not.empty();
expect(message).to.includes('duplicate key');
});

const data = {
topic: topics.times._id,
content: {
title: { be: 'XX стагоддзе' },
},
metadata,
slug: 'xx-century',
};

await Tag(data).save();
await Tag(data)
.save()
.catch(errorHandler);

expect(errorHandler).to.have.been.called();
await Tag.find({}).then(tags => expect(tags).to.have.length(1));
});

it('should fail to save personalities tag | bad color', async () => {
const errorHandler = spy(({ status, message }) => {
expect(status).to.equal(HttpStatus.BAD_REQUEST);
Expand Down
14 changes: 6 additions & 8 deletions src/api/topic/model.tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ describe('Topic model', () => {
this.timeout(5000);
await dropData();

Topic.ensureIndexes();

await loginTestAdmin();
metadata = await defaultObjectMetadata();
});
Expand All @@ -26,22 +28,18 @@ describe('Topic model', () => {
expect(errorHandler).to.have.been.called();
});

// FIXME
// eslint-disable-next-line
it.skip('should fail to save topic with same slug', async () => {
it('should fail to save topic | dup slug', async () => {
const errorHandler = spy(({ message }) => {
expect(message).to.not.empty();
expect(message).to.includes('duplicate key');
});

await Topic({ slug: 'themes', metadata }).save();
await Topic({ slug: 'themes', metadata })
.save()
.catch(errorHandler);
// [
// { _id: 5d597b4c965e6602d21fcfc7, slug: 'themes' },
// { _id: 5d597b4c965e6602d21fcfc8, slug: 'themes' }
// ]
await Topic.getAll().then(obj => expect(obj).to.have.length(1));

expect(errorHandler).to.have.been.called();
await Topic.getAll().then(topics => expect(topics).to.have.length(1));
});
});
22 changes: 20 additions & 2 deletions src/api/user/model.tests.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import 'db/connect';

import { expect, dropData } from 'utils/testing';
import { expect, dropData, spy } from 'utils/testing';

import User from './model';

Expand All @@ -9,7 +9,11 @@ describe('User model', () => {
const { firstName, email, password } = userData;
const user = new User(userData);

before(dropData);
before(async function() {
this.timeout(5000);
await dropData();
User.ensureIndexes();
});

it('should save user with password', async () => {
await user.setPassword(password);
Expand Down Expand Up @@ -43,6 +47,20 @@ describe('User model', () => {
it('should not authenticate with wrong password', async () =>
expect(await user.authenticate('not secret')).to.be.false());

it('should fail to save user | dup email', async () => {
const errorHandler = spy(({ message }) => {
expect(message).to.not.empty();
expect(message).to.includes('duplicate key');
});

await User(userData)
.save()
.catch(errorHandler);

expect(errorHandler).to.have.been.called();
await User.find({}).then(users => expect(users).to.have.length(1));
});

it('should remove user', async () => {
await User.remove({ email });
const result = await User.findOne({ email });
Expand Down
13 changes: 6 additions & 7 deletions src/db/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,12 @@ export default (silent = false) => {
mongodb: { url, options },
} = config;
mongoose.Promise = global.Promise;
mongoose.connection.on(
'connected',
() => (silent ? null : console.log(`Mongoose: connected to ${url}`))
mongoose.connection.on('connected', () =>
silent ? null : console.log(`Mongoose: connected to ${url}`)
);
mongoose.connection.on('error', err => console.error(`Mongoose: connection error: ${err}`));
mongoose.connection.on(
'disconnected',
() => (silent ? null : console.log('Mongoose: disconnected'))
mongoose.connection.on('disconnected', () =>
silent ? null : console.log('Mongoose: disconnected')
);
return mongoose.connect(
url,
Expand All @@ -27,7 +25,8 @@ export default (silent = false) => {
// Some deprecation warnings keep showing though (for an unknown reason).
useNewUrlParser: true,
useFindAndModify: false,
useCreateIndex: true,
// https://github.com/Automattic/mongoose/issues/2671
// useCreateIndex: true, // - breaks `unique: true`
},
() => {
if (process.env.NODE_ENV === 'testing') {
Expand Down

0 comments on commit e2d9cf7

Please sign in to comment.