From ea1153a89f9fce40cb39c8042026c0635ed7e101 Mon Sep 17 00:00:00 2001 From: Lee Allen Date: Sun, 12 May 2019 13:36:19 -0400 Subject: [PATCH 01/11] Add ability to run migrate:up command to only run the next migration --- bin/cli.js | 22 ++++++++++++++++++++++ src/migrate/Migrator.js | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/bin/cli.js b/bin/cli.js index 5b2c9caab4..a857e4d817 100755 --- a/bin/cli.js +++ b/bin/cli.js @@ -230,6 +230,28 @@ function invoke(env) { .catch(exit); }); + commander + .command('migrate:up') + .description(' Run the next migration that has not yet been run.') + .action(() => { + pending = initKnex(env, commander.opts()) + .migrate.up() + .spread((batchNo, log) => { + if (log.length === 0) { + success(color.cyan('Already up to date')); + } + + success( + color.green( + `Batch ${batchNo} ran the following migrations:\n${log.join( + '\n' + )}` + ) + ); + }) + .catch(exit); + }); + commander .command('migrate:rollback') .description(' Rollback the last batch of migrations performed.') diff --git a/src/migrate/Migrator.js b/src/migrate/Migrator.js index ceed517963..ebfd3a9d9e 100644 --- a/src/migrate/Migrator.js +++ b/src/migrate/Migrator.js @@ -141,6 +141,43 @@ export default class Migrator { }); } + // Runs the next migration that has not yet been run + up(config) { + this._disableProcessing(); + this.config = getMergedConfig(config, this.config); + + return migrationListResolver + .listAllAndCompleted(this.config, this.knex) + .tap((value) => validateMigrationList(this.config.migrationSource, value)) + .spread((all, completed) => { + const migrationToRun = getNewMigrations( + this.config.migrationSource, + all, + completed + ).slice(0, 1); + + const transactionForAll = + !this.config.disableTransactions && + isEmpty( + filter(migrationToRun, (migration) => { + const migrationContents = this.config.migrationSource.getMigration( + migration + ); + + return !this._useTransaction(migrationContents); + }) + ); + + if (transactionForAll) { + return this.knex.transaction((trx) => { + return this._runBatch(migrationToRun, 'up', trx); + }); + } else { + return this._runBatch(migrationToRun, 'up'); + } + }); + } + // Rollback the last "batch", or all, of migrations that were run. rollback(config, all = false) { this._disableProcessing(); From e589dcca84b6c2fcf23d6d90d9f81a4339040c15 Mon Sep 17 00:00:00 2001 From: Lee Allen Date: Sun, 12 May 2019 16:53:06 -0400 Subject: [PATCH 02/11] Add cli test for migrate:up --- test/jake/jakelib/migrate-test.js | 124 ++++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) diff --git a/test/jake/jakelib/migrate-test.js b/test/jake/jakelib/migrate-test.js index 0360ae7531..ad18c282cd 100644 --- a/test/jake/jakelib/migrate-test.js +++ b/test/jake/jakelib/migrate-test.js @@ -430,6 +430,130 @@ test('migrate:up runs only the next unrun migration', (temp) => { }); }); +test('migrate:up runs only the next unrun migration', (temp) => { + const migrationFile1 = '001_create_books_table.js'; + const migrationFile2 = '002_add_pages_column_to_books_table.js'; + + fs.writeFileSync( + `${temp}/migrations/${migrationFile1}`, + ` + exports.up = (knex) => knex.schema + .createTable('books', (table) => { + table.string('title'); + }); + + exports.down = (knex) => knex.schema.dropTable('books'); + ` + ); + + fs.writeFileSync( + `${temp}/migrations/${migrationFile2}`, + ` + exports.up = (knex) => knex.schema + .table('books', (table) => { + table.integer('pages'); + }); + + exports.down = (knex) => knex.schema + .table('books', (table) => { + table.dropColumn('pages'); + }); + ` + ); + + return assertExec( + `node ${KNEX} migrate:up \ + --client=sqlite3 \ + --connection=${temp}/db \ + --migrations-directory=${temp}/migrations`, + 'create_books_table' + ) + .then(({ stdout }) => { + assert.include( + stdout, + `Batch 1 ran the following migrations:\n${migrationFile1}` + ); + + const db = new sqlite3.Database(`${temp}/db`); + + return new Promise((resolve, reject) => { + db.all('SELECT * FROM knex_migrations', (err, rows) => { + const migrationsWithoutMigrationTime = rows.map((row) => { + return { + id: row.id, + name: row.name, + batch: row.batch, + }; + }); + + assert.includeDeepOrderedMembers(migrationsWithoutMigrationTime, [ + { + id: 1, + name: migrationFile1, + batch: 1, + }, + ]); + + err ? reject(err) : resolve(rows); + }); + }); + }) + .then(() => { + return assertExec( + `node ${KNEX} migrate:up \ + --client=sqlite3 \ + --connection=${temp}/db \ + --migrations-directory=${temp}/migrations`, + 'create_books_table' + ).then(({ stdout }) => { + assert.include( + stdout, + `Batch 2 ran the following migrations:\n${migrationFile2}` + ); + + const db = new sqlite3.Database(`${temp}/db`); + + return new Promise((resolve, reject) => { + db.all('SELECT * FROM knex_migrations', (err, rows) => { + const migrationsWithoutMigrationTime = rows.map((row) => { + return { + id: row.id, + name: row.name, + batch: row.batch, + }; + }); + + assert.includeDeepOrderedMembers(migrationsWithoutMigrationTime, [ + { + id: 1, + name: migrationFile1, + batch: 1, + }, + { + id: 2, + name: migrationFile2, + batch: 2, + }, + ]); + + err ? reject(err) : resolve(rows); + }); + }); + }); + }) + .then(() => { + return assertExec( + `node ${KNEX} migrate:up \ + --client=sqlite3 \ + --connection=${temp}/db \ + --migrations-directory=${temp}/migrations`, + 'create_books_table' + ).then(({ stdout }) => { + assert.include(stdout, 'Already up to date'); + }); + }); +}); + module.exports = { taskList, }; From f857da76ff14cc6ccfd3b83da7ea92744bf4f718 Mon Sep 17 00:00:00 2001 From: Lee Allen Date: Sun, 12 May 2019 17:44:50 -0400 Subject: [PATCH 03/11] Add test for migrator --- test/integration/migrate/index.js | 68 +++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/test/integration/migrate/index.js b/test/integration/migrate/index.js index 2aaa28074e..e24a7f0dd8 100644 --- a/test/integration/migrate/index.js +++ b/test/integration/migrate/index.js @@ -582,6 +582,74 @@ module.exports = function(knex) { }); }); + describe('knex.migrate.up', () => { + afterEach(() => { + return knex.migrate.rollback( + { directory: 'test/integration/migrate/test' }, + true + ); + }); + + it('should only run the first migration if no migrations have run', function() { + return knex.migrate + .up({ + directory: 'test/integration/migrate/test', + }) + .then(() => { + return knex('knex_migrations') + .select('*') + .then(function(data) { + expect(data).to.have.length(1); + expect(path.basename(data[0].name)).to.equal( + '20131019235242_migration_1.js' + ); + }); + }); + }); + + it('should only run the next migration that has not yet run if other migrations have already run', function() { + return knex.migrate + .up({ + directory: 'test/integration/migrate/test', + }) + .then(() => { + return knex.migrate + .up({ + directory: 'test/integration/migrate/test', + }) + .then(() => { + return knex('knex_migrations') + .select('*') + .then(function(data) { + expect(data).to.have.length(2); + expect(path.basename(data[0].name)).to.equal( + '20131019235242_migration_1.js' + ); + expect(path.basename(data[1].name)).to.equal( + '20131019235306_migration_2.js' + ); + }); + }); + }); + }); + + it('should not error and return a resolved promise if all migrations have already been run', function() { + return knex.migrate + .latest({ + directory: 'test/integration/migrate/test', + }) + .then(() => { + return knex.migrate + .up({ + directory: 'test/integration/migrate/test', + }) + .then((data) => { + expect(data).to.be.an('array'); + }); + }); + }); + }); + after(function() { rimraf.sync(path.join(__dirname, './migration')); }); From 772fcf00b1d22017ac84bcf8fcbe6a36dc5321c9 Mon Sep 17 00:00:00 2001 From: Lee Allen Date: Thu, 16 May 2019 19:15:32 -0400 Subject: [PATCH 04/11] Fix wording of test --- test/integration/migrate/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/migrate/index.js b/test/integration/migrate/index.js index e24a7f0dd8..db7831e952 100644 --- a/test/integration/migrate/index.js +++ b/test/integration/migrate/index.js @@ -633,7 +633,7 @@ module.exports = function(knex) { }); }); - it('should not error and return a resolved promise if all migrations have already been run', function() { + it('should not error if all migrations have already been run', function() { return knex.migrate .latest({ directory: 'test/integration/migrate/test', From 91a8f83cd7d103e9806c24a9e059b4cbc4d4e195 Mon Sep 17 00:00:00 2001 From: Lee Allen Date: Thu, 16 May 2019 19:40:13 -0400 Subject: [PATCH 05/11] Add type and stub --- src/migrate/migrate-stub.js | 1 + types/index.d.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/src/migrate/migrate-stub.js b/src/migrate/migrate-stub.js index eea5a59615..7154d291af 100644 --- a/src/migrate/migrate-stub.js +++ b/src/migrate/migrate-stub.js @@ -15,4 +15,5 @@ StubMigrate.prototype = { rollback: noSuchMethod, currentVersion: noSuchMethod, up: noSuchMethod, + down: noSuchMethod, }; diff --git a/types/index.d.ts b/types/index.d.ts index 44b852ef15..65bd1b67eb 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -1727,6 +1727,7 @@ declare namespace Knex { status(config?: MigratorConfig): Bluebird; currentVersion(config?: MigratorConfig): Bluebird; up(config?: MigratorConfig): Bluebird; + down(config?: MigratorConfig): Bluebird; } interface SeederConfig { From f24aa0c7ec64126af34988d1a5fa38a76f67dc8d Mon Sep 17 00:00:00 2001 From: Lee Allen Date: Thu, 16 May 2019 19:57:15 -0400 Subject: [PATCH 06/11] Add down method to Migrator and add functionality to cli --- bin/cli.js | 22 ++++++++++++++++++++++ src/migrate/Migrator.js | 23 +++++++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/bin/cli.js b/bin/cli.js index a857e4d817..23c6c6df1f 100755 --- a/bin/cli.js +++ b/bin/cli.js @@ -275,6 +275,28 @@ function invoke(env) { .catch(exit); }); + commander + .command('migrate:down') + .description(' Undo the last migration performed.') + .action(() => { + pending = initKnex(env, commander.opts()) + .migrate.down() + .spread((batchNo, log) => { + if (log.length === 0) { + success(color.cyan('Already at the base migration')); + } + + success( + color.green( + `Batch ${batchNo} rolled back the following migrations:\n${log.join( + '\n' + )}` + ) + ); + }) + .catch(exit); + }); + commander .command('migrate:currentVersion') .description(' View the current version for the migration.') diff --git a/src/migrate/Migrator.js b/src/migrate/Migrator.js index ebfd3a9d9e..997ad5bc4f 100644 --- a/src/migrate/Migrator.js +++ b/src/migrate/Migrator.js @@ -206,6 +206,29 @@ export default class Migrator { }); } + down(config) { + this._disableProcessing(); + this.config = getMergedConfig(config, this.config); + + return migrationListResolver + .listAllAndCompleted(this.config, this.knex) + .tap((value) => { + return validateMigrationList(this.config.migrationSource, value); + }) + .spread((all, completed) => { + const migrationToRun = all + .filter((migration) => { + return completed.includes( + this.config.migrationSource.getMigrationName(migration) + ); + }) + .reverse() + .slice(0, 1); + + return this._runBatch(migrationToRun, 'down'); + }); + } + status(config) { this._disableProcessing(); this.config = getMergedConfig(config, this.config); From 4298a4c6b63e51e60aa4e8cc7813d9c38e622a42 Mon Sep 17 00:00:00 2001 From: Lee Allen Date: Tue, 28 May 2019 20:45:38 -0400 Subject: [PATCH 07/11] Add cli test for migrate:down --- test/jake/jakelib/migrate-test.js | 125 ++++++++++++++---------------- 1 file changed, 57 insertions(+), 68 deletions(-) diff --git a/test/jake/jakelib/migrate-test.js b/test/jake/jakelib/migrate-test.js index ad18c282cd..5fb852dc53 100644 --- a/test/jake/jakelib/migrate-test.js +++ b/test/jake/jakelib/migrate-test.js @@ -423,26 +423,26 @@ test('migrate:up runs only the next unrun migration', (temp) => { --client=sqlite3 \ --connection=${temp}/db \ --migrations-directory=${temp}/migrations`, - 'create_books_table' + 'already_up_to_date' ).then(({ stdout }) => { assert.include(stdout, 'Already up to date'); }); }); }); -test('migrate:up runs only the next unrun migration', (temp) => { - const migrationFile1 = '001_create_books_table.js'; - const migrationFile2 = '002_add_pages_column_to_books_table.js'; +test('migrate:down undos only the last run migration', (temp) => { + const migrationFile1 = '001_create_address_table.js'; + const migrationFile2 = '002_add_zip_to_address_table.js'; fs.writeFileSync( `${temp}/migrations/${migrationFile1}`, ` exports.up = (knex) => knex.schema - .createTable('books', (table) => { - table.string('title'); + .createTable('address', (table) => { + table.string('street'); }); - exports.down = (knex) => knex.schema.dropTable('books'); + exports.down = (knex) => knex.schema.dropTable('address'); ` ); @@ -450,65 +450,35 @@ test('migrate:up runs only the next unrun migration', (temp) => { `${temp}/migrations/${migrationFile2}`, ` exports.up = (knex) => knex.schema - .table('books', (table) => { - table.integer('pages'); + .table('address', (table) => { + table.integer('zip_code'); }); exports.down = (knex) => knex.schema - .table('books', (table) => { - table.dropColumn('pages'); + .table('address', (table) => { + table.dropColumn('zip_code'); }); ` ); return assertExec( - `node ${KNEX} migrate:up \ + `node ${KNEX} migrate:latest \ --client=sqlite3 \ --connection=${temp}/db \ --migrations-directory=${temp}/migrations`, - 'create_books_table' - ) - .then(({ stdout }) => { - assert.include( - stdout, - `Batch 1 ran the following migrations:\n${migrationFile1}` - ); - - const db = new sqlite3.Database(`${temp}/db`); - - return new Promise((resolve, reject) => { - db.all('SELECT * FROM knex_migrations', (err, rows) => { - const migrationsWithoutMigrationTime = rows.map((row) => { - return { - id: row.id, - name: row.name, - batch: row.batch, - }; - }); - - assert.includeDeepOrderedMembers(migrationsWithoutMigrationTime, [ - { - id: 1, - name: migrationFile1, - batch: 1, - }, - ]); - - err ? reject(err) : resolve(rows); - }); - }); - }) - .then(() => { - return assertExec( - `node ${KNEX} migrate:up \ - --client=sqlite3 \ - --connection=${temp}/db \ - --migrations-directory=${temp}/migrations`, - 'create_books_table' - ).then(({ stdout }) => { + 'run_all_migrations' + ).then(() => { + return assertExec( + `node ${KNEX} migrate:down \ + --client=sqlite3 \ + --connection=${temp}/db \ + --migrations-directory=${temp}/migrations`, + 'undo_migration_002' + ) + .then(({ stdout }) => { assert.include( stdout, - `Batch 2 ran the following migrations:\n${migrationFile2}` + `Batch 1 rolled back the following migrations:\n${migrationFile2}` ); const db = new sqlite3.Database(`${temp}/db`); @@ -529,29 +499,48 @@ test('migrate:up runs only the next unrun migration', (temp) => { name: migrationFile1, batch: 1, }, - { - id: 2, - name: migrationFile2, - batch: 2, - }, ]); - err ? reject(err) : resolve(rows); + err ? reject(err) : resolve(); }); }); - }); - }) - .then(() => { - return assertExec( - `node ${KNEX} migrate:up \ + }) + .then(() => { + return assertExec( + `node ${KNEX} migrate:down \ --client=sqlite3 \ --connection=${temp}/db \ --migrations-directory=${temp}/migrations`, - 'create_books_table' - ).then(({ stdout }) => { - assert.include(stdout, 'Already up to date'); + 'undo_migration_002' + ).then(({ stdout }) => { + assert.include( + stdout, + `Batch 1 rolled back the following migrations:\n${migrationFile1}` + ); + + const db = new sqlite3.Database(`${temp}/db`); + + return new Promise((resolve, reject) => { + db.all('SELECT * FROM knex_migrations', (err, rows) => { + assert.isEmpty(rows); + + err ? reject(err) : resolve(); + }); + }); + }); + }) + .then(() => { + return assertExec( + `node ${KNEX} migrate:down \ + --client=sqlite3 \ + --connection=${temp}/db \ + --migrations-directory=${temp}/migrations`, + 'undo_migration_002' + ).then(({ stdout }) => { + assert.include(stdout, 'Already at the base migration'); + }); }); - }); + }); }); module.exports = { From c76708ec031070d0719d1af0a630ebec0b5d67bf Mon Sep 17 00:00:00 2001 From: Lee Allen Date: Tue, 28 May 2019 20:55:56 -0400 Subject: [PATCH 08/11] Fix chaining in test file --- test/jake/jakelib/migrate-test.js | 74 +++++++++++++++---------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/test/jake/jakelib/migrate-test.js b/test/jake/jakelib/migrate-test.js index 5fb852dc53..90cea1085c 100644 --- a/test/jake/jakelib/migrate-test.js +++ b/test/jake/jakelib/migrate-test.js @@ -467,15 +467,15 @@ test('migrate:down undos only the last run migration', (temp) => { --connection=${temp}/db \ --migrations-directory=${temp}/migrations`, 'run_all_migrations' - ).then(() => { - return assertExec( - `node ${KNEX} migrate:down \ + ) + .then(() => { + return assertExec( + `node ${KNEX} migrate:down \ --client=sqlite3 \ --connection=${temp}/db \ --migrations-directory=${temp}/migrations`, - 'undo_migration_002' - ) - .then(({ stdout }) => { + 'undo_migration_002' + ).then(({ stdout }) => { assert.include( stdout, `Batch 1 rolled back the following migrations:\n${migrationFile2}` @@ -504,43 +504,43 @@ test('migrate:down undos only the last run migration', (temp) => { err ? reject(err) : resolve(); }); }); - }) - .then(() => { - return assertExec( - `node ${KNEX} migrate:down \ - --client=sqlite3 \ - --connection=${temp}/db \ - --migrations-directory=${temp}/migrations`, - 'undo_migration_002' - ).then(({ stdout }) => { - assert.include( - stdout, - `Batch 1 rolled back the following migrations:\n${migrationFile1}` - ); + }); + }) + .then(() => { + return assertExec( + `node ${KNEX} migrate:down \ + --client=sqlite3 \ + --connection=${temp}/db \ + --migrations-directory=${temp}/migrations`, + 'undo_migration_002' + ).then(({ stdout }) => { + assert.include( + stdout, + `Batch 1 rolled back the following migrations:\n${migrationFile1}` + ); - const db = new sqlite3.Database(`${temp}/db`); + const db = new sqlite3.Database(`${temp}/db`); - return new Promise((resolve, reject) => { - db.all('SELECT * FROM knex_migrations', (err, rows) => { - assert.isEmpty(rows); + return new Promise((resolve, reject) => { + db.all('SELECT * FROM knex_migrations', (err, rows) => { + assert.isEmpty(rows); - err ? reject(err) : resolve(); - }); + err ? reject(err) : resolve(); }); }); - }) - .then(() => { - return assertExec( - `node ${KNEX} migrate:down \ - --client=sqlite3 \ - --connection=${temp}/db \ - --migrations-directory=${temp}/migrations`, - 'undo_migration_002' - ).then(({ stdout }) => { - assert.include(stdout, 'Already at the base migration'); - }); }); - }); + }) + .then(() => { + return assertExec( + `node ${KNEX} migrate:down \ + --client=sqlite3 \ + --connection=${temp}/db \ + --migrations-directory=${temp}/migrations`, + 'undo_migration_002' + ).then(({ stdout }) => { + assert.include(stdout, 'Already at the base migration'); + }); + }); }); module.exports = { From aee47603b7e8d588f0e7c4375387b5ee356f2737 Mon Sep 17 00:00:00 2001 From: Lee Allen Date: Tue, 28 May 2019 21:02:18 -0400 Subject: [PATCH 09/11] Remove dupicate migrate:up --- bin/cli.js | 22 ---------- src/migrate/Migrator.js | 37 ----------------- test/integration/migrate/index.js | 68 ------------------------------- 3 files changed, 127 deletions(-) diff --git a/bin/cli.js b/bin/cli.js index 23c6c6df1f..b1b7e187b1 100755 --- a/bin/cli.js +++ b/bin/cli.js @@ -230,28 +230,6 @@ function invoke(env) { .catch(exit); }); - commander - .command('migrate:up') - .description(' Run the next migration that has not yet been run.') - .action(() => { - pending = initKnex(env, commander.opts()) - .migrate.up() - .spread((batchNo, log) => { - if (log.length === 0) { - success(color.cyan('Already up to date')); - } - - success( - color.green( - `Batch ${batchNo} ran the following migrations:\n${log.join( - '\n' - )}` - ) - ); - }) - .catch(exit); - }); - commander .command('migrate:rollback') .description(' Rollback the last batch of migrations performed.') diff --git a/src/migrate/Migrator.js b/src/migrate/Migrator.js index 997ad5bc4f..4848434288 100644 --- a/src/migrate/Migrator.js +++ b/src/migrate/Migrator.js @@ -141,43 +141,6 @@ export default class Migrator { }); } - // Runs the next migration that has not yet been run - up(config) { - this._disableProcessing(); - this.config = getMergedConfig(config, this.config); - - return migrationListResolver - .listAllAndCompleted(this.config, this.knex) - .tap((value) => validateMigrationList(this.config.migrationSource, value)) - .spread((all, completed) => { - const migrationToRun = getNewMigrations( - this.config.migrationSource, - all, - completed - ).slice(0, 1); - - const transactionForAll = - !this.config.disableTransactions && - isEmpty( - filter(migrationToRun, (migration) => { - const migrationContents = this.config.migrationSource.getMigration( - migration - ); - - return !this._useTransaction(migrationContents); - }) - ); - - if (transactionForAll) { - return this.knex.transaction((trx) => { - return this._runBatch(migrationToRun, 'up', trx); - }); - } else { - return this._runBatch(migrationToRun, 'up'); - } - }); - } - // Rollback the last "batch", or all, of migrations that were run. rollback(config, all = false) { this._disableProcessing(); diff --git a/test/integration/migrate/index.js b/test/integration/migrate/index.js index db7831e952..2aaa28074e 100644 --- a/test/integration/migrate/index.js +++ b/test/integration/migrate/index.js @@ -582,74 +582,6 @@ module.exports = function(knex) { }); }); - describe('knex.migrate.up', () => { - afterEach(() => { - return knex.migrate.rollback( - { directory: 'test/integration/migrate/test' }, - true - ); - }); - - it('should only run the first migration if no migrations have run', function() { - return knex.migrate - .up({ - directory: 'test/integration/migrate/test', - }) - .then(() => { - return knex('knex_migrations') - .select('*') - .then(function(data) { - expect(data).to.have.length(1); - expect(path.basename(data[0].name)).to.equal( - '20131019235242_migration_1.js' - ); - }); - }); - }); - - it('should only run the next migration that has not yet run if other migrations have already run', function() { - return knex.migrate - .up({ - directory: 'test/integration/migrate/test', - }) - .then(() => { - return knex.migrate - .up({ - directory: 'test/integration/migrate/test', - }) - .then(() => { - return knex('knex_migrations') - .select('*') - .then(function(data) { - expect(data).to.have.length(2); - expect(path.basename(data[0].name)).to.equal( - '20131019235242_migration_1.js' - ); - expect(path.basename(data[1].name)).to.equal( - '20131019235306_migration_2.js' - ); - }); - }); - }); - }); - - it('should not error if all migrations have already been run', function() { - return knex.migrate - .latest({ - directory: 'test/integration/migrate/test', - }) - .then(() => { - return knex.migrate - .up({ - directory: 'test/integration/migrate/test', - }) - .then((data) => { - expect(data).to.be.an('array'); - }); - }); - }); - }); - after(function() { rimraf.sync(path.join(__dirname, './migration')); }); From aafdd10f295a8d91c13bc13278cbe58686da5ba6 Mon Sep 17 00:00:00 2001 From: Lee Allen Date: Tue, 28 May 2019 21:02:45 -0400 Subject: [PATCH 10/11] Fix wording of assert exec --- test/jake/jakelib/migrate-test.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/jake/jakelib/migrate-test.js b/test/jake/jakelib/migrate-test.js index 90cea1085c..535d739b58 100644 --- a/test/jake/jakelib/migrate-test.js +++ b/test/jake/jakelib/migrate-test.js @@ -380,7 +380,7 @@ test('migrate:up runs only the next unrun migration', (temp) => { --client=sqlite3 \ --connection=${temp}/db \ --migrations-directory=${temp}/migrations`, - 'create_books_table' + 'update_books_table' ).then(({ stdout }) => { assert.include( stdout, @@ -512,7 +512,7 @@ test('migrate:down undos only the last run migration', (temp) => { --client=sqlite3 \ --connection=${temp}/db \ --migrations-directory=${temp}/migrations`, - 'undo_migration_002' + 'undo_migration_001' ).then(({ stdout }) => { assert.include( stdout, @@ -536,7 +536,7 @@ test('migrate:down undos only the last run migration', (temp) => { --client=sqlite3 \ --connection=${temp}/db \ --migrations-directory=${temp}/migrations`, - 'undo_migration_002' + 'already_at_the_base_migration' ).then(({ stdout }) => { assert.include(stdout, 'Already at the base migration'); }); From 6d7ec60537b3b33f2133e65d87c2b47781c9a921 Mon Sep 17 00:00:00 2001 From: Lee Allen Date: Tue, 28 May 2019 21:16:52 -0400 Subject: [PATCH 11/11] Add migrator test for migrate:down --- test/integration/migrate/index.js | 66 +++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/test/integration/migrate/index.js b/test/integration/migrate/index.js index 2aaa28074e..6dc373955c 100644 --- a/test/integration/migrate/index.js +++ b/test/integration/migrate/index.js @@ -582,6 +582,72 @@ module.exports = function(knex) { }); }); + describe('knex.migrate.down', () => { + beforeEach(() => { + return knex.migrate.latest({ + directory: ['test/integration/migrate/test'], + }); + }); + + afterEach(() => { + return knex.migrate.rollback( + { directory: ['test/integration/migrate/test'] }, + true + ); + }); + + it('should only undo the last migration that was run if all migrations have run', function() { + return knex.migrate + .down({ + directory: ['test/integration/migrate/test'], + }) + .then(() => { + return knex('knex_migrations') + .select('*') + .then((data) => { + expect(data).to.have.length(1); + expect(path.basename(data[0].name)).to.equal( + '20131019235242_migration_1.js' + ); + }); + }); + }); + + it('should only undo the last migration that was run if there are other migrations that have not yet run', function() { + return knex.migrate + .down({ + directory: ['test/integration/migrate/test'], + }) + .then(() => { + return knex.migrate + .down({ + directory: ['test/integration/migrate/test'], + }) + .then(() => { + return knex('knex_migrations') + .select('*') + .then((data) => { + expect(data).to.have.length(0); + }); + }); + }); + }); + + it('should not error if all migrations have already been undone', function() { + return knex.migrate + .rollback({ directory: ['test/integration/migrate/test'] }, true) + .then(() => { + return knex.migrate + .down({ + directory: ['test/integration/migrate/test'], + }) + .then((data) => { + expect(data).to.be.an('array'); + }); + }); + }); + }); + after(function() { rimraf.sync(path.join(__dirname, './migration')); });