Files
shields/core/token-pooling/token-pool.spec.js
2021-10-05 17:17:26 +01:00

126 lines
3.3 KiB
JavaScript

import { expect } from 'chai'
import sinon from 'sinon'
import times from 'lodash.times'
import { Token, TokenPool } from './token-pool.js'
function expectPoolToBeExhausted(pool) {
expect(() => {
pool.next()
}).to.throw(Error, /^Token pool is exhausted$/)
}
describe('The token pool', function () {
const ids = ['1', '2', '3', '4', '5']
const batchSize = 3
let tokenPool
beforeEach(function () {
tokenPool = new TokenPool({ batchSize })
ids.forEach(id => tokenPool.add(id))
})
it('should yield the expected tokens', function () {
ids.forEach(id =>
times(batchSize, () => expect(tokenPool.next().id).to.equal(id))
)
})
it('should repeat when reaching the end', function () {
ids.forEach(id =>
times(batchSize, () => expect(tokenPool.next().id).to.equal(id))
)
ids.forEach(id =>
times(batchSize, () => expect(tokenPool.next().id).to.equal(id))
)
})
context('tokens are marked exhausted immediately', function () {
it('should be exhausted', function () {
ids.forEach(() => {
const token = tokenPool.next()
token.update(0, Token.nextResetNever)
})
expectPoolToBeExhausted(tokenPool)
})
})
context('tokens are marked after the last request', function () {
it('should be exhausted', function () {
ids.forEach(() => {
const token = times(batchSize, () => tokenPool.next()).pop()
token.update(0, Token.nextResetNever)
})
expectPoolToBeExhausted(tokenPool)
})
})
context('tokens are renewed', function () {
it('should keep using them', function () {
const tokensToRenew = ['2', '4']
const renewalCount = 3
ids.forEach(id => {
const token = times(batchSize, () => tokenPool.next()).pop()
const usesRemaining = tokensToRenew.includes(token.id)
? renewalCount
: 0
token.update(usesRemaining, Token.nextResetNever)
})
tokensToRenew.forEach(id => {
let token
times(renewalCount, () => {
token = tokenPool.next()
expect(token.id).to.equal(id)
}).pop()
token.update(0, Token.nextResetNever)
})
expectPoolToBeExhausted(tokenPool)
})
})
context('tokens reset', function () {
let clock
beforeEach(function () {
clock = sinon.useFakeTimers()
})
afterEach(function () {
clock.restore()
})
it('should start using them', function () {
const tokensToReset = ['2', '4']
const futureTime = 1440
ids.forEach(id => {
const token = times(batchSize, () => tokenPool.next()).pop()
const nextReset = tokensToReset.includes(token.id)
? futureTime
: Token.nextResetNever
token.update(0, nextReset)
})
expectPoolToBeExhausted(tokenPool)
clock.tick(1000 * futureTime)
tokensToReset.forEach(id => {
const token = times(batchSize, () => tokenPool.next()).pop()
token.update(0, Token.nextResetNever)
})
expectPoolToBeExhausted(tokenPool)
})
})
context('when empty', function () {
it('next() should return the expected error', function () {
const tokenPool = new TokenPool()
expect(() => tokenPool.next()).to.throw('Token pool is exhausted')
})
})
})