added migration, migration tests 🎉

This commit is contained in:
Wyatt Johnson
2017-11-08 16:35:38 -07:00
parent 0257e09a40
commit 77c927ac59
4 changed files with 419 additions and 2 deletions
+1 -1
View File
@@ -17,7 +17,7 @@ module.exports = {
}}
]);
// If no comments were found, nothing needes to be done!
// If no comments were found, nothing needs to be done!
if (comments.length <= 0) {
return;
}
+211
View File
@@ -0,0 +1,211 @@
const UserModel = require('../models/user');
const merge = require('lodash/merge');
const getUserBatch = async () => {
let query = {
status: {
$in: [
'ACTIVE',
'BANNED',
'PENDING',
'APPROVED'
]
}
};
// Find all the users that need migrating.
return UserModel.collection.find(query);
};
module.exports = {
async up() {
const created_at = Date.now();
// Create a new batch operation.
let bulk = UserModel.collection.initializeUnorderedBulkOp();
// Get the first batch of users.
let cursor = await getUserBatch();
while (await cursor.hasNext()) {
const user = await cursor.next();
const {id, status, canEditName, suspension, disabled} = user;
let update = {
$unset: {
canEditName: '',
suspension: '',
disabled: '',
},
$set: {
status: {
// The username status is specific to each case.
username: {
history: []
},
// The user is not banned by default.
banned: {
status: false,
history: []
},
// The user is not suspended by default.
suspension: {
until: null,
history: []
},
},
updated_at: created_at
},
};
if (disabled) {
update = merge(update, {
$set: {
status: {
banned: {
status: true,
history: [{
status: true,
created_at
}]
},
}
}
});
}
// If the user has an "until" property of their suspension, then we need
// to reflect that in the new status object.
if (suspension && suspension.until !== null) {
update = merge(update, {
$set: {
status: {
suspension: {
until: suspension.until,
history: [{
until: suspension.until,
created_at,
}]
}
}
}
});
}
switch (status) {
case 'ACTIVE':
if (canEditName) {
update = merge(update, {
$set: {
status: {
username: {
status: 'UNSET',
history: [{
status: 'UNSET',
created_at
}]
}
}
}
});
} else {
update = merge(update, {
$set: {
status: {
username: {
status: 'SET',
history: [{
status: 'SET',
created_at
}]
}
}
}
});
}
break;
case 'BANNED':
if (canEditName) {
update = merge(update, {
$set: {
status: {
username: {
status: 'REJECTED',
history: [{
status: 'REJECTED',
created_at
}]
}
}
}
});
} else {
update = merge(update, {
$set: {
status: {
banned: {
status: true,
history: [{
status: true,
created_at
}]
},
username: {
status: 'SET',
history: [{
status: 'SET',
created_at
}]
}
}
}
});
}
break;
case 'PENDING':
update = merge(update, {
$set: {
status: {
username: {
status: 'CHANGED',
history: [{
status: 'CHANGED',
created_at
}]
}
}
}
});
break;
case 'APPROVED':
update = merge(update, {
$set: {
status: {
username: {
status: 'APPROVED',
history: [{
status: 'APPROVED',
created_at
}]
}
}
}
});
break;
default:
throw new Error(`${status} is an invalid status`);
}
bulk.find({id}).updateOne(update);
}
// Execute the bulk update operation.
await bulk.execute();
}
};
+4 -1
View File
@@ -33,7 +33,7 @@
},
"talk": {
"migration": {
"minVersion": 1507322128
"minVersion": 1510174676
}
},
"repository": {
@@ -228,5 +228,8 @@
"post-checkout": [],
"post-merge": []
}
},
"release": {
"analyzeCommits": "simple-commit-message"
}
}
@@ -0,0 +1,203 @@
const migration = require('../../../migrations/1510174676_user_status');
const UserModel = require('../../../models/user');
const chai = require('chai');
chai.use(require('chai-datetime'));
const {expect} = chai;
describe('migration.1510174676_user_status', () => {
describe('active user', () => {
beforeEach(async () => {
await UserModel.collection.insert({
id: '123',
username: 'Kirk',
lowercaseUsername: 'kirk',
status: 'ACTIVE',
canEditName: false
});
});
it('completes the migration', async () => {
let user = await UserModel.collection.findOne({id: '123'});
expect(user).to.have.property('status', 'ACTIVE');
expect(user).to.have.property('canEditName', false);
// Perform the migration.
await migration.up();
user = await UserModel.collection.findOne({id: '123'});
// Check that it was correct.
expect(user).to.have.property('status');
expect(user.status).to.have.property('username');
expect(user.status.username).to.have.property('status', 'SET');
expect(user.status.username.history).to.have.length(1);
});
});
describe('social user', () => {
beforeEach(async () => {
await UserModel.collection.insert({
id: '123',
username: 'Kirk',
lowercaseUsername: 'kirk',
status: 'ACTIVE',
canEditName: true
});
});
it('completes the migration', async () => {
let user = await UserModel.collection.findOne({id: '123'});
expect(user).to.have.property('status', 'ACTIVE');
expect(user).to.have.property('canEditName', true);
// Perform the migration.
await migration.up();
user = await UserModel.collection.findOne({id: '123'});
// Check that it was correct.
expect(user).to.have.property('status');
expect(user.status).to.have.property('username');
expect(user.status.username).to.have.property('status', 'UNSET');
expect(user.status.username.history).to.have.length(1);
});
});
describe('rejected username', () => {
beforeEach(async () => {
await UserModel.collection.insert({
id: '123',
username: 'Kirk',
lowercaseUsername: 'kirk',
status: 'BANNED',
canEditName: true
});
});
it('completes the migration', async () => {
let user = await UserModel.collection.findOne({id: '123'});
expect(user).to.have.property('status');
expect(user.status).to.equal('BANNED');
expect(user.canEditName).to.equal(true);
// Perform the migration.
await migration.up();
user = await UserModel.collection.findOne({id: '123'});
// Check that it was correct.
expect(user).to.have.property('status');
expect(user.status).to.have.property('banned');
expect(user.status.banned).to.have.property('status', false);
expect(user.status.username).to.have.property('status', 'REJECTED');
expect(user.status.username.history).to.have.length(1);
});
});
describe('approved username', () => {
beforeEach(async () => {
await UserModel.collection.insert({
id: '123',
username: 'Kirk',
lowercaseUsername: 'kirk',
status: 'APPROVED',
canEditName: false
});
});
it('completes the migration', async () => {
let user = await UserModel.collection.findOne({id: '123'});
expect(user).to.have.property('status');
expect(user.status).to.equal('APPROVED');
expect(user.canEditName).to.equal(false);
// Perform the migration.
await migration.up();
user = await UserModel.collection.findOne({id: '123'});
// Check that it was correct.
expect(user).to.have.property('status');
expect(user.status).to.have.property('banned');
expect(user.status.banned).to.have.property('status', false);
expect(user.status.username).to.have.property('status', 'APPROVED');
expect(user.status.username.history).to.have.length(1);
});
});
describe('suspended user', () => {
beforeEach(async () => {
await UserModel.collection.insert({
id: '123',
username: 'Kirk',
lowercaseUsername: 'kirk',
status: 'ACTIVE',
suspension: {
until: new Date()
}
});
});
it('completes the migration', async () => {
let user = await UserModel.collection.findOne({id: '123'});
expect(user).to.have.property('suspension');
expect(user.suspension).to.have.property('until');
expect(user.suspension.until).to.not.be.null;
const until = user.suspension.until;
// Perform the migration.
await migration.up();
user = await UserModel.collection.findOne({id: '123'});
// Check that it was correct.
expect(user).to.have.property('status');
expect(user.status).to.have.property('suspension');
expect(user.status.suspension).to.have.property('until');
expect(user.status.suspension.until).to.not.be.null;
expect(user.status.suspension.until).to.be.withinTime(new Date(until.getTime() - 1000), new Date(until.getTime() + 1000));
});
});
describe('banned user', () => {
beforeEach(async () => {
await UserModel.collection.insert({
id: '123',
username: 'Kirk',
lowercaseUsername: 'kirk',
status: 'BANNED',
canEditName: false
});
});
it('completes the migration', async () => {
let user = await UserModel.collection.findOne({id: '123'});
expect(user).to.have.property('status');
expect(user.status).to.equal('BANNED');
// Perform the migration.
await migration.up();
user = await UserModel.collection.findOne({id: '123'});
// Check that it was correct.
expect(user).to.have.property('status');
expect(user.status).to.have.property('banned');
expect(user.status.banned).to.have.property('status', true);
});
});
});