Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: first stab at integration test towards contentful #329

Draft
wants to merge 10 commits into
base: main
Choose a base branch
from
11 changes: 6 additions & 5 deletions .github/workflows/run-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ jobs:
test:
runs-on: ubuntu-latest

env:
MIGRATIONS_DIR: __test-migrations__
CTF_SPACE_ID: ${{ secrets.CTF_SPACE_ID }}
CTF_ENVIRONMENT_ID: ${{ secrets.CTF_ENVIRONMENT_ID }}
CTF_CMA_TOKEN: ${{ secrets.CTF_CMA_TOKEN }}

steps:
- name: Check out code
uses: actions/checkout@v2
Expand All @@ -25,8 +31,3 @@ jobs:

- name: Run tests
run: npm test
env:
MIGRATIONS_DIR: __test-migrations__
CTF_SPACE_ID: TEST_SPACE_ID
CTF_ENVIRONMENT_ID: master
CTF_CMA_TOKEN: dummy_token
4 changes: 2 additions & 2 deletions __test-utils__/create-migration.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ const fs = require('fs')
module.exports.createSimpleMigrationFile = () => {
const content = `
module.exports.up = (migration, context) => {
const populationCategories = migration
const testContentType = migration
.createContentType('testContentType')
.name('Test content type')
.description('')
.displayField('testContentId')

populationCategories
testContentType
.createField('testContentId')
.name('test content id')
.type('Symbol')
Expand Down
10 changes: 0 additions & 10 deletions __test-utils__/log.js

This file was deleted.

7 changes: 3 additions & 4 deletions __tests__/generate.test.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
const fs = require('fs')
const { join } = require('path')
const { handler: generateCommand } = require('../bin/commands/generate')
const { extractLogLinesFromConsole } = require('../__test-utils__/log')

describe('generate', () => {
it('should create a new migration file', async () => {
const stdout = extractLogLinesFromConsole()
//const stdout = extractLogLinesFromConsole()
const migrationName = 'test-migration'
await generateCommand({ name: migrationName })
let result = await generateCommand({ name: migrationName })

let numberOfMigrationsInMigrationsDir = fs.readdirSync(process.env.MIGRATIONS_DIR).length
expect(numberOfMigrationsInMigrationsDir).toBe(1)

const migrationFileName = stdout[0].split(' ').find((m) => m.indexOf('js') > -1)
const migrationFileName = result.split(' ').find((m) => m.indexOf('js') > -1)
const migrationFilePath = `${process.env.MIGRATIONS_DIR}/${migrationFileName}`
const migrationFile = fs.readFileSync(migrationFilePath, 'utf-8')
const template = fs.readFileSync(join(__dirname, '..', 'templates', 'migration.mustache'), 'utf8')
Expand Down
24 changes: 24 additions & 0 deletions __tests__/integrations/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Integration tests

These tests are meant to test the integrations to contentful.
The purpose of these tests are to run the code towards a real contentful space.

## Setup

There are two ways to enable integration tests.
The safest option is to create a new contentful space dedicated to running the tests.
The other option is to run the tests against an existing contentful space but with an environment dedicated to running the tests.


1. Create a contentful space
2. Add env variables to `.env.test` file
1. `CONTENTFUL_SPACE_ID` - the id of the contentful space
2. `CTF_ENVIRONMENT_ID` - the environment to run the tests in
3. `CTF_CMA_TOKEN` - the access token for the contentful space

## Usage

1. There are 2 utility functions that needs be used before running the tests.
1. `setupTestContentfulSpace` - creates a contentful space
2. `resetTestContentfulSpace` - deletes a contentful space
2. Run `npm run test:integration` to run the tests -- CHECK THIS
23 changes: 23 additions & 0 deletions __tests__/integrations/migrate.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
const { handler: migrateCommand } = require('../../bin/commands/migrate')
const { handler: rollbackCommand } = require('../../bin/commands/rollback')
const { createSimpleMigrationFile } = require('../../__test-utils__/create-migration')

afterEach(async () => {
//unapply the migration done by the tests
await rollbackCommand({ force: true })
})

describe('migrate', () => {
test('migrate if the force flag is used against master', async () => {
createSimpleMigrationFile()

let result = await migrateCommand({ force: true })

expect(result).toBe('Applied the following migrations:\n 20230609122547608 - new-migration')
}, 100000)

test('log if there are no migrations to apply', async () => {
let result = await migrateCommand({ force: true })
expect(result).toBe('No migrations to apply.')
}, 100000)
})
15 changes: 7 additions & 8 deletions __tests__/list.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
const { setupMockedContentfulApi, closeMockedContentfulApi } = require('../mocks/contentful/baseContentfulHandler')
const { handler: listCommand } = require('../bin/commands/list')
const { extractLogLinesFromConsole } = require('../__test-utils__/log')
const { listOneMigrationAppliedHandler } = require('../mocks/contentful/handlers/list/oneAppliedMigrationsHandler')
const { listNoAppliedMigrationHandler } = require('../mocks/contentful/handlers/list/noAppliedMigrationsHandler')
const { createSimpleMigrationFile } = require('../__test-utils__/create-migration')
Expand All @@ -12,9 +11,8 @@ describe('list', () => {
let numberOfMigrationsInMigrationsDir = readdirSync(process.env.MIGRATIONS_DIR).length
expect(numberOfMigrationsInMigrationsDir).toBe(0)

const stdout = extractLogLinesFromConsole()
await listCommand()
expect(stdout).toContain('Found no applied migrations')
let result = await listCommand()
expect(result).toBe('Found no applied migrations')
closeMockedContentfulApi()
})

Expand All @@ -25,10 +23,11 @@ describe('list', () => {
let numberOfMigrationsInMigrationsDir = readdirSync(process.env.MIGRATIONS_DIR).length
expect(numberOfMigrationsInMigrationsDir).toBe(1)

const stdout = extractLogLinesFromConsole()
await listCommand()
expect(stdout).toContain('Applied migrations:')
expect(stdout).toContain('20230609122547608 - new-migration')
//todo: fix
let result = await listCommand()
expect(result).toBe('Applied migrations:\n 20230609122547608 - new-migration')
/*expect(stdout).toContain('Applied migrations:')
expect(stdout).toContain('20230609122547608 - new-migration')*/
closeMockedContentfulApi()
})
})
6 changes: 2 additions & 4 deletions __tests__/migrate.test.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
const { handler: migrateCommand } = require('../bin/commands/migrate')
const { extractLogLinesFromConsole } = require('../__test-utils__/log')
const { setupMockedContentfulApi, closeMockedContentfulApi } = require('../mocks/contentful/baseContentfulHandler')

describe('migrate', () => {
it('should demand user to use "--force" flag if running against master space', async () => {
setupMockedContentfulApi()
const stdout = extractLogLinesFromConsole()
await migrateCommand(false)
expect(stdout).toContain('Executing migrations against master requires the --force flag.')
let result = await migrateCommand(false)
expect(result).toBe('Executing migrations against master requires the --force flag.')
closeMockedContentfulApi()
})
})
11 changes: 7 additions & 4 deletions __tests__/reset.test.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
const { handler: resetCommand } = require('../bin/commands/reset')
const { extractLogLinesFromConsole } = require('../__test-utils__/log')
const { setupMockedContentfulApi, closeMockedContentfulApi } = require('../mocks/contentful/baseContentfulHandler')
const { listNoAppliedMigrationHandler } = require('../mocks/contentful/handlers/list/noAppliedMigrationsHandler')

describe('reset', () => {
it('should not reset environment if on master', async () => {
const stdout = extractLogLinesFromConsole()
await resetCommand({ force: false })
expect(stdout).toContain(`Can't reset environment if you are on master.`)
setupMockedContentfulApi()

let result = await resetCommand({ force: false })
expect(result).toBe(`Can't reset environment if you are on master.`)
closeMockedContentfulApi()
})
})
12 changes: 7 additions & 5 deletions __tests__/rollback.test.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
const fs = require('fs')
const { join } = require('path')
const { handler: rollbackCommand } = require('../bin/commands/rollback')
const { extractLogLinesFromConsole } = require('../__test-utils__/log')
const { handler: migrateCommand } = require('../bin/commands/migrate')
const { setupMockedContentfulApi, closeMockedContentfulApi } = require('../mocks/contentful/baseContentfulHandler')

