Select Git revision
-
Rhys Arkins authoredRhys Arkins authored
cache-headers.spec.js 6.81 KiB
'use strict'
const { test, given } = require('sazerac')
const chai = require('chai')
const { expect } = require('chai')
const sinon = require('sinon')
const httpMocks = require('node-mocks-http')
const {
coalesceCacheLength,
setHeadersForCacheLength,
setCacheHeaders,
setCacheHeadersForStaticResource,
serverHasBeenUpSinceResourceCached,
} = require('./cache-headers')
chai.use(require('chai-datetime'))
describe('Cache header functions', function() {
let res
beforeEach(function() {
res = httpMocks.createResponse()
})
describe('coalesceCacheLength', function() {
const cacheHeaderConfig = { defaultCacheLengthSeconds: 777 }
test(coalesceCacheLength, () => {
given({ cacheHeaderConfig, queryParams: {} }).expect(777)
given({
cacheHeaderConfig,
serviceDefaultCacheLengthSeconds: 900,
queryParams: {},
}).expect(900)
given({
cacheHeaderConfig,
serviceDefaultCacheLengthSeconds: 900,
queryParams: { maxAge: 1000 },
}).expect(1000)
given({
cacheHeaderConfig,
serviceDefaultCacheLengthSeconds: 900,
queryParams: { maxAge: 1000, other: 'here', maybe: 'bogus' },
}).expect(1000)
given({
cacheHeaderConfig,
serviceDefaultCacheLengthSeconds: 900,
queryParams: { maxAge: 400 },
}).expect(900)
given({
cacheHeaderConfig,
serviceDefaultCacheLengthSeconds: 900,
queryParams: { maxAge: '-1000' },
}).expect(900)
given({
cacheHeaderConfig,
serviceDefaultCacheLengthSeconds: 900,
queryParams: { maxAge: '' },
}).expect(900)
given({
cacheHeaderConfig,
serviceDefaultCacheLengthSeconds: 900,
queryParams: { maxAge: 'not a number' },
}).expect(900)
given({
cacheHeaderConfig,
serviceDefaultCacheLengthSeconds: 900,
serviceOverrideCacheLengthSeconds: 400,
queryParams: {},
}).expect(900)
given({
cacheHeaderConfig,
serviceOverrideCacheLengthSeconds: 400,
queryParams: {},
}).expect(777)
given({
cacheHeaderConfig,
serviceOverrideCacheLengthSeconds: 900,
queryParams: {},
}).expect(900)
given({
cacheHeaderConfig,
serviceOverrideCacheLengthSeconds: 800,
queryParams: { maxAge: 500 },
}).expect(800)
given({
cacheHeaderConfig,
serviceOverrideCacheLengthSeconds: 900,
queryParams: { maxAge: 800 },
}).expect(900)
})
})
describe('setHeadersForCacheLength', function() {
let sandbox
beforeEach(function() {
sandbox = sinon.createSandbox()
sandbox.useFakeTimers()
})
afterEach(function() {
sandbox.restore()
sandbox = undefined
})
it('should set the correct Date header', function() {
// Confidence check.
expect(res._headers.date).to.equal(undefined)
// Act.
setHeadersForCacheLength(res, 123)
// Assert.
const now = new Date().toGMTString()
expect(res._headers.date).to.equal(now)
})
context('cacheLengthSeconds is zero', function() {
beforeEach(function() {
setHeadersForCacheLength(res, 0)
})
it('should set the expected Cache-Control header', function() {
expect(res._headers['cache-control']).to.equal(
'no-cache, no-store, must-revalidate'
)
})
it('should set the expected Expires header', function() {
expect(res._headers.expires).to.equal(new Date().toGMTString())
})
})
context('cacheLengthSeconds is nonzero', function() {
beforeEach(function() {
setHeadersForCacheLength(res, 123)
})
it('should set the expected Cache-Control header', function() {
expect(res._headers['cache-control']).to.equal('max-age=123')
})
it('should set the expected Expires header', function() {
const expires = new Date(Date.now() + 123 * 1000).toGMTString()
expect(res._headers.expires).to.equal(expires)
})
})
})
describe('setCacheHeaders', function() {
it('sets the expected fields', function() {
const expectedFields = ['date', 'cache-control', 'expires']
expectedFields.forEach(field =>
expect(res._headers[field]).to.equal(undefined)
)
setCacheHeaders({
cacheHeaderConfig: { defaultCacheLengthSeconds: 1234 },
serviceDefaultCacheLengthSeconds: 567,
queryParams: { maxAge: 999999 },
res,
})
expectedFields.forEach(field =>
expect(res._headers[field])
.to.be.a('string')
.and.have.lengthOf.at.least(1)
)
})
})
describe('setCacheHeadersForStaticResource', function() {
beforeEach(function() {
setCacheHeadersForStaticResource(res)
})
it('should set the expected Cache-Control header', function() {
expect(res._headers['cache-control']).to.equal(`max-age=${24 * 3600}`)
})
it('should set the expected Last-Modified header', function() {
const lastModified = res._headers['last-modified']
expect(new Date(lastModified)).to.be.withinTime(
// Within the last 60 seconds.
new Date(Date.now() - 60 * 1000),
new Date()
)
})
})
describe('serverHasBeenUpSinceResourceCached', function() {
// The stringified req's are hard to understand. I thought Sazerac
// provided a way to override the describe message, though I can't find it.
context('when there is no If-Modified-Since header', function() {
it('returns false', function() {
const req = httpMocks.createRequest()
expect(serverHasBeenUpSinceResourceCached(req)).to.equal(false)
})
})
context('when the If-Modified-Since header is invalid', function() {
it('returns false', function() {
const req = httpMocks.createRequest({
headers: { 'If-Modified-Since': 'this-is-not-a-date' },
})
expect(serverHasBeenUpSinceResourceCached(req)).to.equal(false)
})
})
context(
'when the If-Modified-Since header is before the process started',
function() {
it('returns false', function() {
const req = httpMocks.createRequest({
headers: { 'If-Modified-Since': '2018-02-01T05:00:00.000Z' },
})
expect(serverHasBeenUpSinceResourceCached(req)).to.equal(false)
})
}
)
context(
'when the If-Modified-Since header is after the process started',
function() {
it('returns true', function() {
const modifiedTimeStamp = new Date(Date.now() + 1800000)
const req = httpMocks.createRequest({
headers: { 'If-Modified-Since': modifiedTimeStamp.toISOString() },
})
expect(serverHasBeenUpSinceResourceCached(req)).to.equal(true)
})
}
)
})
})