Skip to content

Commit

Permalink
Add unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
qtomlinson committed Nov 29, 2024
1 parent 27443a7 commit 4c00f7b
Show file tree
Hide file tree
Showing 5 changed files with 214 additions and 21 deletions.
4 changes: 2 additions & 2 deletions providers/upgrade/defUpgradeQueue.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ class DefinitionQueueUpgrader extends DefinitionVersionChecker {
return this._upgrade.initialize()
}

setupProcessing(definitionService, logger) {
return setup(this._upgrade, definitionService, logger)
setupProcessing(definitionService, logger, once) {
return setup(this._upgrade, definitionService, logger, once)
}
}

Expand Down
2 changes: 1 addition & 1 deletion providers/upgrade/process.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class DefinitionUpgrader {
let queueHandler
let defUpgrader

function setup(_queue, _definitionService, _logger, _defVersionChecker = factory(), once = false) {
function setup(_queue, _definitionService, _logger, once = false, _defVersionChecker = factory()) {
defUpgrader = new DefinitionUpgrader(_definitionService, _logger, _defVersionChecker)
queueHandler = new QueueHandler(_queue, _logger, defUpgrader)
return queueHandler.work(once)
Expand Down
86 changes: 86 additions & 0 deletions test/providers/upgrade/defUpgradeQueue.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// (c) Copyright 2024, SAP SE and ClearlyDefined contributors. Licensed under the MIT license.
// SPDX-License-Identifier: MIT

const chaiAsPromised = require('chai-as-promised')
const chai = require('chai')
chai.use(chaiAsPromised)
const { expect } = require('chai')
const sinon = require('sinon')
const DefinitionQueueUpgrader = require('../../../providers/upgrade/defUpgradeQueue')

describe('DefinitionQueueUpgrader', () => {
const definition = { coordinates: 'test', _meta: { schemaVersion: '1.0.0' } }
let queue, upgrader

beforeEach(async () => {
const logger = { debug: sinon.stub() }
queue = {
queue: sinon.stub().resolves(),
initialize: sinon.stub().resolves()
}
const queueFactory = sinon.stub().returns(queue)
upgrader = new DefinitionQueueUpgrader({ logger, queue: queueFactory })
})

it('returns an instance of DefinitionQueueUpgrader', () => {
expect(upgrader).to.be.an.instanceOf(DefinitionQueueUpgrader)
})

it('sets and gets current schema version', () => {
upgrader.currentSchema = '1.0.0'
expect(upgrader.currentSchema).to.equal('1.0.0')
})

it('initializes', async () => {
await upgrader.initialize()
expect(queue.initialize.calledOnce).to.be.true
})

it('connects to queue after setupProcessing', async () => {
await upgrader.initialize()
const definitionService = { currentSchema: '1.0.0' }
const logger = { debug: sinon.stub() }
queue.dequeueMultiple = sinon.stub().resolves([])
upgrader.setupProcessing(definitionService, logger, true)
expect(queue.dequeueMultiple.calledOnce).to.be.true
})

context('validate', () => {
it('fails if current schema version is not set', async () => {
await expect(upgrader.validate(definition)).to.be.rejectedWith(Error)
})

it('fails if it is not initialized', async () => {
upgrader.currentSchema = '1.0.0'
const stale = { coordinates: 'test', _meta: { schemaVersion: '0.0.1' } }
await expect(upgrader.validate(stale)).to.be.rejectedWith(Error)
})
})

context('validate after set up', () => {
beforeEach(async () => {
await upgrader.initialize()
upgrader.currentSchema = '1.0.0'
})

it('does not queue null definition', async () => {
const result = await upgrader.validate(null)
expect(result).to.be.not.ok
expect(queue.queue.called).to.be.false
})

it('does not queue an up-to-date definition', async () => {
const definition = { coordinates: 'test', _meta: { schemaVersion: '1.0.0' } }
const result = await upgrader.validate(definition)
expect(result).to.deep.equal(definition)
expect(queue.queue.called).to.be.false
})

it('queues and returns a stale definition', async () => {
const definition = { coordinates: 'test', _meta: { schemaVersion: '0.0.1' } }
const result = await upgrader.validate(definition)
expect(result).to.deep.equal(definition)
expect(queue.queue.calledOnce).to.be.true
})
})
})
76 changes: 76 additions & 0 deletions test/providers/upgrade/defVersionCheck.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// (c) Copyright 2024, SAP SE and ClearlyDefined contributors. Licensed under the MIT license.
// SPDX-License-Identifier: MIT

const chaiAsPromised = require('chai-as-promised')
const chai = require('chai')
chai.use(chaiAsPromised)
const { expect } = require('chai')
const sinon = require('sinon')
const { DefinitionVersionChecker, factory } = require('../../../providers/upgrade/defVersionCheck')

describe('DefinitionVersionChecker', () => {
let logger, checker
beforeEach(() => {
logger = { debug: sinon.stub() }
checker = new DefinitionVersionChecker({ logger })
})

it('returns an instance of DefinitionVersionChecker', () => {
expect(checker).to.be.an.instanceOf(DefinitionVersionChecker)
})

it('creates a new instance of DefinitionVersionChecker using factory', () => {
const checker = factory({ logger: logger })
expect(checker).to.be.an.instanceOf(DefinitionVersionChecker)
})

it('sets and gets current schema version', () => {
checker.currentSchema = '1.0.0'
expect(checker.currentSchema).to.equal('1.0.0')
})

it('initializes and returns undefined', async () => {
const result = await checker.initialize()
expect(result).to.be.not.ok
})

it('returns after setupProcessing', async () => {
const result = checker.setupProcessing()
expect(result).to.be.not.ok
})

it('throws an error in validate if current schema version is not set', async () => {
const definition = { _meta: { schemaVersion: '1.0.0' } }
await expect(checker.validate(definition)).to.be.rejectedWith(Error)
})

context('validate after current schema version is set', () => {
beforeEach(() => {
checker.currentSchema = '1.0.0'
})

it('returns the definition if it is up-to-date', async () => {
const definition = { _meta: { schemaVersion: '1.0.0' } }
const result = await checker.validate(definition)
expect(result).to.deep.equal(definition)
})

it('returns undefined for a stale definition', async () => {
const definition = { _meta: { schemaVersion: '0.1.0' } }
const result = await checker.validate(definition)
expect(result).to.be.undefined
})

it('returns undefined for a definition without schema version', async () => {
const definition = {}
const result = await checker.validate(definition)
expect(result).to.be.undefined
})

it('handles null', async () => {
checker.currentSchema = '1.0.0'
const result = await checker.validate(null)
expect(result).to.be.not.ok
})
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,20 @@ const sinon = require('sinon')
const { QueueHandler, DefinitionUpgrader } = require('../../../providers/upgrade/process')

describe('Definition Upgrade Queue Processing', () => {
let logger

beforeEach(() => {
logger = {
info: sinon.stub(),
error: sinon.stub(),
debug: sinon.stub()
}
})

describe('QueueHandler', () => {
let logger, queue, messageHandler, handler
let queue, messageHandler, handler

beforeEach(() => {
logger = {
info: sinon.stub(),
error: sinon.stub()
}
queue = {
dequeueMultiple: sinon.stub(),
delete: sinon.stub().resolves()
Expand All @@ -23,35 +30,45 @@ describe('Definition Upgrade Queue Processing', () => {
handler = new QueueHandler(queue, logger, messageHandler)
})

it('should return an instance of QueueHandler', () => {
it('returns an instance of QueueHandler', () => {
expect(handler).to.be.an.instanceOf(QueueHandler)
})

it('should work on a queue', () => {
it('works on a queue', () => {
queue.dequeueMultiple.resolves([])
handler.work(true)
expect(queue.dequeueMultiple.calledOnce).to.be.true
expect(messageHandler.processMessage.notCalled).to.be.true
expect(queue.delete.notCalled).to.be.true
})

it('should process one message', async () => {
it('processes one message', async () => {
queue.dequeueMultiple.resolves([{ message: 'test' }])
await handler.work(true)
expect(queue.dequeueMultiple.calledOnce).to.be.true
expect(messageHandler.processMessage.calledOnce).to.be.true
expect(queue.delete.calledOnce).to.be.true
})

it('should process multiple messages', async () => {
it('processes multiple messages', async () => {
queue.dequeueMultiple.resolves([{ message: 'testA' }, { message: 'testB' }])
await handler.work(true)
expect(queue.dequeueMultiple.calledOnce).to.be.true
expect(messageHandler.processMessage.calledTwice).to.be.true
expect(queue.delete.calledTwice).to.be.true
})

it('should log error and not delete the message', async () => {
it('handles if error is thrown', async () => {
queue.dequeueMultiple.resolves([{ message: 'testA' }])
messageHandler.processMessage = sinon.stub().throws()
await handler.work(true)
expect(queue.dequeueMultiple.calledOnce).to.be.true
expect(messageHandler.processMessage.calledOnce).to.be.true
expect(queue.delete.called).to.be.false
expect(logger.error.calledOnce).to.be.true
})

it('handles both sucessful and unsucessful messages', async () => {
queue.dequeueMultiple.resolves([{ message: 'testA' }, { message: 'testB' }])
messageHandler.processMessage = sinon.stub().onFirstCall().throws().onSecondCall().resolves()
await handler.work(true)
Expand All @@ -63,13 +80,10 @@ describe('Definition Upgrade Queue Processing', () => {
})

describe('DefinitionUpgrader', () => {
const definition = { coordinates: 'pypi/pypi/-/test/revision' }
let logger, definitionService, versionChecker, upgrader
const definition = Object.freeze({ coordinates: 'pypi/pypi/-/test/revision' })
let definitionService, versionChecker, upgrader

beforeEach(() => {
logger = {
info: sinon.stub(),
debug: sinon.stub()
}
definitionService = {
getStored: sinon.stub(),
computeStoreAndCurate: sinon.stub().resolves()
Expand All @@ -80,7 +94,7 @@ describe('Definition Upgrade Queue Processing', () => {
upgrader = new DefinitionUpgrader(definitionService, logger, versionChecker)
})

it('should recompute a definition', async () => {
it('recomputes a definition, if a definition is not up-to-date', async () => {
definitionService.getStored.resolves(definition)
versionChecker.validate.resolves()

Expand All @@ -90,7 +104,7 @@ describe('Definition Upgrade Queue Processing', () => {
expect(definitionService.computeStoreAndCurate.calledOnce).to.be.true
})

it('should skip compute when a definition is up-to-date', async () => {
it('skips compute if a definition is up-to-date', async () => {
definitionService.getStored.resolves(definition)
versionChecker.validate.resolves(definition)

Expand All @@ -99,5 +113,22 @@ describe('Definition Upgrade Queue Processing', () => {
expect(versionChecker.validate.calledOnce).to.be.true
expect(definitionService.computeStoreAndCurate.notCalled).to.be.true
})

it('computes if a definition does not exist', async () => {
definitionService.getStored.resolves()
versionChecker.validate.resolves()

await upgrader.processMessage({ data: { coordinates: 'pypi/pypi/-/test/revision' } })
expect(definitionService.getStored.calledOnce).to.be.true
expect(versionChecker.validate.calledOnce).to.be.true
expect(definitionService.computeStoreAndCurate.calledOnce).to.be.true
})

it('skips if there is no coordinates', async () => {
await upgrader.processMessage({ data: {} })
expect(definitionService.getStored.notCalled).to.be.true
expect(versionChecker.validate.notCalled).to.be.true
expect(definitionService.computeStoreAndCurate.notCalled).to.be.true
})
})
})

0 comments on commit 4c00f7b

Please sign in to comment.