Why is .mock.instances printing this? - jestjs

This code snippet is pulled from the jest documentation.
const myMock = jest.fn();
const a = new myMock();
const b = {};
const bound = myMock.bind(b);
bound();
console.log(myMock.mock.instances);
// > [ <a>, <b> ]
I'm having trouble understanding why the
console.log(myMock.mock.instances) prints:
[< a >, < b > ]
I'm just a little confused why tags are being printed.
In addition, when I run it on my machine I get:
[ mockConstructor {}, {} ]

<a> and <b> aren't tags but formatting for special values that differ from regular JavaScript values.
[<a>, <b>] means that myMock function received a as this on the first call and b on the second call.

Related

get var inside script tag using puppeteer

good evening everyone, I'm trying to get the array that is in this.data = [{"id_penggiat":"6f81520f-1a8b-4d1d-a7d5-defdb630818b"...] . using cheerio and puppets. I have tried my best but not getting results. help me to solver this
<script>
.......
var PenggiatField = {
fieldid: '#penggiatField',
data: true,
debug: false,
Init: function(params) {
var field = this;
this.data = [{"id_penggiat":"6f81520f-1a8b-4d1d-a7d5-defdb630818b","id_kerma":"9388706e-7156-4d07-bf77-cb9c6d7f30d3","id_mitra":null,"id_unit":"89c82da3-7b28-4305-82c4-347dae042847","id_unit_teknis":null,"no_pihak":"1","nm_pihak":"Institut Teknologi Sepuluh Nopember","alamat":"Kampus ITS Sukolilo Surabaya","ttd_nama":"Tri Joko Wahyu Adi, ST., MT., Ph.D.","ttd_jabatan":"Direktur","pic_nama":"","pic_jabatan":"","pic_email":null,"pelaksana":["c2c72bf4-ec6c-46dd-8be8-d9fb77a90bd6","7e42c5bb-0c44-4b93-9162-ec6fb31cd67c","902bd59e-745d-4903-b1bf-171fe6f0fb8c","c93fb75a-1065-4587-a7af-475d4256f44d","9a6592f0-ff86-401d-8021-0e9f6fc285fe","8f2d4244-d868-45e3-a906-578ce2f9f572","1f8fc06b-4707-4e11-bdc8-312f39017758"],"create_date":"2022-03-16 04:41:14.146436","id_creator":"79ce0204-5c6d-43dd-a310-8c13a557a402","last_update":"2022-03-16 04:54:25.228835","id_updater":"79ce0204-5c6d-43dd-a310-8c13a557a402","soft_delete":"0","a_lembaga":"university","id_institusi":"89c82da3-7b28-4305-82c4-347dae042847","nm_mitra":null,"nm_unit":"Institut Teknologi Sepuluh Nopember","nm_unit_teknis":null,"id_klas_mitra":"12","nm_klas_mitra":"Institusi Pendidikan","id_negara":"ID","nm_negara":"Indonesia"},{"id_penggiat":"c4c3db69-8cbb-4a8e-ae6c-544b532760c6","id_kerma":"9388706e-7156-4d07-bf77-cb9c6d7f30d3","id_mitra":"f4b81538-6442-4a19-b9f6-8581d152725d","id_unit":null,"id_unit_teknis":null,"no_pihak":"2","nm_pihak":"Sekolah Menengah Atas Negeri 1 Karas Magetan","alamat":"Jl. Karas, Punden, Kuwon, Kec. Kendal, Kabupaten Magetan, Jawa Timur 63395","ttd_nama":"Bahtiar Kholili, S.Pd., M.M.Pd.","ttd_jabatan":"Kepala Sekolah","pic_nama":"","pic_jabatan":"","pic_email":null,"pelaksana":null,"create_date":"2022-03-16 04:41:14.146436","id_creator":"79ce0204-5c6d-43dd-a310-8c13a557a402","last_update":"2022-03-16 04:54:25.228835","id_updater":"79ce0204-5c6d-43dd-a310-8c13a557a402","soft_delete":"0","a_lembaga":"mitra","id_institusi":"f4b81538-6442-4a19-b9f6-8581d152725d","nm_mitra":"Sekolah Menengah Atas Negeri 1 Karas Magetan","nm_unit":null,"nm_unit_teknis":null,"id_klas_mitra":"12","nm_klas_mitra":"Institusi Pendidikan","id_negara":"ID","nm_negara":"Indonesia"}];
........
</script>
in puppeteer the following would do the job, but it is not a general solution.
await page.goto(pageUrl)
const filteredArray = await page.$$eval('script', scripts =>
JSON.parse(
scripts
.map(src => src.innerHTML)
.filter(el => el.includes('"id_penggiat":'))[0] // selecting the desired <script>
.split('\n')
.filter(el => el.includes('"id_penggiat":'))[0] // selecting the exact script line within the <sript>'s innerHTML
.replace(/this.data\W=\W|;$/gm, '')
.trim()
)
)
console.log(filteredArray)
what's happening?
page.$$eval collects all <script> tags into an array
we map over all scripts' innerHTML
select the one that includes the "id_penggiat": string fragment
any JavaScript scripts will be received in a huge string with innerHTML, all lines will be delimited by \n linebreaks: we can split them one-by-one
let's select the exact line within the tag that includes "id_penggiat": string fragment
clean the output string from the un-parseable parts like the variable name, this, and the ending ;. plus trim the extra spaces from the beginning of the line.
the final result can be parsed as JSON.
note: using the 1st index [0] on the Array.filter-ed values picking only the first occurrences, if you want all of them: you will need to process further.

NodeJS could not read [Object] in JSON data

I have data as a JSON format
{"mac":"f008d155b4fe","deviceClass":["iBeacon","eddystone"],"model":"iBeacon","lastSeen":"1637655820","bevent":{"event":"update"},"rssi":{"last":-84},"beacons":[{"ibeacon":{"uuid":"783a69707094d0863b4a9bf94e555241","major":816,"minor":6,"power":0},"eddystone":{"power":0}}],"sensors":{"temperatureC":18,"voltage":3.299999952316284},"stats":{"uptime":"710","adv_cnt":"24","frame_cnt":7}},
{"mac":"a0e6f8515eff","deviceClass":["arubaTag"],"firmware":{"bankA":"1.2-15"},"assetId":"0000-0000-0000","lastSeen":"1637655821","bevent":{"event":"update"},"rssi":{"last":-69},"sensors":{"battery":83},"stats":{"uptime":"82350","frame_cnt":3},"vendorName":"Aruba"}
I can print data from the level 1 but I could not print data in another level from JSON
I would like to print value from beacons: [ [Object] ],
Please give me a hints thank you
here is my code
const data = [
{"mac":"f008d155b4fe","deviceClass":["iBeacon","eddystone"],"model":"iBeacon","lastSeen":"1637655820","bevent":{"event":"update"},"rssi":{"last":-84},"beacons":[{"ibeacon":{"uuid":"783a69707094d0863b4a9bf94e555241","major":816,"minor":6,"power":0},"eddystone":{"power":0}}],"sensors":{"temperatureC":18,"voltage":3.299999952316284},"stats":{"uptime":"710","adv_cnt":"24","frame_cnt":7}},
{"mac":"a0e6f8515eff","deviceClass":["arubaTag"],"firmware":{"bankA":"1.2-15"},"assetId":"0000-0000-0000","lastSeen":"1637655821","bevent":{"event":"update"},"rssi":{"last":-69},"sensors":{"battery":83},"stats":{"uptime":"82350","frame_cnt":3},"vendorName":"Aruba"}
];
const arr1 = data.filter(d => d.mac == "f008d155b4fe");
console.log('arr1', arr1);
for (k in arr1.beacons) {
console.log(k, ":", arr1.beacons[k]);
}
This worked for me, I made it all an object and now you can access the beacons by doing newData.devices[0].beacons[0].(property)
const newData = {"devices": [{"mac":"f008d155b4fe","deviceClass":["iBeacon","eddystone"],"model":"iBeacon","lastSeen":"1637655820","bevent":{"event":"update"},"rssi":{"last":-84},"beacons":[{"ibeacon":{"uuid":"783a69707094d0863b4a9bf94e555241","major":816,"minor":6,"power":0},"eddystone":{"power":0}}],"sensors":{"temperatureC":18,"voltage":3.299999952316284},"stats":{"uptime":"710","adv_cnt":"24","frame_cnt":7}}, {"mac":"a0e6f8515eff","deviceClass":["arubaTag"],"firmware":{"bankA":"1.2-15"},"assetId":"0000-0000-0000","lastSeen":"1637655821","bevent":{"event":"update"},"rssi":{"last":-69},"sensors":{"battery":83},"stats":{"uptime":"82350","frame_cnt":3},"vendorName":"Aruba"}]};
for (const beacon of newData.devices[0].beacons) {
console.log(beacon);
}
you are close to the solution, but arr1 is an array, so it doesn't have a 'beacon' property. Use the following instead:
const data = [
{"mac":"f008d155b4fe","deviceClass":["iBeacon","eddystone"],"model":"iBeacon","lastSeen":"1637655820","bevent":{"event":"update"},"rssi":{"last":-84},"beacons":[{"ibeacon":{"uuid":"7$
{"mac":"a0e6f8515eff","deviceClass":["arubaTag"],"firmware":{"bankA":"1.2-15"},"assetId":"0000-0000-0000","lastSeen":"1637655821","bevent":{"event":"update"},"rssi":{"last":-69},"sen$
];
const arr1 = data.filter(d => d.mac == "f008d155b4fe");
console.log('arr1', arr1);
for (k of arr1) {
console.log(k.beacons);
}
arr1 is an Array it doesn't have beacons property. If you expect it to be the only one item with the mac you should use data.find instead of data.filter. Also do not use for-in loop to iterate over arrays. You can use for-of or .forEach instead.
const data = [
{"mac":"f008d155b4fe","deviceClass":["iBeacon","eddystone"],"model":"iBeacon","lastSeen":"1637655820","bevent":{"event":"update"},"rssi":{"last":-84},"beacons":[{"ibeacon":{"uuid":"783a69707094d0863b4a9bf94e555241","major":816,"minor":6,"power":0},"eddystone":{"power":0}}],"sensors":{"temperatureC":18,"voltage":3.299999952316284},"stats":{"uptime":"710","adv_cnt":"24","frame_cnt":7}},
{"mac":"a0e6f8515eff","deviceClass":["arubaTag"],"firmware":{"bankA":"1.2-15"},"assetId":"0000-0000-0000","lastSeen":"1637655821","bevent":{"event":"update"},"rssi":{"last":-69},"sensors":{"battery":83},"stats":{"uptime":"82350","frame_cnt":3},"vendorName":"Aruba"}
];
// expecting only o1
const arr1 = data.find(d => d.mac == "f008d155b4fe");
console.log('arr1', arr1);
for (const beacon of arr1.beacons) { // use for-of or `forEach`
console.log(beacon);
}

Is it absolutely the case that arrays are used by reference in other modules in Node.js?

I have
// file cars.js
var bodyshop = require('./bodyshop')
var connections = [];
many functions which operate on connections. adding them, changing them etc.
code in this file includes things like
bodyshop.meld(blah)
bodyshop.mix(blah)
exports.connections = connections
and then
// file bodyshop.js
let cars = require('./cars');
even more functions which operate on connections. adding them, changing them etc.
code in this file includes things like
cars.connections[3].color = pink
cars.connections.splice(deleteMe, 1)
module.exports = { meld, mix, flatten }
Is it absolutely honestly the case that code in bodyshop such as cars.connections.splice(deleteMe, 1) will indeed delete an item from "the" connections (ie, the one and only connections, declared in cars.js) and code in bodyshop such as cars.connections[3].color = pink will indeed change the color of index 3 of "the" self-same one and only connections?
Is it quite OK / safe / acceptable that I used the syntax "module.exports = { }" at the end of bodyshop, rather than three lines like "exports.meld = meld" ?
Is this sentence indeed to totally correct?? "In Node.js if you export from M an array, when using the array in another module X which requires M, the array will be by reference in X, i.e. not by copy" ... ?
I created two files with the following methods and the array as you mentioned.
First File: test1.js
const testArray = [];
const getArray = () => {
return testArray;
};
module.exports = {
testArray,
getArray
}
Second File: test2.js
const { testArray, getArray } = require('./test1');
console.log('testing the required array before modifying it');
console.log(getArray());
testArray.push('test');
console.log('testing the method result after modifying the required array content');
console.log(getArray());
If you can create the mentioned files and run them locally, you will see the following result.
>node test2.js
testing the required array before modifying it
[]
testing the method result after modifying the required array content
[ 'test' ]
The points observed is,
yes, it's okay if you want to export it with the syntax module.exports = { }, It not much an issue.
If any of the methods modify this array outside of the required file, it will affect here as well, This because require will be a reference, not a copy.
The one possible solution will be creating a JSON copy of it while requiring as below:
const { testArray, getArray } = require('./test1');
const testArrayCopy = JSON.parse(JSON.stringify(testArray));
console.log('testing the required array before modifying it');
console.log(getArray());
testArrayCopy.push('test');
console.log('testing the method result after modifying the required array content');
console.log(getArray());
This is the result:
>node test2.js
testing the required array before modifying it
[]
testing the method result after modifying the required array content
[]
Note: JSON copy will not help you in parsing DateTime properly.

Find JSON value using variable from function

I'm working on a function where I need to be able to input a string which is a key in a JSON object then I need to be able to take the actual object and tack on the string to get the correct value from the JSON
function contact(contact_method) {
let method = array[place].settings.contact_method; // Example for contact_method is 'first_contact_method'
console.log(method)
}
The idea is I have 3 different contact methods and I'd like to be able to use the same function for all 3. I know the code above is barely a function but I think it shows what I want to be able to do.
I could not find anything on MDN or SO about this. I had tried using ES6 and string with `` but that did not work it just returned [object Object].first_contact_method
You can access keys of objects with a variable by using [].
For instance:
const obj = { a: 4, b: 5, c: () => { /* do something*/}, d() { /* do something*/ } }
const keyA = 'a'
const keyC = 'c'
const valueA = obj[keyA] // valueA === 4
const methodC = obj[keyC]
// Call method c
methodC()
// or short
obj[keyC]()
// and even for "real" methods
obj['d']()

chai test array equality doesn't work as expected

Why does the following fail?
expect([0,0]).to.equal([0,0]);
and what is the right way to test that?
For expect, .equal will compare objects rather than their data, and in your case it is two different arrays.
Use .eql in order to deeply compare values. Check out this link.
Or you could use .deep.equal in order to simulate same as .eql.
Or in your case you might want to check .members.
For asserts you can use .deepEqual, link.
Try to use deep Equal. It will compare nested arrays as well as nested Json.
expect({ foo: 'bar' }).to.deep.equal({ foo: 'bar' });
Please refer to main documentation site.
for unordered deep equality, use members
expect([1,2,3]).to.have.members([3,2,1]); // passes expect([1,2,3]).to.have.members([1,2,3]); // passes expect([1,2,3]).to.eql([3,2,1]); // fails
source
import chai from 'chai';
const arr1 = [2, 1];
const arr2 = [2, 1];
chai.expect(arr1).to.eql(arr2); // Will pass. `eql` is data compare instead of object compare.
You can use .deepEqual()
const { assert } = require('chai');
assert.deepEqual([0,0], [0,0]);
You can use
https://www.chaijs.com/api/assert/#method_samedeepmembers
assert.sameDeepMembers(set1, set2, [message])
Asserts that set1 and set2 have the same members in any order. Uses a deep equality check.
assert.sameDeepMembers([ { a: 1 }, { b: 2 }, { c: 3 } ], [{ b: 2 }, { a: 1 }, { c: 3 }], 'same deep members');
This is how to use chai to deeply test associative arrays.
I had an issue trying to assert that two associative arrays were equal. I know that these shouldn't really be used in javascript but I was writing unit tests around legacy code which returns a reference to an associative array. :-)
I did it by defining the variable as an object (not array) prior to my function call:
var myAssocArray = {}; // not []
var expectedAssocArray = {}; // not []
expectedAssocArray['myKey'] = 'something';
expectedAssocArray['differentKey'] = 'something else';
// legacy function which returns associate array reference
myFunction(myAssocArray);
assert.deepEqual(myAssocArray, expectedAssocArray,'compare two associative arrays');

Resources