2022-05-07 16:17:37 +02:00
import isRoughlyEqual from 'is-roughly-equal'
import { ok , AssertionError } from 'assert'
import { DateTime } from 'luxon'
import * as a from 'assert'
import { createRequire } from 'module'
2022-11-18 13:44:27 +01:00
import { gunzipSync } from 'zlib'
2017-11-12 21:03:24 +01:00
2017-12-11 16:33:17 +01:00
const hour = 60 * 60 * 1000
2018-05-14 00:35:21 +02:00
const day = 24 * hour
const week = 7 * day
2017-11-12 21:03:24 +01:00
2017-12-11 16:33:17 +01:00
// next Monday 10 am
2022-04-23 14:40:51 +02:00
const createWhen = ( timezone , locale , tMock ) => {
ok ( Number . isInteger ( tMock ) , 'tMock must be an integer' )
2020-05-21 22:21:07 +02:00
const t = process . env . VCR _MODE && ! process . env . VCR _OFF
2022-04-23 14:40:51 +02:00
? tMock
2020-05-21 22:21:07 +02:00
: Date . now ( )
return DateTime . fromMillis ( t , {
2017-12-28 22:57:22 +01:00
zone : timezone ,
locale ,
} ) . startOf ( 'week' ) . plus ( { weeks : 1 , hours : 10 } ) . toJSDate ( )
}
2018-04-18 20:08:47 +02:00
2021-12-29 21:11:07 +01:00
const assertValidWhen = ( actual , expected , name , delta = day + 6 * hour ) => {
2017-12-28 22:57:22 +01:00
const ts = + new Date ( actual )
2018-05-14 00:35:21 +02:00
a . ok ( ! Number . isNaN ( ts ) , name + ' is not parsable by Date' )
2018-04-18 20:08:47 +02:00
// the timestamps might be from long-distance trains
2020-05-22 16:09:25 +02:00
if ( ! isRoughlyEqual ( delta , + expected , ts ) ) {
throw new AssertionError ( {
message : name + ' is out of range' ,
actual : ts ,
2022-04-28 22:11:34 +02:00
expected : ` ${ expected - delta } - ${ + expected + delta } ` ,
2020-05-22 16:09:25 +02:00
operator : 'isRoughlyEqual' ,
} )
}
2017-12-11 15:41:27 +01:00
}
2020-05-21 19:04:47 +02:00
// HTTP request mocking
if ( process . env . VCR _MODE && ! process . env . VCR _OFF ) {
2022-05-07 16:17:37 +02:00
const require = createRequire ( import . meta . url )
2022-06-18 16:50:33 +02:00
const { Polly } = require ( '@pollyjs/core' )
const NodeHttpAdapter = require ( '@pollyjs/adapter-node-http' )
const FSPersister = require ( '@pollyjs/persister-fs' )
const tap = require ( 'tap' )
2022-11-18 13:44:27 +01:00
// monkey-patch NodeHttpAdapter to handle gzipped responses properly
// todo: submit a PR
// related: https://github.com/Netflix/pollyjs/issues/256
// related: https://github.com/Netflix/pollyjs/issues/463
// related: https://github.com/Netflix/pollyjs/issues/207
const _getBodyFromChunks = NodeHttpAdapter . prototype . getBodyFromChunks
NodeHttpAdapter . prototype . getBodyFromChunks = function getBodyFromChunksWithGunzip ( chunks , headers ) {
if ( headers [ 'content-encoding' ] === 'gzip' ) {
const concatenated = Buffer . concat ( chunks )
chunks = [ gunzipSync ( concatenated ) ]
// todo: this is ugly, find a better way
delete headers [ 'content-encoding' ]
headers [ 'content-length' ] = chunks [ 0 ] . length
}
return _getBodyFromChunks . call ( this , chunks , headers )
}
2022-06-18 16:50:33 +02:00
Polly . register ( NodeHttpAdapter )
Polly . register ( FSPersister )
let mode
if ( process . env . VCR _MODE === 'record' ) mode = 'record'
else if ( process . env . VCR _MODE === 'playback' ) mode = 'replay'
else throw new Error ( 'invalid $VCR_MODE, must be "record" or "replay"' )
const polly = new Polly ( 'requests' , {
logLevel : 'warn' ,
// If a request's recording is not found, pass-through to the server and record the response.
recordIfMissing : false ,
// If false, Polly will throw when attempting to persist any failed requests. A request is considered to be a failed request when its response's status code is ≥ 400.
recordFailedRequests : true ,
// Await any unresolved requests handled by the polly instance (via flush) when stop is called.
flushRequestsOnStop : true ,
// The Polly mode. Can be one of the following:
// - replay: Replay responses from recordings.
// - record: Force Polly to record all requests. This will overwrite recordings that already exist.
// - passthrough: Passes all requests through directly to the server without recording or replaying.
mode ,
adapters : [ 'node-http' ] ,
persister : 'fs' ,
persisterOptions : {
fs : {
recordingsDir : new URL ( '../fixtures' , import . meta . url ) . pathname ,
} ,
// When disabled, requests that have not been captured by the running Polly instance will be removed from any previous recording. This ensures that a recording will only contain the requests that were made during the lifespan of the Polly instance. When enabled, new requests will be appended to the recording file.
keepUnusedRequests : true , // todo: change to false?
} ,
matchRequestsBy : {
2022-11-09 23:53:50 +01:00
order : false ,
2022-06-18 16:50:33 +02:00
headers : {
// todo: use an allow-list here?
exclude : [
// request
'user-agent' , // randomised
'connection' , // not relevant for tests
// response
'set-cookie' , // often randomised
'date' , // constantly changing
] ,
} ,
} ,
} )
tap . teardown ( async ( ) => {
await polly . stop ( )
2020-05-21 19:04:47 +02:00
} )
}
2020-05-21 19:04:22 +02:00
2022-05-07 16:17:37 +02:00
export {
2020-05-21 19:04:22 +02:00
hour , createWhen , assertValidWhen ,
2017-11-12 21:03:24 +01:00
}