Skip to content

Commit

Permalink
feat(record): update mode (#2241)
Browse files Browse the repository at this point in the history
  • Loading branch information
rkesters committed Nov 8, 2021
1 parent 63a5482 commit 1cb4880
Show file tree
Hide file tree
Showing 4 changed files with 323 additions and 1 deletion.
2 changes: 2 additions & 0 deletions README.md
Expand Up @@ -1471,6 +1471,8 @@ To set the mode call `nockBack.setMode(mode)` or run the tests with the `NOCK_BA

- record: use recorded nocks, record new nocks

- update: remove recorded nocks, record nocks

- lockdown: use recorded nocks, disables all http calls even when not nocked, doesn't record

## Common issues
Expand Down
56 changes: 56 additions & 0 deletions lib/back.js
Expand Up @@ -175,6 +175,47 @@ const record = {
},
}

const update = {
setup: function () {
recorder.restore()
recorder.clear()
cleanAll()
activate()
disableNetConnect()
},

start: function (fixture, options) {
if (!fs) {
throw new Error('no fs')
}
const context = removeFixture(fixture)
recorder.record({
dont_print: true,
output_objects: true,
...options.recorder,
})

context.isRecording = true

return context
},

finish: function (fixture, options, context) {
let outputs = recorder.outputs()

if (typeof options.afterRecord === 'function') {
outputs = options.afterRecord(outputs)
}

outputs =
typeof outputs === 'string' ? outputs : JSON.stringify(outputs, null, 4)
debug('recorder outputs:', outputs)

fs.mkdirSync(path.dirname(fixture), { recursive: true })
fs.writeFileSync(fixture, outputs)
},
}

const lockdown = {
setup: function () {
recorder.restore()
Expand Down Expand Up @@ -215,6 +256,19 @@ function load(fixture, options) {
return context
}

function removeFixture(fixture, options) {
const context = {
scopes: [],
assertScopesFinished: function () {},
}

if (fixture && fixtureExists(fixture)) {
fs.rmSync ? fs.rmSync(fixture) : fs.unlinkSync(fixture)
}
context.isLoaded = false
return context
}

function applyHook(scopes, fn) {
if (!fn) {
return
Expand Down Expand Up @@ -258,6 +312,8 @@ const Modes = {

record, // use recorded nocks, record new nocks

update, // allow http calls, record all nocks, don't use recorded nocks

lockdown, // use recorded nocks, disables all http calls even when not nocked, doesnt record
}

Expand Down
2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -61,7 +61,7 @@
"lint:js": "eslint --cache --cache-location './.cache/eslint' '**/*.js'",
"lint:js:fix": "eslint --cache --cache-location './.cache/eslint' --fix '**/*.js'",
"lint:ts": "dtslint types",
"test": "nyc mocha tests",
"test": "nyc --reporter=lcov --reporter=text mocha tests",
"test:coverage": "open coverage/lcov-report/index.html"
},
"license": "MIT",
Expand Down
264 changes: 264 additions & 0 deletions tests/test_back.js
Expand Up @@ -482,6 +482,270 @@ describe('Nock Back', () => {
})
})

describe('update mode', () => {
let fixture
let fixtureLoc
let fixturePath

beforeEach(() => {
// random fixture file so tests don't interfere with each other
const token = crypto.randomBytes(4).toString('hex')
fixture = `temp_${token}.json`
fixtureLoc = path.resolve(__dirname, 'fixtures', fixture)
fixturePath = path.resolve(__dirname, 'fixtures')
nockBack.setMode('update')
fs.copyFileSync(
path.resolve(fixturePath, 'wrong_uri.json'),
path.resolve(fixturePath, 'temp_wrong_uri.json')
)
})

after(() => {
rimraf.sync(path.resolve(__dirname, 'fixtures', 'temp_*.json'))
})

it('should record when configured correctly', done => {
expect(fs.existsSync(fixtureLoc)).to.be.false()

nockBack(fixture, nockDone => {
startHttpServer(requestListener).then(server => {
const request = http.request(
{
host: 'localhost',
path: '/',
port: server.address().port,
},
response => {
nockDone()

expect(response.statusCode).to.equal(217)
expect(fs.existsSync(fixtureLoc)).to.be.true()
done()
}
)

request.on('error', () => expect.fail())
request.end()
})
})
})

it('should record the expected data', done => {
nockBack(fixture, nockDone => {
startHttpServer(requestListener).then(server => {
const request = http.request(
{
host: 'localhost',
path: '/',
port: server.address().port,
method: 'GET',
},
response => {
response.once('end', () => {
nockDone()

const fixtureContent = JSON.parse(
fs.readFileSync(fixtureLoc).toString('utf8')
)
expect(fixtureContent).to.have.length(1)

const [firstFixture] = fixtureContent
expect(firstFixture).to.include({
method: 'GET',
path: '/',
status: 217,
})

done()
})

response.resume()
}
)

request.on('error', err => expect.fail(err.message))
request.end()
})
})
})

// Adding this test because there was an issue when not calling
// nock.activate() after calling nock.restore().
it('can record twice', done => {
expect(fs.existsSync(fixtureLoc)).to.be.false()

nockBack(fixture, function (nockDone) {
startHttpServer(requestListener).then(server => {
const request = http.request(
{
host: 'localhost',
path: '/',
port: server.address().port,
},
response => {
nockDone()

expect(response.statusCode).to.equal(217)
expect(fs.existsSync(fixtureLoc)).to.be.true()
done()
}
)

request.on('error', () => expect.fail())
request.end()
})
})
})

it('should allow outside calls', done => {
nockBack('temp_wrong_uri.json', nockDone => {
startHttpServer(requestListener).then(server => {
const request = http.request(
{
host: 'localhost',
path: '/',
port: server.address().port,
},
response => {
nockDone()
expect(response.statusCode).to.equal(217)
expect(
fs.existsSync(`${fixturePath}/temp_wrong_uri.json`)
).to.be.true()
done()
}
)

request.on('error', () => expect.fail())
request.end()
})
})
})

it("shouldn't load recorded tests", done => {
fs.copyFileSync(
path.resolve(fixturePath, 'good_request.json'),
path.resolve(fixturePath, 'temp_good_request.json')
)
nockBack('temp_good_request.json', function (nockDone) {
expect(this.scopes).to.have.lengthOf.at.least(0)
http
.get('http://www.example.test/', () => {
expect.fail()
})
.on('error', () => {
nockDone()
done()
})
})
})

it('should filter after recording', done => {
expect(fs.existsSync(fixtureLoc)).to.be.false()

// You would do some filtering here, but for this test we'll just return
// an empty array.
const afterRecord = () => []

nockBack(fixture, { afterRecord }, function (nockDone) {
startHttpServer(requestListener).then(server => {
const request = http.request(
{
host: 'localhost',
path: '/',
port: server.address().port,
},
response => {
nockDone()

expect(response.statusCode).to.equal(217)
expect(fs.existsSync(fixtureLoc)).to.be.true()
expect(this.scopes).to.be.empty()
done()
}
)
request.on('error', () => expect.fail())
request.end()
})
})
})

it('should format after recording', done => {
expect(fs.existsSync(fixtureLoc)).to.be.false()

const afterRecord = () => 'string-response'

nockBack(fixture, { afterRecord }, function (nockDone) {
startHttpServer(requestListener).then(server => {
const request = http.request(
{
host: 'localhost',
path: '/',
port: server.address().port,
},
response => {
nockDone()

expect(response.statusCode).to.equal(217)
expect(fs.existsSync(fixtureLoc)).to.be.true()
expect(fs.readFileSync(fixtureLoc, 'utf8')).to.equal(
'string-response'
)
done()
}
)
request.on('error', () => expect.fail())
request.end()
})
})
})

it('should pass custom options to recorder', done => {
nockBack(
fixture,
{ recorder: { enable_reqheaders_recording: true } },
nockDone => {
startHttpServer(requestListener).then(server => {
const request = http.request(
{
host: 'localhost',
path: '/',
port: server.address().port,
method: 'GET',
},
response => {
response.once('end', () => {
nockDone()

const fixtureContent = JSON.parse(
fs.readFileSync(fixtureLoc).toString('utf8')
)

expect(fixtureContent).to.have.length(1)
expect(fixtureContent[0].reqheaders).to.be.ok()

done()
})
response.resume()
}
)

request.on('error', () => expect.fail())
request.end()
})
}
)
})

it('should throw the expected exception when fs is not available', () => {
const nockBackWithoutFs = proxyquire('../lib/back', { fs: null })
nockBackWithoutFs.setMode('update')

nockBackWithoutFs.fixtures = path.resolve(__dirname, 'fixtures')
expect(() => nockBackWithoutFs('good_request.json')).to.throw('no fs')
})
})

describe('lockdown mode', () => {
beforeEach(() => {
nockBack.setMode('lockdown')
Expand Down

0 comments on commit 1cb4880

Please sign in to comment.