db-vendo-client/test/e2e/lib/util.js

128 lines
4.5 KiB
JavaScript
Raw Normal View History

import isRoughlyEqual from 'is-roughly-equal';
import {ok, AssertionError} from 'assert';
import {DateTime} from 'luxon';
import * as a from 'assert';
import {createRequire} from 'module';
// Note: We *must* import tap up here, not just in the if(VCR_MODE) block below, because a) we can only use `require()` conditionally, not `import`; and b) requiring it below makes the teardown script behave differently.
// may be related: https://github.com/tapjs/tapjs/issues/1005
import tap from 'tap';
import {gunzipSync} from 'zlib';
const hour = 60 * 60 * 1000;
const day = 24 * hour;
const week = 7 * day;
2017-12-11 16:33:17 +01:00
// next Monday 10 am
const createWhen = (timezone, locale, tMock) => {
ok(Number.isInteger(tMock), 'tMock must be an integer');
const t = process.env.VCR_MODE && !process.env.VCR_OFF
? tMock
: Date.now();
return DateTime.fromMillis(t, {
zone: timezone,
locale,
})
.startOf('week')
.plus({weeks: 1, hours: 10})
.toJSDate();
};
const assertValidWhen = (actual, expected, name, delta = day + 6 * hour) => {
const ts = Number(new Date(actual));
a.ok(!Number.isNaN(ts), name + ' is not parsable by Date');
// the timestamps might be from long-distance trains
if (!isRoughlyEqual(delta, Number(expected), ts)) {
2020-05-22 16:09:25 +02:00
throw new AssertionError({
message: name + ' is out of range',
actual: ts,
expected: `${expected - delta} - ${Number(expected) + delta}`,
2020-05-22 16:09:25 +02:00
operator: 'isRoughlyEqual',
});
2020-05-22 16:09:25 +02:00
}
};
// HTTP request mocking
if (process.env.VCR_MODE && !process.env.VCR_OFF) {
const require = createRequire(import.meta.url);
const {Polly} = require('@pollyjs/core');
const NodeHttpAdapter = require('@pollyjs/adapter-node-http');
const FSPersister = require('@pollyjs/persister-fs');
// 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);
};
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: {
order: false,
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:22 +02:00
2022-05-07 16:17:37 +02:00
export {
2020-05-21 19:04:22 +02:00
hour, createWhen, assertValidWhen,
};