--- /dev/null
+/* eslint-env mocha */
+/* eslint-disable capitalized-comments */
+'use strict';
+
+const assert = require('assert');
+const sinon = require('sinon'); // eslint-disable-line node/no-unpublished-require
+const MysteryBox = require('../../lib/mystery-box');
+const stubLogger = require('../stub-logger');
+
+describe('MysteryBox', function () {
+ const noExpectedException = 'did not get expected exception';
+ let mb, options, object;
+ beforeEach(function () {
+ options = {
+ encryptionSecret: 'this is not a very good secret',
+ };
+ });
+ afterEach(function () {
+ sinon.restore();
+ });
+
+ describe('constructor', function () {
+ it('needs a secret', async function () {
+ options = {};
+ try {
+ mb = new MysteryBox(stubLogger, options);
+ assert.fail(noExpectedException);
+ } catch (e) {
+ assert.strictEqual(e.message, 'missing encryption secret', noExpectedException);
+ }
+ });
+
+ it('covers options', function () {
+ try {
+ mb = new MysteryBox(stubLogger);
+ assert.fail(noExpectedException);
+ } catch (e) {
+ assert.strictEqual(e.message, 'missing encryption secret', noExpectedException);
+ }
+ });
+
+ it('covers bad flags', function () {
+ options.defaultFlags = 300;
+ try {
+ mb = new MysteryBox(stubLogger, options);
+ assert.fail(noExpectedException);
+ } catch (e) {
+ assert(e instanceof RangeError, noExpectedException);
+ }
+ });
+
+ it('covers missing ciphers', function () {
+ sinon.stub(MysteryBox._test.crypto, 'getCiphers').returns(['rot13']);
+ try {
+ mb = new MysteryBox(stubLogger, options);
+ assert.fail(noExpectedException);
+ } catch (e) {
+ assert.strictEqual(e.message, 'no supported versions available', noExpectedException);
+ }
+ });
+ }); // constructor
+
+ describe('pack, unpack', function () {
+ beforeEach(function () {
+ mb = new MysteryBox(stubLogger, options);
+ });
+
+ it('covers packing unsupported version', async function () {
+ try {
+ await mb.pack({}, 0);
+ assert.fail(noExpectedException);
+ } catch (e) {
+ assert(e instanceof RangeError, noExpectedException);
+ }
+ });
+
+ it('covers unpacking unsupported version', async function () {
+ const badBuffer = Buffer.alloc(128);
+ badBuffer.writeUInt8(0, 0); // No such thing as version 0
+ const badPayload = badBuffer.toString('base64');
+ try {
+ await mb.unpack(badPayload);
+ assert.fail(noExpectedException);
+ } catch (e) {
+ assert(e instanceof RangeError, noExpectedException);
+ }
+ });
+
+ it('encrypts and decrypts default version', async function () {
+ this.slow(500);
+ object = {
+ foo: 'bar',
+ baz: 'quux',
+ flarp: 13,
+ };
+ const encryptedResult = await mb.pack(object);
+ const decryptedResult = await mb.unpack(encryptedResult);
+ assert.deepStrictEqual(decryptedResult, object);
+ });
+
+ it('encrypts and decrypts default version, buffer contents', async function () {
+ this.slow(500);
+ object = Buffer.from('a fine little buffer');
+ const encryptedResult = await mb.pack(object);
+ const decryptedResult = await mb.unpack(encryptedResult);
+ assert.deepStrictEqual(decryptedResult, object);
+ });
+
+ it('encrypts and decrypts all available versions +brotli', async function () {
+ Object.keys(mb.versionParameters).map((v) => Number(v)).forEach(async (version) => {
+ object = {
+ foo: 'bar',
+ baz: 'quux',
+ flarp: 13,
+ };
+ const encryptedResult = await mb.pack(object, version, 0x00);
+ const decryptedResult = await mb.unpack(encryptedResult);
+ assert.deepStrictEqual(decryptedResult, object, `${version} results not symmetric`);
+ });
+ });
+
+ it('encrypts and decrypts all available versions +flate', async function () {
+ Object.keys(mb.versionParameters).map((v) => Number(v)).forEach(async (version) => {
+ object = {
+ foo: 'bar',
+ baz: 'quux',
+ flarp: 13,
+ };
+ const encryptedResult = await mb.pack(object, version, 0x01);
+ const decryptedResult = await mb.unpack(encryptedResult);
+ assert.deepStrictEqual(decryptedResult, object, `${version} results not symmetric`);
+ });
+ });
+
+ it('handles large object +brotli', async function () {
+ this.timeout(5000);
+ this.slow(2000);
+ const firstChar = 32, lastChar = 126;
+ const rnd = () => {
+ return Math.floor(firstChar + (lastChar - firstChar + 1) * Math.random());
+ }
+ object = {
+ longProperty: 'x'.repeat(384 * 1024).split('').map(() => String.fromCharCode(rnd())).join(''),
+ };
+ const encryptedResult = await mb.pack(object, mb.bestVersion, 0x00);
+ const decryptedResult = await mb.unpack(encryptedResult);
+ assert.deepStrictEqual(decryptedResult, object);
+ });
+
+ it('handles large object +flate', async function () {
+ this.timeout(5000);
+ this.slow(2000);
+ const firstChar = 32, lastChar = 126;
+ const rnd = () => {
+ return Math.floor(firstChar + (lastChar - firstChar + 1) * Math.random());
+ }
+ object = {
+ longProperty: 'x'.repeat(384 * 1024).split('').map(() => String.fromCharCode(rnd())).join(''),
+ };
+ const encryptedResult = await mb.pack(object, mb.bestVersion, 0x01);
+ const decryptedResult = await mb.unpack(encryptedResult);
+ assert.deepStrictEqual(decryptedResult, object);
+ });
+ }); // pack, unpack
+
+}); // MysteryBox
\ No newline at end of file