Skip to content

Commit

Permalink
feat: implement more tests (#312)
Browse files Browse the repository at this point in the history
* feat: rewrite generate test

* feat: improvements

* feat: run prettier on all files

* feat: add simple reset test

* feat: fixes
  • Loading branch information
driatic authored Jul 13, 2023
1 parent a791c43 commit feed65a
Show file tree
Hide file tree
Showing 8 changed files with 81 additions and 41 deletions.
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

0 comments on commit feed65a

Please sign in to comment.