From a1453bf9b710fc9fe92152e763da30bc482bfd8b Mon Sep 17 00:00:00 2001 From: Joshua Willing Date: Thu, 3 Feb 2022 22:13:06 -0800 Subject: [PATCH 1/3] convert long numbers to strings in response --- README.md | 25 ++++---- package-lock.json | 30 +++++++++ package.json | 1 + src/models/agent.model.js | 16 ++++- src/models/client.model.js | 41 +++++++++--- src/utilities/conversion.utilities.js | 13 ++++ src/utilities/filemaker.utilities.js | 11 ++-- test/agent.test.js | 90 ++++++++++++++++++++++++++- test/utilities.test.js | 23 ++++++- 9 files changed, 222 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 3498004..20afa13 100644 --- a/README.md +++ b/README.md @@ -220,18 +220,19 @@ connect('nedb://memory'); After connecting to a datastore you can import and create clients. A client is created using the create method on the Filemaker class. The FileMaker class accepts an object with the following properties: -| Property | Type | Description | -| ------------- | :------------------: | :---------------------------------------------------------------------------------: | -| database | String | The FileMaker database to connect to | -| server | String | The FileMaker server to use as the host. **Note:** Must be an http or https Domain. | -| user | String | The FileMaker user account to be used when authenticating into the Data API | -| password | String | The FileMaker user account's password. | -| [name] | String | A name for the client. | -| [usage] | Boolean | Track Data API usage for this client. **Note:** Default is `true` | -| [timeout] | Number | The default timeout time for requests **Note:** Default is 0, (no timeout) | -| [concurrency] | Number | The number of concurrent requests that will be made to FileMaker | -| [proxy] | Object | settings for a proxy server | -| [agent] | Object | settings for a custom request agent | +| Property | Type | Description | +| ----------------------------- | :------------------: | :---------------------------------------------------------------------------------: | +| database | String | The FileMaker database to connect to | +| server | String | The FileMaker server to use as the host. **Note:** Must be an http or https Domain. | +| user | String | The FileMaker user account to be used when authenticating into the Data API | +| password | String | The FileMaker user account's password. | +| [name] | String | A name for the client. | +| [usage] | Boolean | Track Data API usage for this client. **Note:** Default is `true` | +| [timeout] | Number | The default timeout time for requests **Note:** Default is 0, (no timeout) | +| [concurrency] | Number | The number of concurrent requests that will be made to FileMaker | +| [proxy] | Object | settings for a proxy server | +| [agent] | Object | settings for a custom request agent | +| [convertLongNumbersToStrings] | Boolean | Converts long numbers like Get(UUIDNumber) and Random() to strings in responses | :warning: You should only use the agent parameter when absolutely necessary. The Data API was designed to be used on https. Deviating from the intended use should be done with caution. diff --git a/package-lock.json b/package-lock.json index c4d8f0a..27d02a0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "axios-cookiejar-support": "^1.0.0", "form-data": "^3.0.0", "into-stream": "^5.1.1", + "json-bigint": "^1.0.0", "lodash": "^4.17.15", "marpat": "^3.0.5", "mime-types": "^2.1.26", @@ -1571,6 +1572,14 @@ "tweetnacl": "^0.14.3" } }, + "node_modules/bignumber.js": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.2.tgz", + "integrity": "sha512-GAcQvbpsM0pUb0zw1EI0KhQEZ+lRwR5fYaAp3vPOYuP7aDvGy6cVN6XHLauvF8SOga2y0dcLcjt3iQDTSEliyw==", + "engines": { + "node": "*" + } + }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -5140,6 +5149,14 @@ "node": ">=4" } }, + "node_modules/json-bigint": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", + "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", + "dependencies": { + "bignumber.js": "^9.0.0" + } + }, "node_modules/json-schema": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", @@ -11033,6 +11050,11 @@ "tweetnacl": "^0.14.3" } }, + "bignumber.js": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.2.tgz", + "integrity": "sha512-GAcQvbpsM0pUb0zw1EI0KhQEZ+lRwR5fYaAp3vPOYuP7aDvGy6cVN6XHLauvF8SOga2y0dcLcjt3iQDTSEliyw==" + }, "binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -13734,6 +13756,14 @@ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true }, + "json-bigint": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz", + "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==", + "requires": { + "bignumber.js": "^9.0.0" + } + }, "json-schema": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", diff --git a/package.json b/package.json index bfe779e..fbec5ac 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,7 @@ "axios-cookiejar-support": "^1.0.0", "form-data": "^3.0.0", "into-stream": "^5.1.1", + "json-bigint": "^1.0.0", "lodash": "^4.17.15", "marpat": "^3.0.5", "mime-types": "^2.1.26", diff --git a/src/models/agent.model.js b/src/models/agent.model.js index f69efe4..cdd82f2 100644 --- a/src/models/agent.model.js +++ b/src/models/agent.model.js @@ -11,6 +11,7 @@ const { Connection } = require('./connection.model'); const axios = require('axios'); const axiosCookieJarSupport = require('axios-cookiejar-support').default; const { omit } = require('../utilities'); +const JSONbig = require('json-bigint')({ storeAsString: true }); const instance = axios.create(); @@ -111,6 +112,15 @@ class Agent extends EmbeddedDocument { */ proxy: { type: Object + }, + /** + * return long numbers as strings instead of truncated e notation. + * @member Agent#proxy + * @type Boolean + */ + convertLongNumbersToStrings: { + type: Boolean, + default: () => false } }); } @@ -126,6 +136,8 @@ class Agent extends EmbeddedDocument { preInit({ agent, protocol, timeout, concurrency, connection }) { this.concurrency = concurrency > 0 ? concurrency : 1; + this.convertLongNumbersToStrings = !!this.convertLongNumbersToStrings; + this.connection = Connection.create(connection); if (agent) this.globalize(protocol, agent); } @@ -213,6 +225,8 @@ class Agent extends EmbeddedDocument { const id = uuidv4(); const interceptor = instance.interceptors.request.use( ({ httpAgent, httpsAgent, ...request }) => { + if (this.convertLongNumbersToStrings) + request.transformResponse = data => JSONbig.parse(data); instance.interceptors.request.eject(interceptor); return new Promise((resolve, reject) => this.push({ @@ -384,7 +398,7 @@ class Agent extends EmbeddedDocument { if (token) { this.connection.deactivate(token, id); } - + this.connection.confirm(); if (error.code) { diff --git a/src/models/client.model.js b/src/models/client.model.js index a30df8c..d169f7d 100644 --- a/src/models/client.model.js +++ b/src/models/client.model.js @@ -80,6 +80,7 @@ class Client extends Document { threshold, usage, proxy, + convertLongNumbersToStrings, ...connection } = data; const protocol = data.server.startsWith('https') ? 'https' : 'http'; @@ -91,6 +92,7 @@ class Client extends Document { threshold, concurrency, protocol, + convertLongNumbersToStrings, connection }); } @@ -387,7 +389,9 @@ class Client extends Document { .then(response => response.data) .then(body => this.data.outgoing(body)) .then(body => this._save(body)) - .then(body => parseScriptResult(body)) + .then(body => + parseScriptResult(body, this.agent.convertLongNumbersToStrings) + ) .then(result => resolve(result)) .catch(error => this._save(reject(error))) ); @@ -450,7 +454,9 @@ class Client extends Document { .then(response => response.data) .then(body => this.data.outgoing(body)) .then(body => this._save(body)) - .then(body => parseScriptResult(body)) + .then(body => + parseScriptResult(body, this.agent.convertLongNumbersToStrings) + ) .then(response => resolve(parameters.merge ? Object.assign(data, response) : response) ) @@ -505,7 +511,9 @@ class Client extends Document { .then(response => response.data) .then(body => this.data.outgoing(body)) .then(body => this._save(body)) - .then(body => parseScriptResult(body)) + .then(body => + parseScriptResult(body, this.agent.convertLongNumbersToStrings) + ) .then(body => resolve( parameters.merge @@ -555,7 +563,9 @@ class Client extends Document { .then(response => response.data) .then(body => this.data.outgoing(body)) .then(body => this._save(body)) - .then(body => parseScriptResult(body)) + .then(body => + parseScriptResult(body, this.agent.convertLongNumbersToStrings) + ) .then(result => resolve(result)) .catch(error => this._save(reject(error))) ); @@ -605,7 +615,9 @@ class Client extends Document { .then(response => response.data) .then(body => this.data.outgoing(body)) .then(body => this._save(body)) - .then(body => parseScriptResult(body)) + .then(body => + parseScriptResult(body, this.agent.convertLongNumbersToStrings) + ) .then(result => resolve(result)) .catch(error => this._save(reject(error))) ); @@ -659,7 +671,9 @@ class Client extends Document { .then(response => response.data) .then(body => this.data.outgoing(body)) .then(body => this._save(body)) - .then(body => parseScriptResult(body)) + .then(body => + parseScriptResult(body, this.agent.convertLongNumbersToStrings) + ) .then(result => resolve(result)) .catch(error => this._save(reject(error))) ); @@ -716,7 +730,9 @@ class Client extends Document { .then(response => response.data) .then(body => this.data.outgoing(body)) .then(body => this._save(body)) - .then(body => parseScriptResult(body)) + .then(body => + parseScriptResult(body, this.agent.convertLongNumbersToStrings) + ) .then(result => resolve(result)) .catch(error => { this._save(); @@ -829,7 +845,9 @@ class Client extends Document { .then(response => response.data) .then(body => this.data.outgoing(body)) .then(body => this._save(body)) - .then(body => parseScriptResult(body)) + .then(body => + parseScriptResult(body, this.agent.convertLongNumbersToStrings) + ) .then(response => Object.assign(response, { recordId: resolvedId })) ) .then(response => resolve(response)) @@ -895,7 +913,12 @@ class Client extends Document { .then(response => response.data) .then(body => this.data.outgoing(body)) .then(body => this._save(body)) - .then(body => pick(parseScriptResult(body), 'scriptResult')) + .then(body => + pick( + parseScriptResult(body, this.agent.convertLongNumbersToStrings), + 'scriptResult' + ) + ) .then(result => resolve(result)) .catch(error => this._save(reject(error))) ); diff --git a/src/utilities/conversion.utilities.js b/src/utilities/conversion.utilities.js index e206eb8..8275af8 100644 --- a/src/utilities/conversion.utilities.js +++ b/src/utilities/conversion.utilities.js @@ -1,6 +1,7 @@ 'use strict'; const _ = require('lodash'); +const JSONbig = require('json-bigint')({ storeAsString: true }); /** * @class Conversion Utilities @@ -109,6 +110,17 @@ const omit = (data, properties) => */ const parse = value => (isJSON(value) ? JSON.parse(value) : value); +/** + * @function parseBigInt + * @public + * @memberof Conversion Utilities + * @description The parseBigInt function performs a try catch before attempting to parse the value as JSON. If the value is not valid JSON it wil return the value. Long numbers are returned as strings. + * @see isJSON + * @param {Any} value The value to attempt to parse. + * @return {Object|Any} A JSON object or array of objects without the properties passed to it + */ +const parseBigInt = value => (isJSON(value) ? JSONbig.parse(value) : value); + /** * @function pick * @public @@ -158,5 +170,6 @@ module.exports = { omit, pick, parse, + parseBigInt, deepMapKeys }; diff --git a/src/utilities/filemaker.utilities.js b/src/utilities/filemaker.utilities.js index 26266d3..d138c8a 100644 --- a/src/utilities/filemaker.utilities.js +++ b/src/utilities/filemaker.utilities.js @@ -1,7 +1,7 @@ 'use strict'; const _ = require('lodash'); -const { stringify, parse } = require('./conversion.utilities'); +const { stringify, parse, parseBigInt } = require('./conversion.utilities'); /** @class Filemaker Utilities */ @@ -111,19 +111,22 @@ const sanitizeParameters = (parameters, safeParameters) => ); /** - * @function parseScriptResults + * @function parseScriptResult * @public * @memberof Filemaker Utilities * @description The parseScriptResults function filters the FileMaker DAPI response by testing if a script was triggered * with the request, then either selecting the response, script error, and script result from the * response or selecting just the response. * @param {Object} data The response recieved from the FileMaker DAPI. + * @param {boolean} convertLongNumbersToStrings convert long numbers to strings * @return {Object} A json object containing the selected data from the Data API Response. */ -const parseScriptResult = data => +const parseScriptResult = (data, convertLongNumbersToStrings) => _.mapValues(data.response, (value, property, object) => property.includes('scriptResult') - ? (object[property] = parse(value)) + ? (object[property] = convertLongNumbersToStrings + ? parseBigInt(value) + : parse(value)) : value ); diff --git a/test/agent.test.js b/test/agent.test.js index 18d5454..19ac745 100644 --- a/test/agent.test.js +++ b/test/agent.test.js @@ -73,6 +73,7 @@ describe('Agent Configuration Capabilities', () => { '_schema', 'concurrency', 'connection', + 'convertLongNumbersToStrings', 'queue', 'delay', 'pending', @@ -120,6 +121,7 @@ describe('Agent Configuration Capabilities', () => { 'agent', 'connection', 'concurrency', + 'convertLongNumbersToStrings', 'delay', 'pending', 'queue', @@ -150,6 +152,7 @@ describe('Agent Configuration Capabilities', () => { 'agent', 'concurrency', 'connection', + 'convertLongNumbersToStrings', 'delay', 'global', 'pending', @@ -253,6 +256,7 @@ describe('Agent Configuration Capabilities', () => { 'agent', 'concurrency', 'connection', + 'convertLongNumbersToStrings', 'delay', 'global', 'pending', @@ -268,7 +272,7 @@ describe('Agent Configuration Capabilities', () => { it('should use a proxy if one is set', () => { http - .createServer(function(req, res) { + .createServer(function (req, res) { proxy.web(req, res, { target: process.env.SERVER }); @@ -338,6 +342,7 @@ describe('Agent Configuration Capabilities', () => { '_schema', 'protocol', 'connection', + 'convertLongNumbersToStrings', 'global', 'proxy', 'timeout', @@ -369,6 +374,7 @@ describe('Agent Configuration Capabilities', () => { '_schema', 'protocol', 'connection', + 'convertLongNumbersToStrings', 'global', 'proxy', 'timeout', @@ -403,6 +409,88 @@ describe('Agent Configuration Capabilities', () => { .to.equal('ECONNABORTED'); }); + describe('convertLongNumbersToStrings option', () => { + it('should return strings in fieldData if enabled', () => { + const client = Filemaker.create({ + database: process.env.DATABASE, + server: process.env.SERVER, + user: process.env.USERNAME, + password: process.env.PASSWORD, + usage: true, + convertLongNumbersToStrings: true + }); + return expect( + client + .save() + .then(client => client.list(process.env.LAYOUT, { limit: 1 })) + .then(res => res.data[0].fieldData.uuidNumber) + .catch(error => error) + ).to.eventually.be.a('string'); + }); + + it('should return numbers in fieldData by default', () => { + const client = Filemaker.create({ + database: process.env.DATABASE, + server: process.env.SERVER, + user: process.env.USERNAME, + password: process.env.PASSWORD, + usage: true + }); + return expect( + client + .save() + .then(client => client.list(process.env.LAYOUT, { limit: 1 })) + .then(res => res.data[0].fieldData.uuidNumber) + .catch(error => error) + ).to.eventually.be.a('number'); + }); + + it('should return strings in scriptResult if enabled', () => { + const client = Filemaker.create({ + database: process.env.DATABASE, + server: process.env.SERVER, + user: process.env.USERNAME, + password: process.env.PASSWORD, + usage: true, + convertLongNumbersToStrings: true + }); + return expect( + client + .save() + .then(client => + client.list(process.env.LAYOUT, { + limit: 1, + script: 'Long Number JSON Script' + }) + ) + .then(res => res.scriptResult.longNumber) + .catch(error => error) + ).to.eventually.be.a('string'); + }); + + it('should return numbers in scriptResult by default', () => { + const client = Filemaker.create({ + database: process.env.DATABASE, + server: process.env.SERVER, + user: process.env.USERNAME, + password: process.env.PASSWORD, + usage: true + }); + return expect( + client + .save() + .then(client => + client.list(process.env.LAYOUT, { + limit: 1, + script: 'Long Number JSON Script' + }) + ) + .then(res => res.scriptResult.longNumber) + .catch(error => error) + ).to.eventually.be.a('number'); + }); + }); + it('should not try to resolve pending requests that do not have a resolve function', () => { const client = Filemaker.create({ database: process.env.DATABASE, diff --git a/test/utilities.test.js b/test/utilities.test.js index 093238c..d523e20 100644 --- a/test/utilities.test.js +++ b/test/utilities.test.js @@ -15,7 +15,8 @@ const { pick, omit, parse, - isJSON + isJSON, + parseBigInt } = require('../src/utilities/conversion.utilities'); chai.use(chaiAsPromised); @@ -56,6 +57,26 @@ describe('Conversion Utility Capabilities', () => { .and.to.include.keys('name'); }); }); + describe('ParseBigInt Utility', () => { + it('it should return a string when given a string', () => { + return expect(parseBigInt('A String')).to.be.a('string'); + }); + it('it should return an object when given a stringified object', () => { + return expect(parseBigInt(JSON.stringify({ name: 'Han Solo' }))) + .to.be.a('object') + .and.to.include.keys('name'); + }); + it('it should convert long numbers to strings', () => { + const parsed = parseBigInt('{"longNum": 123456789012345678901234567890}'); + const longNum = parsed.longNum; + return expect(longNum).to.be.a('string'); + }); + it('it should leave short numbers as numbers', () => { + const parsed = parseBigInt('{"shortNum": 123}'); + const shortNum = parsed.shortNum; + return expect(shortNum).to.be.a('number'); + }); + }); describe('isJSON Utility', () => { it('it should return true for an object', () => { return expect(isJSON({ object: true })).to.equal(true); From a9b0265b0e98f1963348e71426b7446b879a2fd6 Mon Sep 17 00:00:00 2001 From: Joshua Willing Date: Fri, 4 Feb 2022 13:59:40 -0800 Subject: [PATCH 2/3] move longNum logic to the existing parse fn --- src/models/agent.model.js | 6 ++-- src/utilities/conversion.utilities.js | 20 ++++-------- src/utilities/filemaker.utilities.js | 6 ++-- test/utilities.test.js | 47 +++++++++++++++------------ 4 files changed, 38 insertions(+), 41 deletions(-) diff --git a/src/models/agent.model.js b/src/models/agent.model.js index cdd82f2..c2304a3 100644 --- a/src/models/agent.model.js +++ b/src/models/agent.model.js @@ -11,7 +11,7 @@ const { Connection } = require('./connection.model'); const axios = require('axios'); const axiosCookieJarSupport = require('axios-cookiejar-support').default; const { omit } = require('../utilities'); -const JSONbig = require('json-bigint')({ storeAsString: true }); +const { parse } = require('../utilities/conversion.utilities'); const instance = axios.create(); @@ -225,8 +225,8 @@ class Agent extends EmbeddedDocument { const id = uuidv4(); const interceptor = instance.interceptors.request.use( ({ httpAgent, httpsAgent, ...request }) => { - if (this.convertLongNumbersToStrings) - request.transformResponse = data => JSONbig.parse(data); + request.transformResponse = data => + parse(data, this.convertLongNumbersToStrings); instance.interceptors.request.eject(interceptor); return new Promise((resolve, reject) => this.push({ diff --git a/src/utilities/conversion.utilities.js b/src/utilities/conversion.utilities.js index 8275af8..62c7f11 100644 --- a/src/utilities/conversion.utilities.js +++ b/src/utilities/conversion.utilities.js @@ -106,20 +106,15 @@ const omit = (data, properties) => * @description The parse function performs a try catch before attempting to parse the value as JSON. If the value is not valid JSON it wil return the value. * @see isJSON * @param {Any} value The value to attempt to parse. + * @param {boolean} [convertLongNumbersToStrings] convert long numbers to strings. * @return {Object|Any} A JSON object or array of objects without the properties passed to it */ -const parse = value => (isJSON(value) ? JSON.parse(value) : value); - -/** - * @function parseBigInt - * @public - * @memberof Conversion Utilities - * @description The parseBigInt function performs a try catch before attempting to parse the value as JSON. If the value is not valid JSON it wil return the value. Long numbers are returned as strings. - * @see isJSON - * @param {Any} value The value to attempt to parse. - * @return {Object|Any} A JSON object or array of objects without the properties passed to it - */ -const parseBigInt = value => (isJSON(value) ? JSONbig.parse(value) : value); +const parse = (value, convertLongNumbersToStrings) => + isJSON(value) + ? convertLongNumbersToStrings + ? JSONbig.parse(value) + : JSON.parse(value) + : value; /** * @function pick @@ -170,6 +165,5 @@ module.exports = { omit, pick, parse, - parseBigInt, deepMapKeys }; diff --git a/src/utilities/filemaker.utilities.js b/src/utilities/filemaker.utilities.js index d138c8a..318f272 100644 --- a/src/utilities/filemaker.utilities.js +++ b/src/utilities/filemaker.utilities.js @@ -1,7 +1,7 @@ 'use strict'; const _ = require('lodash'); -const { stringify, parse, parseBigInt } = require('./conversion.utilities'); +const { stringify, parse } = require('./conversion.utilities'); /** @class Filemaker Utilities */ @@ -124,9 +124,7 @@ const sanitizeParameters = (parameters, safeParameters) => const parseScriptResult = (data, convertLongNumbersToStrings) => _.mapValues(data.response, (value, property, object) => property.includes('scriptResult') - ? (object[property] = convertLongNumbersToStrings - ? parseBigInt(value) - : parse(value)) + ? (object[property] = parse(value, convertLongNumbersToStrings)) : value ); diff --git a/test/utilities.test.js b/test/utilities.test.js index d523e20..eb1727a 100644 --- a/test/utilities.test.js +++ b/test/utilities.test.js @@ -15,8 +15,7 @@ const { pick, omit, parse, - isJSON, - parseBigInt + isJSON } = require('../src/utilities/conversion.utilities'); chai.use(chaiAsPromised); @@ -56,25 +55,31 @@ describe('Conversion Utility Capabilities', () => { .to.be.a('object') .and.to.include.keys('name'); }); - }); - describe('ParseBigInt Utility', () => { - it('it should return a string when given a string', () => { - return expect(parseBigInt('A String')).to.be.a('string'); - }); - it('it should return an object when given a stringified object', () => { - return expect(parseBigInt(JSON.stringify({ name: 'Han Solo' }))) - .to.be.a('object') - .and.to.include.keys('name'); - }); - it('it should convert long numbers to strings', () => { - const parsed = parseBigInt('{"longNum": 123456789012345678901234567890}'); - const longNum = parsed.longNum; - return expect(longNum).to.be.a('string'); - }); - it('it should leave short numbers as numbers', () => { - const parsed = parseBigInt('{"shortNum": 123}'); - const shortNum = parsed.shortNum; - return expect(shortNum).to.be.a('number'); + describe('Long number handling', () => { + const convertLongNums = true; + it('it should return a string when given a string', () => { + return expect(parse('A String', convertLongNums)).to.be.a('string'); + }); + it('it should return an object when given a stringified object', () => { + return expect( + parse(JSON.stringify({ name: 'Han Solo' }), convertLongNums) + ) + .to.be.a('object') + .and.to.include.keys('name'); + }); + it('it should convert long numbers to strings', () => { + const parsed = parse( + '{"longNum": 123456789012345678901234567890}', + convertLongNums + ); + const longNum = parsed.longNum; + return expect(longNum).to.be.a('string'); + }); + it('it should leave short numbers as numbers', () => { + const parsed = parse('{"shortNum": 123}', convertLongNums); + const shortNum = parsed.shortNum; + return expect(shortNum).to.be.a('number'); + }); }); }); describe('isJSON Utility', () => { From 9fbb585cc8ab5385ba74d1019bc1ae2e0d3870e6 Mon Sep 17 00:00:00 2001 From: Joshua Willing Date: Fri, 4 Feb 2022 15:35:35 -0800 Subject: [PATCH 3/3] add tests for negatives and decimals --- test/utilities.test.js | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/test/utilities.test.js b/test/utilities.test.js index eb1727a..428e8c4 100644 --- a/test/utilities.test.js +++ b/test/utilities.test.js @@ -80,6 +80,32 @@ describe('Conversion Utility Capabilities', () => { const shortNum = parsed.shortNum; return expect(shortNum).to.be.a('number'); }); + it('it should work with negative numbers', () => { + const parsed = parse( + '{"longNum": -123456789012345678901234567890}', + convertLongNums + ); + const longNum = parsed.longNum; + return expect(longNum).to.eql('-123456789012345678901234567890'); + }); + it('it should work with short negative numbers', () => { + const parsed = parse('{"longNum": -123}', convertLongNums); + const longNum = parsed.longNum; + return expect(longNum).to.eql(-123); + }); + it('it should work with decimals', () => { + const parsed = parse( + '{"longNum": 1.12345678901234567890123456789}', + convertLongNums + ); + const longNum = parsed.longNum; + return expect(longNum).to.eql('1.12345678901234567890123456789'); + }); + it('it should work with short decimals', () => { + const parsed = parse('{"longNum": 1.123}', convertLongNums); + const longNum = parsed.longNum; + return expect(longNum).to.eql(1.123); + }); }); }); describe('isJSON Utility', () => {