describe('rollback', () => {
it('should demand user to use "--force" flag if running against master space', async () => {
const stdout = extractLogLinesFromConsole()
await rollbackCommand({ force: false })
expect(stdout).toContain('Executing migrations against master requires the --force flag.')
setupMockedContentfulApi()

let result = await rollbackCommand({ force: false })
expect(result).toBe('Executing migrations against master requires the --force flag.')

closeMockedContentfulApi()
})
})
4 changes: 3 additions & 1 deletion bin/commands/generate.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ exports.handler = async ({ name }) => {
const migrationPath = join(migrationsDir, migrationFileName)

await writeFileAsync(migrationPath, migrationContents)
log.success(`Migration file ${migrationFileName} created`)
let successString = `Migration file ${migrationFileName} created`
log.success(successString)
return successString
} catch (e) {
log.error('Migration file creation failed.', e)
process.exitCode = 1
Expand Down
13 changes: 6 additions & 7 deletions bin/commands/list.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,13 @@ exports.handler = async () => {
const appliedMigrations = await list(space)
appliedMigrations.sort((a, b) => b.timestamp.localeCompare(a.timestamp))
if (appliedMigrations.length) {
log.info('Applied migrations:')
console.group()
appliedMigrations.forEach((m) => {
log.info(m)
})
console.groupEnd()
let appliedMigrationsString = 'Applied migrations:\n ' + appliedMigrations.join('\n ')
log.info('appliedMigrationsString')
return appliedMigrationsString
} else {
log.info('Found no applied migrations')
let noAppliedMigrationsString = 'Found no applied migrations'
log.info(noAppliedMigrationsString)
return noAppliedMigrationsString
}
} catch (e) {
log.error(e)
Expand Down
8 changes: 5 additions & 3 deletions bin/commands/migrate.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,15 @@ exports.builder = (yargs) => {
exports.handler = async ({ force }) => {
try {
if (env('CTF_ENVIRONMENT_ID') === 'master' && !force) {
log.error('Executing migrations against master requires the --force flag.')
return
let errorString = 'Executing migrations against master requires the --force flag.'
log.error(errorString)
return errorString
}

await apply({ rollback: false })
return await apply({ rollback: false })
} catch (e) {
log.error(e)
process.exitCode = 1
return e.toString()
}
}
5 changes: 3 additions & 2 deletions bin/commands/reset.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ exports.desc = 'Resets current CTF_ENVIRONMENT_ID to master.'
exports.handler = async () => {
try {
if (env('CTF_ENVIRONMENT_ID') === 'master') {
log.error(`Can't reset environment if you are on master.`)
return
let errorString = `Can't reset environment if you are on master.`
log.error(errorString)
return errorString
}

const space = await spaceModule(env('CTF_SPACE_ID'), env('CTF_ENVIRONMENT_ID'), env('CTF_CMA_TOKEN'))
Expand Down
6 changes: 4 additions & 2 deletions bin/commands/rollback.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const env = require('../../lib/env')
const cliSelect = require('cli-select')
const spaceModule = require('../../lib/contentful-space-manager')
const log = require('../../lib/log')
const { error } = require('../../lib/log')

exports.command = 'rollback'

Expand All @@ -28,8 +29,9 @@ exports.builder = (yargs) => {
exports.handler = async ({ force, interactive }) => {
try {
if (env('CTF_ENVIRONMENT_ID') === 'master' && !force) {
log.error('Executing migrations against master requires the --force flag.')
return
let errorString = 'Executing migrations against master requires the --force flag.'
log.error(errorString)
return errorString
}

if (interactive) {
Expand Down
12 changes: 0 additions & 12 deletions jest.setupFiles.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,2 @@
const dotenv = require('dotenv')
dotenv.config({ path: './.env.test' })

//mock lib/log since encoding characters from chalk makes testing difficult
jest.mock('./lib/log', () => {
console.log('Setting up mocked log')
return {
_esModule: false,
info: (...message) => console.log(...message),
success: (...message) => console.log(...message),
error: (...message) => console.log(...message),
warn: (...message) => console.log(...message),
}
})
4 changes: 4 additions & 0 deletions mocks/contentful/baseContentfulHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ let mockedContentfulServer = null
module.exports.baseURL = 'https://api.contentful.com/spaces/TEST_SPACE_ID'

module.exports.setupMockedContentfulApi = (handlers) => {
//set up environment variables to match mocked responses from contentful
process.env['CTF_SPACE_ID'] = 'TEST_SPACE_ID'
process.env['CTF_ENVIRONMENT_ID'] = 'master'

if (handlers == null) {
handlers = []
}
Expand Down
24 changes: 18 additions & 6 deletions src/migrator.js
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,15 @@ const migrate = async (space, options = {}) => {
await runMigrations(migrationsToApply, space.env.sys.id)
await updateBookkeeping(space, migrationsToApply, options)
log.info(options.rollback ? 'Rolled back.' : 'Migrated.')

let successString
if (options.rollback) {
successString = 'Successful rollback of the following migrations:\n ' + migrationsToApply.join('\n ')
} else {
successString = 'Applied the following migrations:\n ' + migrationsToApply.join('\n ')
}
log.info(successString)
return successString
}

const delay = (time) => new Promise((resolve) => setTimeout(resolve, time))
Expand Down Expand Up @@ -185,8 +194,9 @@ const apply = async (options = {}) => {
const migrationsToHandle = await getMigrationsToHandle(space, options)

if (!migrationsToHandle.length) {
log.info(`No migrations to ${options.rollback ? 'rollback' : 'apply'}.`)
return
let noMigrationsMessage = `No migrations to ${options.rollback ? 'rollback' : 'apply'}.`
log.info(noMigrationsMessage)
return noMigrationsMessage
}

if (options.rollback) {
Expand All @@ -195,22 +205,24 @@ const apply = async (options = {}) => {
log.info('About to apply the following migrations:\n ' + migrationsToHandle.join('\n '))
}

//todo: depending on env the way to migrate differ?
if (env('CTF_ENVIRONMENT_ID') === 'master') {
const newEnvId = utcTimestamp({ dashes: true })

let result
try {
await failIfNoAvailableEnvironments(space)
const spaceNewEnv = await createEnv(space, newEnvId)
await migrate(spaceNewEnv, options)
result = await migrate(spaceNewEnv, options)

await switchEnvAliasAndDropOldEnv(space, newEnvId)
return
return result
} catch (e) {
await space.deleteSpaceEnv(newEnvId)
throw e
}
}

await migrate(space, options)
return await migrate(space, options)
}

const create = async ({ newEnvId }) => {
Expand Down