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: implement more tests #312

Merged
merged 6 commits into from
Jul 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 9 additions & 6 deletions __tests__/generate.test.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
const { execaNode } = require('execa')
const fs = require('fs')
const { join } = require('path')
const { handler: generateCommand } = require('../bin/commands/generate')
const { extractLogLinesFromConsole } = require('../__test-utils__/log')

//todo: rewrite to match refactored other tests?
describe('generate', () => {
it('should create a new migration file', async () => {
const stdout = extractLogLinesFromConsole()
const migrationName = 'test-migration'
const { stdout } = await execaNode('./bin/cmp.js', ['generate', migrationName])
await generateCommand({ name: migrationName })

const migrationFileName = stdout.split(' ').find((m) => m.indexOf('js') > -1)
const migrationFile = fs.readFileSync(`${process.env.MIGRATIONS_DIR}/${migrationFileName}`, 'utf-8')
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 migrationFilePath = `${process.env.MIGRATIONS_DIR}/${migrationFileName}`
const migrationFile = fs.readFileSync(migrationFilePath, 'utf-8')
const template = fs.readFileSync(join(__dirname, '..', 'templates', 'migration.mustache'), 'utf8')

expect(migrationFile).toEqual(template)
})
})
1 change: 0 additions & 1 deletion __tests__/migrate.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
const { execaNode } = require('execa')
const { handler: migrateCommand } = require('../bin/commands/migrate')
const { extractLogLinesFromConsole } = require('../__test-utils__/log')
const { setupMockedContentfulApi, closeMockedContentfulApi } = require('../mocks/contentful/baseContentfulHandler')
Expand Down
10 changes: 10 additions & 0 deletions __tests__/reset.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
const { handler: resetCommand } = require('../bin/commands/reset')
const { extractLogLinesFromConsole } = require('../__test-utils__/log')

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.`)
})
})
13 changes: 13 additions & 0 deletions __tests__/rollback.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
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')

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.')
})
})
25 changes: 16 additions & 9 deletions bin/commands/generate.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#! /usr/bin/env node

const fs = require('fs')
const { join } = require('path')
const Mustache = require('mustache')
Expand All @@ -19,10 +18,9 @@ exports.builder = (yargs) => {
})
}

exports.handler = ({ name }) => {
exports.handler = async ({ name }) => {
try {
const templatePath = fs.readFileSync(join(__dirname, '..', '..', 'templates', 'migration.mustache'), 'utf8')

const migrationContents = Mustache.render(templatePath)
const migrationFileName = `${utcTimestampMs()}-${camelToKebabCase(name)}.js`
const migrationsDir = env('MIGRATIONS_DIR')
Expand All @@ -35,14 +33,23 @@ exports.handler = ({ name }) => {

const migrationPath = join(migrationsDir, migrationFileName)

fs.writeFile(migrationPath, migrationContents, { flag: 'w' }, (err) => {
if (err) {
throw err
}
log.success(`Migration file ${migrationFileName} created`)
})
await writeFileAsync(migrationPath, migrationContents)
log.success(`Migration file ${migrationFileName} created`)
} catch (e) {
log.error('Migration file creation failed.', e)
process.exitCode = 1
}
}

//todo: move to utility if we need this elsewhere
function writeFileAsync(filePath, data) {
return new Promise((resolve, reject) => {
fs.writeFile(filePath, data, (error) => {
if (error) {
reject(error)
} else {
resolve()
}
})
})
}
1 change: 0 additions & 1 deletion jest.setupFiles.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
const dotenv = require('dotenv')
const { setupInterceptorServer } = require('./traffic/interceptor')
dotenv.config({ path: './.env.test' })

//mock lib/log since encoding characters from chalk makes testing difficult
Expand Down
3 changes: 3 additions & 0 deletions mocks/contentful/baseContentfulHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ module.exports.setupMockedContentfulApi = (handlers) => {
if (handlers == null) {
handlers = []
}
let totalNumberOfRequests = 0
log.info('setting up mocked contentful rest server')
const server = setupServer(...spacesHandler, ...localeHandler, ...masterEnvironmentHandler, ...handlers)

Expand All @@ -27,6 +28,8 @@ module.exports.setupMockedContentfulApi = (handlers) => {
server.events.on('request:start', (request, response) => {
// Record every dispatched request.
log.info(`* intercepting ${request.method} request to ${request.url}`)
totalNumberOfRequests++
log.info('Total number of requests: ', totalNumberOfRequests)
})

mockedContentfulServer = server
Expand Down
54 changes: 30 additions & 24 deletions traffic/interceptor.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,39 +9,45 @@ const requests = new Map()
const transactions = new Set()
const server = setupServer()

//this utility can be used to record all network traffic.
// this utility can be used to record all network traffic.
// Each request and response during app lifetime is logged to json in the traffic/output directory.
//run setupInterceptorServer() in bin/cmp.js for this to work.
module.exports.setupInterceptorServer = () => {
// run setupInterceptorServer() in bin/cmp.js for this to work.
module.exports.setupInterceptorServer = ({ logUnhandledRequests, logBypassedTraffic, saveTrafficToFile }) => {
log.info('setting up network traffic interceptor server')

//catch requests from underlying dependencies
server.listen({
onUnhandledRequest(req) {
log.warn(`* Found an unhandled ${req.method} request to ${req.url.href}`)
},
})
if (logUnhandledRequests) {
server.listen({
onUnhandledRequest(req) {
log.warn(`* Found an unhandled ${req.method} request to ${req.url.href}`)
},
})
}

server.events.on('request:start', (request, response) => {
// Record every dispatched request.
log.info(`* intercepting ${request.method} request to ${request.url}`)
requests.set(request.id, request)
transactions.add([request, response])
})
if (logBypassedTraffic) {
server.events.on('request:start', (request, response) => {
// Record every dispatched request.
log.info(`* intercepting ${request.method} request to ${request.url}`)
requests.set(request.id, request)
transactions.add([request, response])
})

// Since we're not providing any request handlers
// to the "setupServer" call, all responses will be
// bypassed (performed as-is). This will allow us to
// collect the actual responses.
server.events.on('response:bypass', (response, requestId) => {
log.info(`* receiving status ${response.status} from ${requests.get(requestId).url}`)
const request = requests.get(requestId)
transactions.add([request, response])
})
// Since we're not providing any request handlers
// to the "setupServer" call, all responses will be
// bypassed (performed as-is). This will allow us to
// collect the actual responses.
server.events.on('response:bypass', (response, requestId) => {
log.info(`* receiving status ${response.status} from ${requests.get(requestId).url}`)
const request = requests.get(requestId)
transactions.add([request, response])
})
}

process.on('exit', () => {
log.info('handling exit')
this.writeTrafficToFile()
if (saveTrafficToFile) {
this.writeTrafficToFile()
}
})
}

Expand Down