serverless-sequelize-migrations
Version:
A Serverless plugin to manage sequelize migrations
1,156 lines (988 loc) • 36.2 kB
JavaScript
const { expect } = require("chai");
const sinon = require("sinon");
const Sequelize = require("sequelize");
const Umzug = require("umzug");
const chai = require("chai");
const chaiAsPromised = require("chai-as-promised");
const MigrationsHandler = require("../handlers/migrationsHandler");
chai.use(chaiAsPromised);
describe("Migrations Handler", () => {
describe("initial setup", () => {
describe("initialize", () => {
before(() => {
this.serverless = {
cli: {
log: () => {}
}
};
this.database = {
CONNECTION_URL: "mysql://username:password@localhost:3306/name"
};
});
it("calls initSequelize and initUmzug with success", () => {
const initSequelizeStub = sinon
.stub(MigrationsHandler.prototype, "initSequelize")
.callsFake(() => "sequelize instance");
const initUmzugStub = sinon
.stub(MigrationsHandler.prototype, "initUmzug")
.callsFake(() => "umzug instance");
new MigrationsHandler(this.serverless, this.database).initialize();
sinon.assert.calledOnce(MigrationsHandler.prototype.initSequelize);
sinon.assert.calledOnce(MigrationsHandler.prototype.initUmzug);
initSequelizeStub.restore();
initUmzugStub.restore();
});
it("fails on initializing sequelize", () => {
const error = new Error("somthing wrong");
const initSequelizeStub = sinon
.stub(MigrationsHandler.prototype, "initSequelize")
.throws(error);
const initUmzugStub = sinon
.stub(MigrationsHandler.prototype, "initUmzug")
.callsFake(() => "umzug instance");
expect(() =>
new MigrationsHandler(this.serverless, this.database).initialize()
).to.throw(error);
sinon.assert.threw(MigrationsHandler.prototype.initSequelize, error);
sinon.assert.notCalled(MigrationsHandler.prototype.initUmzug);
initSequelizeStub.restore();
initUmzugStub.restore();
});
it("fails on initializing umzug", () => {
const error = new Error("somthing wrong");
const initSequelizeStub = sinon
.stub(MigrationsHandler.prototype, "initSequelize")
.callsFake(() => "sequelize instance");
const initUmzugStub = sinon
.stub(MigrationsHandler.prototype, "initUmzug")
.throws(error);
expect(() =>
new MigrationsHandler(this.serverless, this.database).initialize()
).to.throw(error);
sinon.assert.calledOnce(MigrationsHandler.prototype.initSequelize);
sinon.assert.threw(MigrationsHandler.prototype.initUmzug, error);
initSequelizeStub.restore();
initUmzugStub.restore();
});
});
describe("initSequelize", () => {
before(() => {
this.serverless = {
cli: {
log: () => {}
}
};
});
it("creates sequelize instance with success", () => {
const database = {
CONNECTION_URL: "mysql://username:password@localhost:3306/name"
};
const migrationsHandler = new MigrationsHandler(
this.serverless,
database
);
const sequelize = migrationsHandler.initSequelize();
expect(sequelize.options.define.freezeTableName).to.eq(true);
});
it("fails if DB_DIALECT is missing", () => {
const database = {
HOST: "localhost",
PORT: "3306",
NAME: "name",
USERNAME: "username",
PASSWORD: "password"
};
expect(() =>
new MigrationsHandler(this.serverless, database).initSequelize()
).to.throw();
});
});
describe("initUmzug", () => {
before(() => {
this.serverless = {
cli: {
log: () => {}
}
};
this.database = {
CONNECTION_URL: "mysql://username:password@localhost:3306/name"
};
});
it("creates umzug instance with success", () => {
const migrationsHandler = new MigrationsHandler(
this.serverless,
this.database
);
migrationsHandler.sequelize = migrationsHandler.initSequelize();
const umzug = migrationsHandler.initUmzug();
expect(umzug.options.storage).to.eq("sequelize");
expect(umzug.options.storageOptions.sequelize).to.eq(
migrationsHandler.sequelize
);
expect(umzug.options.upName).to.eq("up");
expect(umzug.options.downName).to.eq("down");
expect(umzug.options.migrations.path).to.eq("./migrations");
});
it("creates umzug instance specifying migrations path", () => {
const migrationsHandler = new MigrationsHandler(
this.serverless,
this.database,
"./migrationModels"
);
migrationsHandler.sequelize = migrationsHandler.initSequelize();
const umzug = migrationsHandler.initUmzug();
expect(umzug.options.storage).to.eq("sequelize");
expect(umzug.options.storageOptions.sequelize).to.eq(
migrationsHandler.sequelize
);
expect(umzug.options.upName).to.eq("up");
expect(umzug.options.downName).to.eq("down");
expect(umzug.options.migrations.path).to.eq("./migrationModels");
});
it("fails if sequelize is not initialized", () => {
const migrationsHandler = new MigrationsHandler(
this.serverless,
this.database
);
migrationsHandler.sequelize = null;
expect(() =>
new MigrationsHandler(this.serverless, this.database).initUmzug()
).to.throw();
});
});
describe("migrate", () => {
before(() => {
this.serverless = {
cli: {}
};
this.database = {
CONNECTION_URL: "mysql://username:password@localhost:3306/name"
};
});
beforeEach(() => {
this.sequelizeCloseStub = sinon.stub(Sequelize.prototype, "close");
this.serverless.cli.log = sinon.spy();
});
afterEach(() => {
this.sequelizeCloseStub.restore();
this.serverless.cli.log.resetHistory();
});
it("returns ok if there is no pending migrations", async () => {
const migrationsHandler = new MigrationsHandler(
this.serverless,
this.database
);
migrationsHandler.initialize();
const pendingStub = sinon.stub(Umzug.prototype, "pending").resolves([]);
const success = await migrationsHandler.migrate();
expect(success).to.eq(true);
sinon.assert.calledWith(
this.serverless.cli.log,
"Looking for pending migrations..."
);
sinon.assert.calledWith(
this.serverless.cli.log,
"No pending migrations to apply"
);
sinon.assert.calledOnce(migrationsHandler.umzug.pending);
sinon.assert.calledOnce(migrationsHandler.sequelize.close);
pendingStub.restore();
});
it("migrate with success", async () => {
const migrationsHandler = new MigrationsHandler(
this.serverless,
this.database
);
migrationsHandler.initialize();
const migrations = [
{
file: "migration1.js"
},
{
file: "migration2.js"
}
];
const pendingStub = sinon
.stub(Umzug.prototype, "pending")
.resolves(migrations);
const upStub = sinon.stub(Umzug.prototype, "up").resolves(migrations);
const consLogStub = sinon.stub(console, "log");
const success = await migrationsHandler.migrate();
expect(success).to.eq(true);
sinon.assert.calledWith(
this.serverless.cli.log,
"Looking for pending migrations..."
);
sinon.assert.calledWith(
this.serverless.cli.log,
"Applying pending migrations..."
);
sinon.assert.calledWith(
this.serverless.cli.log,
"2 applied migrations"
);
sinon.assert.calledWith(consLogStub, `=> ${migrations[0].file}`);
sinon.assert.calledWith(consLogStub, `=> ${migrations[1].file}`);
sinon.assert.calledOnce(migrationsHandler.umzug.pending);
sinon.assert.calledOnce(migrationsHandler.umzug.up);
sinon.assert.calledOnce(migrationsHandler.sequelize.close);
pendingStub.restore();
upStub.restore();
consLogStub.restore();
});
context("cannot apply migrations", () => {
it("fails on first migration file", async () => {
const migrationsHandler = new MigrationsHandler(
this.serverless,
this.database
);
migrationsHandler.initialize();
const migrations = [
{
file: "migration1.js"
},
{
file: "migration2.js"
}
];
const pendingStub = sinon
.stub(Umzug.prototype, "pending")
.resolves(migrations);
const upStub = sinon.stub(Umzug.prototype, "up").rejects(migrations);
const executedStub = sinon
.stub(Umzug.prototype, "executed")
.resolves([]);
const success = await migrationsHandler.migrate();
expect(success).to.eq(false);
sinon.assert.calledWith(
this.serverless.cli.log,
"Looking for pending migrations..."
);
sinon.assert.calledWith(
this.serverless.cli.log,
"Applying pending migrations..."
);
sinon.assert.calledWith(
this.serverless.cli.log,
"Error while applying migrations"
);
sinon.assert.calledWith(
this.serverless.cli.log,
"Looking for migration that has problems..."
);
sinon.assert.calledWith(
this.serverless.cli.log,
`Something wrong with ${migrations[0].file}`
);
sinon.assert.calledOnce(migrationsHandler.umzug.pending);
sinon.assert.calledOnce(migrationsHandler.umzug.up);
sinon.assert.calledOnce(migrationsHandler.umzug.executed);
sinon.assert.calledOnce(migrationsHandler.sequelize.close);
pendingStub.restore();
upStub.restore();
executedStub.restore();
});
it("fails on second migration file", async () => {
const migrationsHandler = new MigrationsHandler(
this.serverless,
this.database
);
migrationsHandler.initialize();
const migrations = [
{
file: "migration1.js"
},
{
file: "migration2.js"
}
];
const pendingStub = sinon
.stub(Umzug.prototype, "pending")
.resolves(migrations);
const upStub = sinon.stub(Umzug.prototype, "up").rejects(migrations);
const executedStub = sinon
.stub(Umzug.prototype, "executed")
.resolves([
{
file: "migration1.js"
}
]);
const success = await migrationsHandler.migrate();
expect(success).to.eq(false);
sinon.assert.calledWith(
this.serverless.cli.log,
"Looking for pending migrations..."
);
sinon.assert.calledWith(
this.serverless.cli.log,
"Applying pending migrations..."
);
sinon.assert.calledWith(
this.serverless.cli.log,
"Error while applying migrations"
);
sinon.assert.calledWith(
this.serverless.cli.log,
"Looking for migration that has problems..."
);
sinon.assert.calledWith(
this.serverless.cli.log,
`Something wrong with ${migrations[1].file}`
);
sinon.assert.calledOnce(migrationsHandler.umzug.pending);
sinon.assert.calledOnce(migrationsHandler.umzug.up);
sinon.assert.calledOnce(migrationsHandler.umzug.executed);
sinon.assert.calledOnce(migrationsHandler.sequelize.close);
pendingStub.restore();
upStub.restore();
executedStub.restore();
});
it("fails on first migration file and revert", async () => {
const migrationsHandler = new MigrationsHandler(
this.serverless,
this.database
);
migrationsHandler.initialize();
const migrations = [
{
file: "migration1.js"
},
{
file: "migration2.js"
}
];
const pendingStub = sinon
.stub(Umzug.prototype, "pending")
.resolves(migrations);
const upStub = sinon.stub(Umzug.prototype, "up").rejects(migrations);
const executedStub = sinon
.stub(Umzug.prototype, "executed")
.resolves([]);
const downStub = sinon.stub(Umzug.prototype, "down");
const success = await migrationsHandler.migrate(true);
expect(success).to.eq(false);
sinon.assert.calledWith(
this.serverless.cli.log,
"Looking for pending migrations..."
);
sinon.assert.calledWith(
this.serverless.cli.log,
"Applying pending migrations..."
);
sinon.assert.calledWith(
this.serverless.cli.log,
"Error while applying migrations"
);
sinon.assert.calledWith(
this.serverless.cli.log,
"Looking for migration that has problems..."
);
sinon.assert.calledWith(
this.serverless.cli.log,
`Something wrong with ${migrations[0].file}`
);
sinon.assert.calledOnce(migrationsHandler.umzug.pending);
sinon.assert.calledOnce(migrationsHandler.umzug.up);
sinon.assert.calledOnce(migrationsHandler.umzug.executed);
sinon.assert.notCalled(migrationsHandler.umzug.down);
sinon.assert.calledOnce(migrationsHandler.sequelize.close);
pendingStub.restore();
upStub.restore();
executedStub.restore();
downStub.restore();
});
it("fails on second migration file and revert", async () => {
const migrationsHandler = new MigrationsHandler(
this.serverless,
this.database
);
migrationsHandler.initialize();
const migrations = [
{
file: "migration1.js"
},
{
file: "migration2.js"
}
];
const pendingStub = sinon
.stub(Umzug.prototype, "pending")
.resolves(migrations);
const upStub = sinon.stub(Umzug.prototype, "up").rejects(migrations);
const executedStub = sinon
.stub(Umzug.prototype, "executed")
.resolves([
{
file: "migration1.js"
}
]);
const downStub = sinon.stub(Umzug.prototype, "down").resolves([
{
file: "migration1.js"
}
]);
const consLogStub = sinon.stub(console, "log");
const success = await migrationsHandler.migrate(true);
expect(success).to.eq(false);
sinon.assert.calledWith(
this.serverless.cli.log,
"Looking for pending migrations..."
);
sinon.assert.calledWith(
this.serverless.cli.log,
"Applying pending migrations..."
);
sinon.assert.calledWith(
this.serverless.cli.log,
"Error while applying migrations"
);
sinon.assert.calledWith(
this.serverless.cli.log,
"Looking for migration that has problems..."
);
sinon.assert.calledWith(
this.serverless.cli.log,
`Something wrong with ${migrations[1].file}`
);
sinon.assert.calledWith(
this.serverless.cli.log,
"Reverting applied migrations..."
);
sinon.assert.calledWith(
consLogStub,
`=> reverted ${migrations[0].file}`
);
sinon.assert.calledOnce(migrationsHandler.umzug.pending);
sinon.assert.calledOnce(migrationsHandler.umzug.up);
sinon.assert.calledOnce(migrationsHandler.umzug.executed);
sinon.assert.calledWith(migrationsHandler.umzug.down, {
migrations: ["migration1.js"]
});
sinon.assert.calledOnce(migrationsHandler.sequelize.close);
pendingStub.restore();
upStub.restore();
executedStub.restore();
downStub.restore();
consLogStub.restore();
});
});
});
describe("revert", () => {
before(() => {
this.serverless = {
cli: {}
};
this.database = {
CONNECTION_URL: "mysql://username:password@localhost:3306/name"
};
});
beforeEach(() => {
this.sequelizeCloseStub = sinon.stub(Sequelize.prototype, "close");
this.serverless.cli.log = sinon.spy();
});
afterEach(() => {
this.sequelizeCloseStub.restore();
this.serverless.cli.log.resetHistory();
});
context("when --times and --name are not defined", () => {
it("runs ok if there is no executed migrations", async () => {
const migrationsHandler = new MigrationsHandler(
this.serverless,
this.database
);
migrationsHandler.initialize();
const downStub = sinon.stub(Umzug.prototype, "down").resolves([]);
await migrationsHandler.revert();
sinon.assert.calledWith(
this.serverless.cli.log,
"Trying to revert the last migration"
);
sinon.assert.calledOnce(migrationsHandler.umzug.down);
sinon.assert.calledOnce(migrationsHandler.sequelize.close);
downStub.restore();
});
it("revert last migration with success", async () => {
const migrationsHandler = new MigrationsHandler(
this.serverless,
this.database
);
migrationsHandler.initialize();
const migrations = [
{
file: "migration1.js"
}
];
const downStub = sinon
.stub(Umzug.prototype, "down")
.resolves(migrations);
const consLogStub = sinon.stub(console, "log");
await migrationsHandler.revert();
sinon.assert.calledWith(
this.serverless.cli.log,
"Trying to revert the last migration"
);
sinon.assert.calledOnce(migrationsHandler.umzug.down);
sinon.assert.calledWith(
this.serverless.cli.log,
"1 reverted migrations"
);
sinon.assert.calledWith(consLogStub, "=> migration1.js");
sinon.assert.calledOnce(migrationsHandler.sequelize.close);
downStub.restore();
consLogStub.restore();
});
});
context("when --times > 1 and --name is not defined", () => {
it("runs ok if there is no executed migrations", async () => {
const migrationsHandler = new MigrationsHandler(
this.serverless,
this.database
);
migrationsHandler.initialize();
const executedStub = sinon
.stub(Umzug.prototype, "executed")
.resolves([]);
const downStub = sinon.stub(Umzug.prototype, "down").resolves([]);
const times = 2;
await migrationsHandler.revert(times);
sinon.assert.calledWith(
this.serverless.cli.log,
`Trying to revert the last ${times} migrations`
);
sinon.assert.calledWith(
this.serverless.cli.log,
`There isn't migrations to revert`
);
sinon.assert.calledOnce(migrationsHandler.umzug.executed);
sinon.assert.notCalled(migrationsHandler.umzug.down);
sinon.assert.calledOnce(migrationsHandler.sequelize.close);
downStub.restore();
executedStub.restore();
});
it("revert the two last migration with success", async () => {
const migrationsHandler = new MigrationsHandler(
this.serverless,
this.database
);
migrationsHandler.initialize();
const migrations = [
{
file: "migration1.js"
},
{
file: "migration2.js"
},
{
file: "migration3.js"
}
];
const executedStub = sinon
.stub(Umzug.prototype, "executed")
.resolves(migrations);
const downStub = sinon
.stub(Umzug.prototype, "down")
.resolves([migrations[1], migrations[2]]);
const consLogStub = sinon.stub(console, "log");
const times = 2;
await migrationsHandler.revert(times);
sinon.assert.calledWith(
this.serverless.cli.log,
`Trying to revert the last ${times} migrations`
);
sinon.assert.calledWith(migrationsHandler.umzug.down, {
migrations: [migrations[2].file, migrations[1].file]
});
sinon.assert.calledWith(
this.serverless.cli.log,
`${times} reverted migrations`
);
sinon.assert.calledWith(consLogStub, "=> migration3.js");
sinon.assert.calledWith(consLogStub, "=> migration2.js");
sinon.assert.calledOnce(migrationsHandler.sequelize.close);
downStub.restore();
consLogStub.restore();
executedStub.restore();
});
it("revert all migrations passing a high --times value", async () => {
const migrationsHandler = new MigrationsHandler(
this.serverless,
this.database
);
migrationsHandler.initialize();
const migrations = [
{
file: "migration1.js"
},
{
file: "migration2.js"
},
{
file: "migration3.js"
}
];
const executedStub = sinon
.stub(Umzug.prototype, "executed")
.resolves(migrations);
const downStub = sinon
.stub(Umzug.prototype, "down")
.resolves(migrations);
const consLogStub = sinon.stub(console, "log");
const times = 100;
await migrationsHandler.revert(times);
sinon.assert.calledWith(
this.serverless.cli.log,
`Trying to revert the last ${times} migrations`
);
sinon.assert.calledWith(migrationsHandler.umzug.down, {
migrations: [
migrations[2].file,
migrations[1].file,
migrations[0].file
]
});
sinon.assert.calledWith(
this.serverless.cli.log,
`${migrations.length} reverted migrations`
);
sinon.assert.calledWith(consLogStub, "=> migration3.js");
sinon.assert.calledWith(consLogStub, "=> migration2.js");
sinon.assert.calledOnce(migrationsHandler.sequelize.close);
downStub.restore();
consLogStub.restore();
executedStub.restore();
});
});
context("when --times < 1 and name is not defined", () => {
it("throws an error", async () => {
const migrationsHandler = new MigrationsHandler(
this.serverless,
this.database
);
migrationsHandler.initialize();
await expect(migrationsHandler.revert(0)).to.be.rejectedWith(
"--times must be greater than 0"
);
});
});
context("when name is defined", () => {
it("runs ok if there is no executed migrations with name", async () => {
const migrationsHandler = new MigrationsHandler(
this.serverless,
this.database
);
migrationsHandler.initialize();
const downStub = sinon.stub(Umzug.prototype, "down").resolves([]);
await migrationsHandler.revert();
sinon.assert.calledWith(
this.serverless.cli.log,
"Trying to revert the last migration"
);
sinon.assert.calledOnce(migrationsHandler.umzug.down);
sinon.assert.calledOnce(migrationsHandler.sequelize.close);
downStub.restore();
});
it("revert named migration with success", async () => {
const migrationsHandler = new MigrationsHandler(
this.serverless,
this.database
);
migrationsHandler.initialize();
const migrations = [
{
file: "migration1.js"
},
{
file: "migration2.js"
},
{
file: "migration3.js"
}
];
const downStub = sinon
.stub(Umzug.prototype, "down")
.resolves([migrations[1]]);
const consLogStub = sinon.stub(console, "log");
const name = "migration2.js";
await migrationsHandler.revert(1, name);
sinon.assert.calledWith(
this.serverless.cli.log,
`Trying to revert migration ${name}`
);
sinon.assert.calledWith(migrationsHandler.umzug.down, {
migrations: [name]
});
sinon.assert.calledWith(
this.serverless.cli.log,
"1 reverted migrations"
);
sinon.assert.calledWith(consLogStub, `=> ${name}`);
sinon.assert.calledOnce(migrationsHandler.sequelize.close);
downStub.restore();
consLogStub.restore();
});
});
});
describe("reset", () => {
before(() => {
this.serverless = {
cli: {}
};
this.database = {
CONNECTION_URL: "mysql://username:password@localhost:3306/name"
};
});
beforeEach(() => {
this.sequelizeCloseStub = sinon.stub(Sequelize.prototype, "close");
this.serverless.cli.log = sinon.spy();
});
afterEach(() => {
this.sequelizeCloseStub.restore();
this.serverless.cli.log.resetHistory();
});
it("runs ok if there is no executed migrations", async () => {
const migrationsHandler = new MigrationsHandler(
this.serverless,
this.database
);
migrationsHandler.initialize();
const downStub = sinon.stub(Umzug.prototype, "down").resolves([]);
await migrationsHandler.reset();
sinon.assert.calledWith(
this.serverless.cli.log,
"Trying to revert all migrations..."
);
sinon.assert.calledWith(migrationsHandler.umzug.down, {
to: 0
});
sinon.assert.calledOnce(migrationsHandler.sequelize.close);
downStub.restore();
});
it("revert all migrations with success", async () => {
const migrationsHandler = new MigrationsHandler(
this.serverless,
this.database
);
migrationsHandler.initialize();
const migrations = [
{
file: "migration1.js"
},
{
file: "migration2.js"
},
{
file: "migration3.js"
}
];
const downStub = sinon
.stub(Umzug.prototype, "down")
.resolves(migrations);
const consLogStub = sinon.stub(console, "log");
await migrationsHandler.reset();
sinon.assert.calledWith(
this.serverless.cli.log,
"Trying to revert all migrations..."
);
sinon.assert.calledWith(migrationsHandler.umzug.down, {
to: 0
});
sinon.assert.calledWith(
this.serverless.cli.log,
`${migrations.length} reverted migrations`
);
sinon.assert.calledWith(consLogStub, "=> migration3.js");
sinon.assert.calledWith(consLogStub, "=> migration2.js");
sinon.assert.calledWith(consLogStub, "=> migration1.js");
sinon.assert.calledOnce(migrationsHandler.sequelize.close);
downStub.restore();
consLogStub.restore();
});
});
describe("list", () => {
before(() => {
this.serverless = {
cli: {}
};
this.database = {
CONNECTION_URL: "mysql://username:password@localhost:3306/name"
};
});
beforeEach(() => {
this.sequelizeCloseStub = sinon.stub(Sequelize.prototype, "close");
this.serverless.cli.log = sinon.spy();
});
afterEach(() => {
this.sequelizeCloseStub.restore();
this.serverless.cli.log.resetHistory();
});
context("when there are no explicitly passed parameters", () => {
it("returns ok if there are no pending migrations", async () => {
const migrationsHandler = new MigrationsHandler(
this.serverless,
this.database
);
migrationsHandler.initialize();
const pendingStub = sinon
.stub(Umzug.prototype, "pending")
.resolves([]);
await migrationsHandler.list();
sinon.assert.calledWith(
this.serverless.cli.log,
"Searching for pending migrations..."
);
sinon.assert.calledOnce(migrationsHandler.umzug.pending);
sinon.assert.calledOnce(migrationsHandler.sequelize.close);
pendingStub.restore();
});
it("returns pending migrations", async () => {
const migrationsHandler = new MigrationsHandler(
this.serverless,
this.database
);
migrationsHandler.initialize();
const migrations = [
{
file: "migrations1.js"
},
{
file: "migrations2.js"
},
{
file: "migrations3.js"
}
];
const pendingStub = sinon
.stub(Umzug.prototype, "pending")
.resolves(migrations);
const consLogStub = sinon.stub(console, "log");
await migrationsHandler.list();
sinon.assert.calledWith(
this.serverless.cli.log,
"Searching for pending migrations..."
);
sinon.assert.calledOnce(migrationsHandler.umzug.pending);
sinon.assert.calledOnce(migrationsHandler.sequelize.close);
sinon.assert.calledWith(consLogStub, `=> ${migrations[0].file}`);
sinon.assert.calledWith(consLogStub, `=> ${migrations[1].file}`);
sinon.assert.calledWith(consLogStub, `=> ${migrations[2].file}`);
pendingStub.restore();
consLogStub.restore();
});
});
context("when there are explicitly passed parameters", () => {
context(`when calling with 'pending' status`, () => {
it("returns ok if there are no pending migrations", async () => {
const migrationsHandler = new MigrationsHandler(
this.serverless,
this.database
);
migrationsHandler.initialize();
const pendingStub = sinon
.stub(Umzug.prototype, "pending")
.resolves([]);
const status = "pending";
await migrationsHandler.list(status);
sinon.assert.calledWith(
this.serverless.cli.log,
`Searching for ${status} migrations...`
);
sinon.assert.calledOnce(migrationsHandler.umzug.pending);
sinon.assert.calledOnce(migrationsHandler.sequelize.close);
pendingStub.restore();
});
it("returns pending migrations", async () => {
const migrationsHandler = new MigrationsHandler(
this.serverless,
this.database
);
migrationsHandler.initialize();
const migrations = [
{
file: "migrations1.js"
},
{
file: "migrations2.js"
},
{
file: "migrations3.js"
}
];
const pendingStub = sinon
.stub(Umzug.prototype, "pending")
.resolves(migrations);
const consLogStub = sinon.stub(console, "log");
const status = "pending";
await migrationsHandler.list(status);
sinon.assert.calledWith(
this.serverless.cli.log,
`Searching for ${status} migrations...`
);
sinon.assert.calledOnce(migrationsHandler.umzug.pending);
sinon.assert.calledOnce(migrationsHandler.sequelize.close);
sinon.assert.calledWith(consLogStub, `=> ${migrations[0].file}`);
sinon.assert.calledWith(consLogStub, `=> ${migrations[1].file}`);
sinon.assert.calledWith(consLogStub, `=> ${migrations[2].file}`);
pendingStub.restore();
consLogStub.restore();
});
});
context(`when calling with 'executed' status`, () => {
it("returns ok if there are no executed migrations", async () => {
const migrationsHandler = new MigrationsHandler(
this.serverless,
this.database
);
migrationsHandler.initialize();
const executedStub = sinon
.stub(Umzug.prototype, "executed")
.resolves([]);
const status = "executed";
await migrationsHandler.list(status);
sinon.assert.calledWith(
this.serverless.cli.log,
`Searching for ${status} migrations...`
);
sinon.assert.calledOnce(migrationsHandler.umzug.executed);
sinon.assert.calledOnce(migrationsHandler.sequelize.close);
executedStub.restore();
});
it("returns executed migrations", async () => {
const migrationsHandler = new MigrationsHandler(
this.serverless,
this.database
);
migrationsHandler.initialize();
const migrations = [
{
file: "migrations1.js"
},
{
file: "migrations2.js"
},
{
file: "migrations3.js"
}
];
const executedStub = sinon
.stub(Umzug.prototype, "executed")
.resolves(migrations);
const consLogStub = sinon.stub(console, "log");
const status = "executed";
await migrationsHandler.list(status);
sinon.assert.calledWith(
this.serverless.cli.log,
`Searching for ${status} migrations...`
);
sinon.assert.calledOnce(migrationsHandler.umzug.executed);
sinon.assert.calledOnce(migrationsHandler.sequelize.close);
sinon.assert.calledWith(consLogStub, `=> ${migrations[0].file}`);
sinon.assert.calledWith(consLogStub, `=> ${migrations[1].file}`);
sinon.assert.calledWith(consLogStub, `=> ${migrations[2].file}`);
executedStub.restore();
consLogStub.restore();
});
});
});
});
});
});