From e7b07ff91a035c7235c7b6bb77335e638d28ce55 Mon Sep 17 00:00:00 2001 From: Diego Pamio Date: Mon, 26 Oct 2020 18:22:05 -0300 Subject: [PATCH 1/2] feat: add simplest scoring calculation --- .../fixtures/acceptance/BreweriesSample1.json | 61 ++++++++++ .../fixtures/acceptance/BreweriesSample2.json | 61 ++++++++++ .../fixtures/acceptance/BreweriesSample3.json | 85 ++++++++++++++ .../fixtures/acceptance/BreweriesSample4.json | 51 +++++++++ .../fixtures/acceptance/BreweriesSample5.json | 69 ++++++++++++ cypress/integration/app.spec.js | 16 ++- cypress/support/commands.js | 6 +- jsconfig.json | 9 ++ package-lock.json | 71 +++++++----- package.json | 1 + pages/api/score.js | 4 +- pages/index.js | 15 ++- .../__tests__/calculateScore.unit.test.js | 104 ++++++++++++++++++ utils/score/calculateScore.js | 69 ++++++++++++ utils/score/index.js | 1 + 15 files changed, 586 insertions(+), 37 deletions(-) create mode 100644 cypress/fixtures/acceptance/BreweriesSample1.json create mode 100644 cypress/fixtures/acceptance/BreweriesSample2.json create mode 100644 cypress/fixtures/acceptance/BreweriesSample3.json create mode 100644 cypress/fixtures/acceptance/BreweriesSample4.json create mode 100644 cypress/fixtures/acceptance/BreweriesSample5.json create mode 100644 jsconfig.json create mode 100644 utils/score/__tests__/calculateScore.unit.test.js create mode 100644 utils/score/calculateScore.js create mode 100644 utils/score/index.js diff --git a/cypress/fixtures/acceptance/BreweriesSample1.json b/cypress/fixtures/acceptance/BreweriesSample1.json new file mode 100644 index 0000000..8baee4b --- /dev/null +++ b/cypress/fixtures/acceptance/BreweriesSample1.json @@ -0,0 +1,61 @@ +{ +"state-fish": "Cutthroat Trout", +"state-bird": "Western Meadowloark", +"breweries": [ +{ +"name": "Madison River Brewing", +"location": { +"address": "20900 Frontage Rd Building B", +"state": "MT", +"city": "Belgrade", +"zip-code": "59714" +}, +"food-available": false, +"beers": [ +{ +"name": "Salmon Fly Honey Rye", +"color": "Gold", +"international-bitterness-units": 12, +"alcohol-by-volume": 0.04 +}, +{ +"name": "Copper John Scotch Ale", +"color": "Copper", +"international-bitterness-units": 35, +"alcohol-by-volume": 0.055 +}, +{ +"name": "Dropper IPA", +"color": "Amber", +"international-bitterness-units": 108, +"alcohol-by-volume": 0.065 +} +] +}, +{ +"name": "Bozeman Brewing", +"location": { +"city": "Bozeman", +"address": "504 N. Broadway", +"state": "MT", +"zip-code": "59715" +}, +"food-available": true, +"beers": [ +{ +"name": "Bozone Amber Ale", +"color": "Amber", +"international-bitterness-units": 29, +"alcohol-by-volume": 0.054 +}, +{ +"name": "Plum Street Porter", +"international-bitterness-units": 52, +"color": "Dark", +"alcohol-by-volume": 0.06 +} +] +} +], +"state": "MT" +} diff --git a/cypress/fixtures/acceptance/BreweriesSample2.json b/cypress/fixtures/acceptance/BreweriesSample2.json new file mode 100644 index 0000000..79ca308 --- /dev/null +++ b/cypress/fixtures/acceptance/BreweriesSample2.json @@ -0,0 +1,61 @@ +{ + "state": "MT", + "state-bird": "Western Meadowloark", + "state-fish": "Brown Trout", + "breweries": [ + { + "name": "Madison River Brewing", + "location": { + "address": "20900 Frontage Rd Building B", + "city": "Belgrade", + "state": null, + "zip-code": "59714" + }, + "food-available": false, + "beers": [ + { + "name": "Salmon Fly Honey Rye", + "color": "Gold", + "international-bitterness-units": 10, + "alcohol-by-volume": 0.06 + }, + { + "name": "Copper John Scotch Ale", + "color": "Copper", + "international-bitterness-units": 32, + "alcohol-by-volume": 0.05 + }, + { + "name": "Dropper IPA", + "color": "Amberish", + "international-bitterness-units": 108, + "alcohol-by-volume": 0.065 + } + ] + }, + { + "name": "Bozeman Brewing", + "location": { + "address": "504 N. Park Place", + "city": null, + "state": "MT", + "zip-code": "59715" + }, + "food-available": false, + "beers": [ + { + "name": "Bozone Amber Ale", + "color": "Amber", + "international-bitterness-units": "29", + "alcohol-by-volume": 0.054 + }, + { + "name": "Plum Street Porter", + "color": "Really Dark", + "international-bitterness-units": 52, + "alcohol-by-volume": "0.06" + } + ] + } + ] +} diff --git a/cypress/fixtures/acceptance/BreweriesSample3.json b/cypress/fixtures/acceptance/BreweriesSample3.json new file mode 100644 index 0000000..090488f --- /dev/null +++ b/cypress/fixtures/acceptance/BreweriesSample3.json @@ -0,0 +1,85 @@ +{ + "state": "MT", + "state-bird": "Western Meadowloark", + "state-fish": "Cutthroat Trout", + "breweries": [ + { + "name": "Madison River Brewing", + "location": { + "address": "20900 Frontage Rd Building B", + "city": "Belgrade", + "state": "MT", + "zip-code": "59714" + }, + "food-available": false, + "beers": [ + { + "name": "Salmon Fly Honey Rye", + "color": "Gold", + "international-bitterness-units": 12, + "alcohol-by-volume": 0.04 + }, + { + "name": "Copper John Scotch Ale", + "color": "Copper", + "international-bitterness-units": 35, + "alcohol-by-volume": 0.055 + }, + { + "name": "Dropper IPA", + "color": "Amber", + "international-bitterness-units": 108, + "alcohol-by-volume": 0.065 + }, + { + "name": "Black Ghost Oatmeal Stout", + "color": "Dark", + "international-bitterness-units": 30, + "alcohol-by-volume": 0.075 + } + ] + }, + { + "name": "Bozeman Brewing", + "location": { + "address": "504 N. Broadway", + "city": "Bozeman", + "state": "MT", + "zip-code": "59715" + }, + "food-available": true, + "beers": [ + { + "name": "Bozone Amber Ale", + "color": "Amber", + "international-bitterness-units": 29, + "alcohol-by-volume": 0.054 + }, + { + "name": "Plum Street Porter", + "color": "Dark", + "international-bitterness-units": 52, + "alcohol-by-volume": 0.06 + } + ] + }, + { + "name": "Red Lodge Ales", + "location": { + "address": "1445 North Broadway", + "city": "Red Lodge", + "state": "MT", + "zip-code": "59068" + }, + "food-available": true, + "beers": [ + { + "name": "Helio Hefeweizen", + "color": "Gold", + "international-bitterness-units": 17, + "alcohol-by-volume": 0.055 + } + ] + } + ] +} diff --git a/cypress/fixtures/acceptance/BreweriesSample4.json b/cypress/fixtures/acceptance/BreweriesSample4.json new file mode 100644 index 0000000..139c182 --- /dev/null +++ b/cypress/fixtures/acceptance/BreweriesSample4.json @@ -0,0 +1,51 @@ +{ + "state": "MT", + "breweries": [ + { + "name": "Madison River Brewing", + "food-available": false, + "beer-list": [ + { + "name": "Salmon Fly Honey Rye", + "international-bitterness-units": 12, + "alcohol-by-volume": 0.04 + }, + { + "name": "Copper John Scotch Ale", + "color": "Copper", + "international-bitterness-units": 35, + "alcohol-by-volume": 0.055 + }, + { + "name": "Dropper IPA", + "color": "Amber", + "international-bitterness-units": 108, + "alcohol-by-volume": 0.065 + } + ] + }, + { + "name": "Bozeman Brewing", + "address": { + "streetaddress": "504 N. Broadway", + "city": "Bozeman", + "zip-code": "59715" + }, + "food-available": true, + "beer-list": [ + { + "name": "Bozone Amber Ale", + "color": "Amber", + "international-bitterness-units": 29, + "alcohol-by-volume": 0.054 + }, + { + "name": "Plum Street Porter", + "color": "Dark", + "international-bitterness-units": 52, + "alcohol-by-volume": 0.06 + } + ] + } + ] +} diff --git a/cypress/fixtures/acceptance/BreweriesSample5.json b/cypress/fixtures/acceptance/BreweriesSample5.json new file mode 100644 index 0000000..2803bcb --- /dev/null +++ b/cypress/fixtures/acceptance/BreweriesSample5.json @@ -0,0 +1,69 @@ +{ + "state": "MT", + "state-bird": "Western Meadowloark", + "state-fish": "Cutthroat Trout", + "breweries": [ + { + "name": "Madison River Brewing", + "location": { + "address": "20900 Frontage Rd Building B", + "city": "Belgrade", + "state": "MT", + "zip-code": "59714", + "GPS": { + "lat": 45.44, + "long": 111.04 + } + }, + "food-available": false, + "beers": [ + { + "name": "Salmon Fly Honey Rye", + "color": "Gold", + "international-bitterness-units": 12, + "alcohol-by-volume": 0.04 + }, + { + "name": "Copper John Scotch Ale", + "color": "Copper", + "international-bitterness-units": 35, + "alcohol-by-volume": 0.055 + }, + { + "name": "Dropper IPA", + "color": "Amber", + "international-bitterness-units": 108, + "alcohol-by-volume": 0.065 + } + ] + }, + { + "name": "Bozeman Brewing", + "location": { + "address": "504 N. Broadway", + "city": "Bozeman", + "state": "MT", + "zip-code": "59715", + "GPS": { + "lat": 45.64, + "long": 111.02 + } + }, + "food-available": true, + "beers": [ + { + "name": "Bozone Amber Ale", + "color": "Amber", + "international-bitterness-units": 29, + "alcohol-by-volume": 0.054 + }, + { + "name": "Plum Street Porter", + "color": "Dark", + "international-bitterness-units": 52, + "alcohol-by-volume": 0.06 + } + ] + } + ] +} diff --git a/cypress/integration/app.spec.js b/cypress/integration/app.spec.js index 3561653..f2f3716 100644 --- a/cypress/integration/app.spec.js +++ b/cypress/integration/app.spec.js @@ -84,7 +84,21 @@ describe('The scoring app', () => { cy.contains('Compare').click(); // assert - cy.contains('Score: 1'); + cy.contains('Score: 100.00%'); + }); + }); + context('when the files are different', () => { + it('should show the score as a percentage', () => { + // arrange + const fileNameA = 'BreweriesMaster.json'; + const fileNameB = 'BreweriesSample4.json'; + cy.drop('File A', fileNameA); + cy.drop('File B', fileNameB); + // act + cy.contains('Compare').click(); + + // assert + cy.contains('Score: 35.71%'); }); }); }); diff --git a/cypress/support/commands.js b/cypress/support/commands.js index ba79842..cb8d81b 100644 --- a/cypress/support/commands.js +++ b/cypress/support/commands.js @@ -26,13 +26,9 @@ // eslint-disable-next-line import/no-extraneous-dependencies import 'cypress-file-upload'; -Cypress.Commands.add('drop', (containerName, fileName, okMessage = `File ${fileName} successfully added.`) => { +Cypress.Commands.add('drop', (containerName, fileName) => { const json = `acceptance/${fileName}`; - cy.contains(containerName).attachFile(json, { subjectType: 'drag-n-drop' }); - cy.contains(containerName).parent().parent().contains(fileName); - cy.contains(okMessage).get('.MuiIconButton-label').click(); - cy.contains(okMessage).should('not.exist'); // eslint-disable-next-line cypress/no-unnecessary-waiting cy.wait(500); // Drag-dropping works in mysterious ways }); diff --git a/jsconfig.json b/jsconfig.json new file mode 100644 index 0000000..2481bef --- /dev/null +++ b/jsconfig.json @@ -0,0 +1,9 @@ +{ + "compilerOptions": { + "baseUrl": ".", + "paths": { + "~/*": ["./*"] + } + }, + "exclude": ["node_modules"] +} diff --git a/package-lock.json b/package-lock.json index d0b8714..4b0fcf3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4437,12 +4437,11 @@ "dev": true }, "axios": { - "version": "0.19.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.2.tgz", - "integrity": "sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==", - "dev": true, + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.0.tgz", + "integrity": "sha512-fmkJBknJKoZwem3/IKSSLpkdNXZeBu5Q7GA/aRsr2btgrptmSCxi2oFjZHqGdK9DoTil9PIHlPIZw2EcRJXRvw==", "requires": { - "follow-redirects": "1.5.10" + "follow-redirects": "^1.10.0" } }, "axobject-query": { @@ -7975,30 +7974,9 @@ } }, "follow-redirects": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", - "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", - "dev": true, - "requires": { - "debug": "=3.1.0" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.13.0.tgz", + "integrity": "sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA==" }, "for-in": { "version": "1.0.2", @@ -19869,6 +19847,41 @@ "lodash": "^4.17.19", "minimist": "^1.2.5", "rxjs": "^6.5.5" + }, + "dependencies": { + "axios": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.2.tgz", + "integrity": "sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==", + "dev": true, + "requires": { + "follow-redirects": "1.5.10" + } + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "follow-redirects": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", + "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", + "dev": true, + "requires": { + "debug": "=3.1.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } } }, "walker": { diff --git a/package.json b/package.json index 5d8e677..d332909 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "dependencies": { "@material-ui/core": "^4.11.0", "@material-ui/icons": "^4.9.1", + "axios": "^0.21.0", "material-ui-dropzone": "^3.5.0", "next": "9.5.5", "prop-types": "^15.7.2", diff --git a/pages/api/score.js b/pages/api/score.js index 61863dd..8f385fc 100644 --- a/pages/api/score.js +++ b/pages/api/score.js @@ -1,7 +1,9 @@ +import { calculateScore } from '~/utils/score'; + export default (req, res) => { if (req.method === 'POST') { res.statusCode = 200; - res.json({ score: 1 }); + res.json(calculateScore(JSON.parse(req.body.jsonA), JSON.parse(req.body.jsonB))); } res.statusCode = 405; res.end('Method not allowed'); diff --git a/pages/index.js b/pages/index.js index 7609766..7e95b83 100644 --- a/pages/index.js +++ b/pages/index.js @@ -7,6 +7,7 @@ import { DropzoneArea } from 'material-ui-dropzone'; import Card from '@material-ui/core/Card'; import Grid from '@material-ui/core/Grid'; import Button from '@material-ui/core/Button'; +import axios from 'axios'; export default function Home() { const [jsonA, setJsonA] = useState(); @@ -24,7 +25,17 @@ export default function Home() { }; const compare = () => { - setScore(jsonA === jsonB ? 1 : 0); + axios + .post('/api/score', { + jsonA, + jsonB, + }) + .then(({ data }) => { + setScore(`${(data.scoreNumber * 100).toFixed(2)}%`); + }) + .catch((err) => { + console.log('error in request', err); // ToDo: properly catch errors. + }); }; return ( @@ -47,6 +58,7 @@ export default function Home() { useChipsForPreview dropzoneText="File A" filesLimit={0} + getFileAddedMessage={(fileName) => `${fileName} successfully added.`} previewGridProps={{ container: { justify: 'center', direction: 'row' } }} acceptedFiles={['application/json']} /> @@ -69,6 +81,7 @@ export default function Home() { useChipsForPreview dropzoneText="File B" filesLimit={0} + getFileAddedMessage={(fileName) => `${fileName} successfully added.`} previewGridProps={{ container: { justify: 'center', direction: 'row' } }} acceptedFiles={['application/json']} /> diff --git a/utils/score/__tests__/calculateScore.unit.test.js b/utils/score/__tests__/calculateScore.unit.test.js new file mode 100644 index 0000000..c3442d1 --- /dev/null +++ b/utils/score/__tests__/calculateScore.unit.test.js @@ -0,0 +1,104 @@ +import { calculateScore } from '../calculateScore'; +import complexJSON from '~/cypress/fixtures/acceptance/BreweriesMaster.json'; + +const TEST_PRECISION = 15; +const key0 = 'value1'; +const key1 = 'value1'; +const key2 = 'value2'; +const key3 = 'value3'; +const key4 = 'value4'; +const key5 = 'value5'; + +const simpleJSON = { + key1, +}; + +describe('score', () => { + describe('scoreNumber', () => { + describe('when the jsons are the same object', () => { + it('should return 1', () => { + // arrange + const jsonA = { + stringKey: 'StringValue', + numericKey: 3, + }; + + const jsonB = jsonA; + + // act + const scoreResult = calculateScore(jsonA, jsonB); + + // assert + expect(scoreResult.scoreNumber).toEqual(1); + }); + }); + + describe('when one of the json is empty', () => { + describe.each([ + ['and the other too', {}, {}, 1], + ['against any other json', {}, simpleJSON, 0], + ['when is the second one', complexJSON, {}, 0], + ])('when %s', (title, fileA, fileB, expected) => { + it(`should return ${expected.toFixed(TEST_PRECISION)} as score`, () => { + // act + const result = calculateScore(fileA, fileB); + + // assert + expect(result.scoreNumber.toFixed(TEST_PRECISION)).toEqual(expected.toFixed(TEST_PRECISION)); + }); + }); + }); + + describe('when the JSON are flat ones (only one level)', () => { + describe.each([ + ['with same 4 keys but half of values different', { + key1, key2, key3, key4, + }, { + key1, key2, key3: 'other value', key4: 42, + }, 0.5], + ['with 3 out of 5 identical keys, and the others with different value', { + key1, key2, key3, key4, key5, + }, { + key1, key2, key3: 'anotherValue', key4: 'yetAnotherValue', key5, + }, 3 / 5], + ['with 2 identical keys, one key with different value and one additional key in each', { + key1, key2, key3, key4, + }, { + key0, key2, key3, Key4: 'altValue', key5, + }, 2 / 7], + ])('when %s', (title, fileA, fileB, expected) => { + it(`should return ${expected.toFixed(TEST_PRECISION)} as score`, () => { + // act + const result = calculateScore(fileA, fileB); + + // assert + expect(result.scoreNumber.toFixed(TEST_PRECISION)).toEqual(expected.toFixed(TEST_PRECISION)); + }); + }); + }); + describe('when there are nested JSON', () => { + describe.each([ + ['two out of three root keys flat and equal, the remaining one has one equal and one different key', + { key1, key2, nestedKey: { key3, key4 } }, + { key1, key2, nestedKey: { key3, key4: 'altValue' } }, + 3 / 4], + ['three root keys are flat, two equal and one different, the fourth one has one equal and one different key', + { + key1, key2, keyDifferent: 'value1', nestedKey: { key3, key4 }, + }, + { + key1, key2, keyDifferent: 'value2', nestedKey: { key3, key4: 'altValue' }, + }, + 3 / 5], + ])('when %s', (title, fileA, fileB, expected) => { + it(`should return ${expected.toFixed(TEST_PRECISION)} as score`, () => { + // act + const result = calculateScore(fileA, fileB, { weighted: false }); + + // assert + expect(result.scoreNumber.toFixed(TEST_PRECISION)).toEqual(expected.toFixed(TEST_PRECISION)); + }); + }); + }); + }); +}); diff --git a/utils/score/calculateScore.js b/utils/score/calculateScore.js new file mode 100644 index 0000000..9db176e --- /dev/null +++ b/utils/score/calculateScore.js @@ -0,0 +1,69 @@ +/** + * Gets the union of two object keys, removing duplicates. + * @param objA is one of the objects + * @param objB is the other object + * @return {string[]} is an array of keys, without duplicates + */ +const getUniqueKeys = (objA, objB) => Object + .keys(objA) + .concat(Object.keys(objB) + .filter((item) => Object.keys(objA).indexOf(item) < 0)); + +/** + * A HoF that returns a function that evaluates if the type of the given key is an object (Object/Array) + * @param key is the key to look foor in the object + * @return {function(*): boolean} is the function that returns true if the key inside the object is of type `object` + */ +const isNode = (key) => (object) => typeof object[key] === 'object'; +/** + * Determines if the given key is an object (Object/Array) in all the objects. + * @param key is the key to compare in each object. + * @param objects is the array of objects to compare. + * @return {boolean} whether ALL the objects contain objects in the key. + */ +const bothContainSubElements = (key, objects) => objects.every(isNode(key)); + +// const isLeaf = (key) => (object) => typeof object[key] !== 'object'; +// const sameType = (key, objects) => objects.every(isLeaf(key)); + +/** + * A HoF that returns a reducer of keys for the given pair of objects, while scoring each key recursively thru + * recursivelyScore() + * @param objA is the "Left Object" to reduce. + * @param objB is the "Right Object" to reduce. + * @return {function(*=, *=): (*|{})} + */ +const getScoreReducer = (objA, objB) => (accumulatedResult, key) => { + let result = { count: 1, matched: 0 }; + + if (bothContainSubElements(key, [objA, objB])) { + // eslint-disable-next-line no-use-before-define + result = recursivelyScore(objA[key], objB[key], key); + } else if (typeof objA[key] === typeof objB[key]) { + result.matched = objA[key] === objB[key] ? 1 : 0; + } + return { + count: accumulatedResult.count + result.count, + matched: accumulatedResult.matched + result.matched, + }; +}; + +const recursivelyScore = (objA, objB) => { + const keys = getUniqueKeys(objA, objB); + return keys.reduce( + getScoreReducer(objA, objB), { matched: 0, count: 0 }, + ); +}; + +/** + * Calculates the overal score of two whole json objects. + * @param fileA + * @param fileB + * @return {{scoreNumber: number, log: *}} + */ +export const calculateScore = (fileA, fileB) => { + const result = recursivelyScore(fileA, fileB); + return { + scoreNumber: result.count > 0 ? result.matched / result.count : 1, + }; +}; diff --git a/utils/score/index.js b/utils/score/index.js new file mode 100644 index 0000000..3871d96 --- /dev/null +++ b/utils/score/index.js @@ -0,0 +1 @@ +export { calculateScore } from './calculateScore'; From c7eb8482c37e303de7bef04bbad66c367fb9fc0c Mon Sep 17 00:00:00 2001 From: Diego Pamio Date: Mon, 26 Oct 2020 18:38:14 -0300 Subject: [PATCH 2/2] fix: revert @babel/eslint-parser as codeclimate doesn't support it --- .eslintrc.js | 3 +- package-lock.json | 72 +++++++++++++++-------------------------------- package.json | 4 +-- 3 files changed, 24 insertions(+), 55 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 9046988..8451a7b 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -12,13 +12,12 @@ module.exports = { 'plugin:cypress/recommended', 'airbnb', ], - parser: '@babel/eslint-parser', + parser: 'babel-eslint', plugins: [ 'react', 'react-hooks', 'cypress', 'jest', - '@babel', ], settings: { 'import/resolver': { diff --git a/package-lock.json b/package-lock.json index 4b0fcf3..aca1880 100644 --- a/package-lock.json +++ b/package-lock.json @@ -141,50 +141,6 @@ } } }, - "@babel/eslint-parser": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.12.1.tgz", - "integrity": "sha512-cc7WQHnHQY3++/bghgbDtPx+5bf6xTsokyGzV6Qzh65NLz/unv+mPQuACkQ9GFhIhcTFv6yqwNaEcfX7EkOEsg==", - "dev": true, - "requires": { - "eslint-scope": "5.1.0", - "eslint-visitor-keys": "^1.3.0", - "semver": "^6.3.0" - }, - "dependencies": { - "eslint-scope": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.0.tgz", - "integrity": "sha512-iiGRvtxWqgtx5m8EyQUJihBloE4EnYeGE/bz1wSPwJE6tZuJUtHlhqDM4Xj2ukE8Dyy1+HCZ4hE0fzIVMzb58w==", - "dev": true, - "requires": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" - } - }, - "eslint-visitor-keys": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "@babel/eslint-plugin": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/eslint-plugin/-/eslint-plugin-7.12.1.tgz", - "integrity": "sha512-rOjrD5yupTYCO4x0kEbQmi/NsaD+VGOD/9Cvso64WMVPY2y6o5Nvw2sqFWdeSEBdR1Dsa07YjplBs067x5YbXg==", - "dev": true, - "requires": { - "eslint-rule-composer": "^0.3.0" - } - }, "@babel/generator": { "version": "7.12.1", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.12.1.tgz", @@ -4450,6 +4406,28 @@ "integrity": "sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA==", "dev": true }, + "babel-eslint": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.1.0.tgz", + "integrity": "sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@babel/parser": "^7.7.0", + "@babel/traverse": "^7.7.0", + "@babel/types": "^7.7.0", + "eslint-visitor-keys": "^1.0.0", + "resolve": "^1.12.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + } + } + }, "babel-jest": { "version": "26.6.0", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-26.6.0.tgz", @@ -7284,12 +7262,6 @@ "integrity": "sha512-623WEiZJqxR7VdxFCKLI6d6LLpwJkGPYKODnkH3D7WpOG5KM8yWueBd8TLsNAetEJNF5iJmolaAKO3F8yzyVBQ==", "dev": true }, - "eslint-rule-composer": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/eslint-rule-composer/-/eslint-rule-composer-0.3.0.tgz", - "integrity": "sha512-bt+Sh8CtDmn2OajxvNO+BX7Wn4CIWMpTRm3MaiKPCQcnnlm0CS2mhui6QaoeQugs+3Kj2ESKEEGJUdVafwhiCg==", - "dev": true - }, "eslint-scope": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", diff --git a/package.json b/package.json index d332909..490784f 100644 --- a/package.json +++ b/package.json @@ -28,9 +28,6 @@ "react-dom": "17.0.0" }, "devDependencies": { - "@babel/core": "^7.12.3", - "@babel/eslint-parser": "^7.12.1", - "@babel/eslint-plugin": "^7.12.1", "@commitlint/cli": "^11.0.0", "@commitlint/config-conventional": "^11.0.0", "@cypress/code-coverage": "^3.8.2", @@ -40,6 +37,7 @@ "@semantic-release/github": "^7.1.1", "@semantic-release/release-notes-generator": "^9.0.1", "@types/jest": "^26.0.15", + "babel-eslint": "^10.1.0", "babel-jest": "^26.6.0", "babel-plugin-istanbul": "^6.0.0", "cypress": "^5.4.0",