Related
The issue I am facing is that even though I am able to load the data in the database but the desired result is different from what is being returned.
The issue is that whenever I am running for loop the qn variable is inserted twice but need it only once.
Please if someone can help me resolve this issue.
userProject.js
router.post('/notification/check/upload/survey' , async (req,res) => {
//const taginsert = [];
const mcq = [];
//const newData = {};
//const o = {};
console.log(req.body);
for(var i=0; i<=req.body.questions.length-1;i++) {
// newData = {
// qn: req.body.questions[i].qn
// }
for(var j=0; j<=req.body.questions[i].options.length-1;j++){
const o =
{
qn: req.body.questions[i].qn,
//{
options: [{
option: req.body.questions[i].options[j].option,
totalValues: req.body.questions[i].options[j].totalValues
}]
}
// newData.options = o;
// newData.push(o);
mcq.push(o);
}
}
//mcq = newData;
const check = new userCampaignSurvey({
userId: req.body.userId,
status: 'Pending',
notification_type:req.body.notification_type,
questions: mcq
})
check.save((err,p) => {
if(err) {
res.status(500).send(err);
}
res.status(201).send(p);
})
})
model.js
userId:
{
type: Number,
required: true,
trim: true
},
notification_id:
{
type: Number,
},
notification_type:
{
type: Number,
required: true,
},
status:
{
type: String,
required: true
},
questions: [
{
qn: {
type: String,
required: true
},
options: [
{
option: {
type: String
},
totalViews: {
type:Number
}
}
]
},
],
created_at: {
type: Date,
required: true,
default: Date.now(),
},
});
result received
{
"userId": 1,
"notification_type": 1,
"status": "Pending",
"questions": [
{
"qn": "Which brand do you like better for buying shoes?",
"options": [
{
"option": "Adidas",
"_id": "639064c9ec215f2cd1b2b15d"
}
],
"_id": "639064c9ec215f2cd1b2b15c"
},
{
"qn": "Which brand do you like better for buying shoes?",
"options": [
{
"option": "Reebok",
"_id": "639064c9ec215f2cd1b2b15f"
}
],
"_id": "639064c9ec215f2cd1b2b15e"
}
],
"created_at": "2022-12-07T10:02:48.442Z",
"_id": "639064c9ec215f2cd1b2b15b",
"__v": 0
}
expected result
{
"userId": 1,
"status": "Pending",
"notification_type": 1,
"questions": [
{
"qn": "Which brand do you like better for buying shoes?",
"options": [
{
"option": "Adidas",
"totalViews": 20
},
{
"option": "Reebok",
"totalViews": 10
}
]
}
]
}
I looked at several of the suggested solutions but none seemed to rise to this confounding data formatting challenge.
I have a huge JSON file (over 100k rows) and massive duplicates of data all as top level objects. Here's an example:
[
{
"manufacturer":"Samsung",
"device":"Galaxy A32 5G",
"model":"SM-A326B",
"chipset":"Mediatek MT6853V/NZA",
"date":"2022-01-01",
"fw_id":"A326BXXS4AVA1",
"android":"R(Android 11)",
"known_passcode":false,
"afu":false,
"bfu":false,
"bruteforce":false
},
{
"manufacturer":"Samsung",
"device":"Galaxy A32 5G",
"model":"SM-A326U",
"chipset":"Mediatek MT6853V/NZA",
"date":"2021-03-01",
"fw_id":"A326USQU1AUD4",
"android":"R(Android 11)",
"known_passcode":true,
"afu":false,
"bfu":true,
"bruteforce":true
},
{
"manufacturer":"Samsung",
"device":"Galaxy A32 5G",
"model":"SM-A326U1",
"chipset":"Mediatek MT6853V/NZA",
"date":"2021-09-01",
"fw_id":"A326U1UEU5AUJ2",
"android":"R(Android 11)",
"known_passcode":true,
"afu":false,
"bfu":true,
"bruteforce":true
},
{
"manufacturer":"LGE",
"device":"LG K31",
"model":"LGL355DL",
"chipset":"Mediatek MT6762",
"date":"unknown",
"fw_id":"L355DL10l",
"android":"unknown",
"known_passcode":false,
"afu":false,
"bfu":false,
"bruteforce":false
}
]
This needs to be organized so that data points like manufacturer, device, model are not duplicated hundreds of times.
Btw, here's a JSFiddle to play with:
https://jsfiddle.net/xpancom/Lq7duahv/
Ideally, the JSON format would be the following:
[
{
"manufacturers": [
{
"manufacturer": "Samsung",
"devices": [
{
"device": "Galaxy A32 5G",
"models": [
{
"model": "SM-A326B",
"data": [
{
"chipset": "Mediatek MT6853V/NZA",
"date": "2022-01-01",
"fw_id": "A326BXXS4AVA1",
"android": "R(Android 11)",
"known_passcode": false,
"afu": false,
"bfu": false,
"bruteforce": false
},
{
"chipset": "Mediatek MT6853V/NZA",
"date": "2021-09-01",
"fw_id": "A326BXXU3AUH7",
"android": "R(Android 11)",
"known_passcode": true,
"afu": false,
"bfu": true,
"bruteforce": true
}
]
},
{
"model": "SM-A326U1",
"data": [
{
"chipset": "Mediatek MT6853V/NZA",
"date": "2021-09-01",
"fw_id": "A326U1UEU5AUJ2",
"android": "R(Android 11)",
"known_passcode": true,
"afu": false,
"bfu": true,
"bruteforce": true
}
]
}
]
}
]
},
{
"manufacturer": "LGE",
"devices": [
{
"device": "LG K31",
"models": [
{
"model": "SM-A326B",
"data": [
{
"chipset": "Mediatek MT6762",
"date": "unknown",
"fw_id": "L355DL10l",
"android": "unknown",
"known_passcode": false,
"afu": false,
"bfu": false,
"bruteforce": false
}
]
}
]
}
]
}
]
}
]
Working in React, here's what I've got so far in trying to massage this data:
const source = data;
const destination = [];
const classifiedTokens = []; // will be used to stored already classified tokens
const classifiedTokensModel = []; // will be used to stored already classified tokens for models
const getNextTokenArray = (source) => {
let unusedToken = null;
const nextTokenArray = source.filter(function (element) {
if (!unusedToken && !classifiedTokens.includes(element['device'])) {
unusedToken = element['device'];
classifiedTokens.push(unusedToken);
}
return unusedToken ? unusedToken === element['device'] : false;
});
return unusedToken ? nextTokenArray : null;
};
// Pass in arrays deconstructed from addToDestination to process third tier nested objects for models
const getNextTokenArrayModel = (tokenObject) => {
let tokenObjectDevice = tokenObject['device'];
let tokenObjectData = tokenObject['data'];
let unusedTokenModel = null;
const nextTokenArrayModel = tokenObjectData.filter(function (element) {
if (!unusedTokenModel && !classifiedTokensModel.includes(element['model'])) {
unusedTokenModel = element['model'];
classifiedTokensModel.push(unusedTokenModel);
}
return unusedTokenModel ? unusedTokenModel === element['model'] : false;
});
//return unusedTokenModel ? nextTokenArrayModel : null;
if (unusedTokenModel) {
if (nextTokenArrayModel.length === 0) return;
let res = {
device: tokenObjectDevice,
model: nextTokenArrayModel[0]['model'],
data: [],
};
nextTokenArrayModel.forEach((element) => {
res.data.push({
manufacturer: element.manufacturer,
chipset: element.chipset,
date: element.date,
fw_id: element.fw_id,
android: element.android,
knownPasscode: element.knownPasscode,
afu: element.afu,
bfu: element.bfu,
bruteforce: element.bruteforce,
});
});
destination.push(res);
} else {
return null;
}
};
const addToDestination = (tokenArray) => {
if (tokenArray.length === 0) return;
let res = {
device: tokenArray[0]['device'],
data: [],
};
tokenArray.forEach((element) => {
res.data.push({
manufacturer: element.manufacturer,
model: element.model,
chipset: element.chipset,
date: element.date,
fw_id: element.fw_id,
android: element.android,
knownPasscode: element.knownPasscode,
afu: element.afu,
bfu: element.bfu,
bruteforce: element.bruteforce,
});
});
getNextTokenArrayModel(res); // Call this to process and group nested model duplicates by device
//destination.push(res);
};
let nextTokenArray = getNextTokenArray(source);
while (nextTokenArray) {
addToDestination(nextTokenArray);
nextTokenArray = getNextTokenArray(source);
}
setTimeout(() => {
document.getElementById('root').innerHTML =
'<pre>' + JSON.stringify(destination, null, 2) + '</pre>';
}, 1000);
};
And here's the JSFiddle again:
https://jsfiddle.net/xpancom/Lq7duahv/
Who can smash this data formatting dilemma?
This answer is not React specific, but one approach would be to use array.reduce() to transform each level/node of the structure as shown in the code snippet below.
const source = [
{
manufacturer: 'Samsung',
device: 'Galaxy A32 5G',
model: 'SM-A326B',
chipset: 'Mediatek MT6853V/NZA',
date: '2022-01-01',
fw_id: 'A326BXXS4AVA1',
android: 'R(Android 11)',
known_passcode: false,
afu: false,
bfu: false,
bruteforce: false,
},
{
manufacturer: 'Samsung',
device: 'Galaxy A32 5G',
model: 'SM-A326B',
chipset: 'Mediatek MT6853V/NZA',
date: '2022-01-01',
fw_id: 'A326BXXS4AVA1',
android: 'R(Android 11)',
known_passcode: false,
afu: false,
bfu: false,
bruteforce: false,
},
{
manufacturer: 'Samsung',
device: 'Galaxy A32 5G',
model: 'SM-A326U',
chipset: 'Mediatek MT6853V/NZA',
date: '2021-03-01',
fw_id: 'A326USQU1AUD4',
android: 'R(Android 11)',
known_passcode: true,
afu: false,
bfu: true,
bruteforce: true,
},
{
manufacturer: 'Samsung',
device: 'Galaxy A32 5G',
model: 'SM-A326U1',
chipset: 'Mediatek MT6853V/NZA',
date: '2021-09-01',
fw_id: 'A326U1UEU5AUJ2',
android: 'R(Android 11)',
known_passcode: true,
afu: false,
bfu: true,
bruteforce: true,
},
{
manufacturer: 'LGE',
device: 'LG K31',
model: 'LGL355DL',
chipset: 'Mediatek MT6762',
date: 'unknown',
fw_id: 'L355DL10l',
android: 'unknown',
known_passcode: false,
afu: false,
bfu: false,
bruteforce: false,
},
];
function generateTree(data, key) {
return data.reduce((acc, val) => {
// Split the key name from the child data
const { [key.name]: keyName, ...childData } = val;
// Find a tree item in the structure being generated
const treeItem = acc.find((item) => item[key.name] === keyName);
if (treeItem) {
// If found, append child data
treeItem[key.child].push(childData);
} else {
// If not found, create new key and append child data
acc.push({ [key.name]: keyName, [key.child]: [childData] });
}
return acc;
}, []);
}
// Generate manufacturer/device structure
const manufacturers = generateTree(source, {
name: 'manufacturer', // Key name to use as grouping identifier
child: 'devices', // Key name for child data
});
// Generate device/model structure
manufacturers.forEach((manufacturer) => {
manufacturer.devices = generateTree(manufacturer.devices, {
name: 'device',
child: 'models',
});
// Generate model/data structure
manufacturer.devices.forEach((device) => {
device.models = generateTree(device.models, {
name: 'model',
child: 'data',
});
});
});
const destination = [{ manufacturers }];
console.log(destination);
I'm struggling trying to unit test some components in an app and I would really apreciate if someone could help me.
I've already set up the Jest enviroment for testing in Vue and things work just fine until I try to test a component that rely on other modules with functions in it. These functions are helpers useful for importing vuex actions and getters quicker in the components. Here there are some lines of code that I hope could help with the problem:
this is the error that Jest throws in the console:
/app # yarn test:unit /common / page - header / ProjectWizard.spec.js
yarn run v1 .22 .5
$ jest / common / page - header / ProjectWizard.spec.js
FAIL src / specs / common / page - header / projectWizard.spec.js
● Test suite failed to run
Configuration error:
Could not locate module # / state / helpers mapped as:
/app/$1.
Please check your configuration
for these entries: {
"moduleNameMapper": {
"/^#\/(.*)$/": "/app/$1"
},
"resolver": undefined
}
57 |
import VueGoogleAutocomplete from '../../../node_modules/vue-google-autocomplete'
58 |
> 59 |
import {
|
^
60 | contractTypesMethods,
61 | contractTypesGetters,
62 | installationTypesMethods,
at createNoMappedModuleFoundError(node_modules / jest - resolve / build / index.js: 551: 17)
at src / components / builder / ProjectWizard.vue: 59: 1
at Object. < anonymous > (src / components / builder / ProjectWizard.vue: 491: 3)
this is the ProjectWizard file:
<template>
<form-wizard
#on-complete="onComplete(model)"
error-color="#f1b44c"
color="#EC641C"
nextButtonText="Avanti"
backButtonText="Indietro"
:finishButtonText="(isModifying) ? 'Conferma modifiche' : 'Crea Progetto'"
id="project-form-wizard"
style="overflow: hidden;"
>
<tab-content title="Informazioni preliminari" icon="mdi mdi-folder-information" :before-change="validateFirstTab">
<vue-form-generator-component :model="model" :schema="zeroTabSchema" :options="formOptions" ref="zeroTabSchema">
</vue-form-generator-component>
<b-form-group featured class="col-12" label="Indirizzo (Via etc.)" label-for="indirizzo-progetto">
<vue-google-autocomplete required keypress types="" ref="address" id="indirizzo-progetto"
classname="form-control" placeholder="Inserisci qui l'indirizzo del progetto"
v-on:placechanged="getAddressData" country="it">
</vue-google-autocomplete>
</b-form-group>
<vue-form-generator-component :model="model" :schema="firstTabSchema" :options="formOptions" ref="firstTabForm">
</vue-form-generator-component>
</tab-content>
<tab-content
title="Dettagli progetto"
icon="mdi mdi-home-search-outline"
:before-change="validateSecondTab"
>
<vue-form-generator-component
:model="model"
:schema="secondTabSchema"
:options="formOptions"
ref="secondTabForm"
></vue-form-generator-component>
</tab-content>
</form-wizard>
</template>
<script>
import {
FormWizard,
TabContent
} from "vue-form-wizard";
import VueFormGenerator from 'vue-form-generator'
import {
resources
} from "../../../src/utils/validation"
Object.assign(VueFormGenerator.validators.resources, resources)
import VueGoogleAutocomplete from '../../../node_modules/vue-google-autocomplete'
import {
contractTypesMethods,
contractTypesGetters,
installationTypesMethods,
installationTypesGetters,
interventionTypesMethods,
interventionTypesGetters,
contactsMethods,
projectManagementMethods,
projectManagementGetters,
projectsMethods
} from "#/state/helpers";
// STATELESS
import {
fetchContacts
} from '#/stateless/modules/common'
export default {
data() {
var vm = this;
return {
...contractTypesGetters,
...installationTypesGetters,
...interventionTypesGetters,
...projectManagementGetters,
contractTypes: [],
selectedContract: "",
installationTypesFiltered: [],
interventionTypesFiltered: [],
installationTypes: [],
interventionTypes: [],
contactPersons: [],
address: '',
model: {
projectName: '',
address: {
partialStreet: '',
streetNumber: '',
city: '',
province: '',
country: '',
CAP: '',
state: ''
},
contractType: '',
installationType: '',
interventionType: '',
contactPerson: '',
description: ''
},
formOptions: {
validationErrorClass: "has-error",
validationSuccessClass: "has-success",
validateAfterChanged: true,
},
zeroTabSchema: {
fields: [{
type: "input",
inputType: "text",
label: "Nome del progetto",
model: "projectName",
required: true,
featured: true,
maxlength: 64,
validator: VueFormGenerator.validators.string,
styleClasses: 'col-12'
},]
},
firstTabSchema: {
fields: [
{
type: "input",
inputType: "text",
label: "Via",
model: "address.partialStreet",
required: true,
featured: true,
maxlength: 128,
validator: VueFormGenerator.validators.string,
styleClasses: 'col-6'
},
{
type: "input",
inputType: "text",
label: "Numero civico",
model: "address.streetNumber",
required: true,
featured: true,
maxlength: 16,
validator: VueFormGenerator.validators.string,
styleClasses: 'col-6'
},
{
type: "input",
inputType: "text",
label: "Città",
model: "address.city",
required: true,
featured: true,
maxlength: 64,
validator: VueFormGenerator.validators.string,
styleClasses: 'col-6'
},
{
type: "input",
inputType: "text",
label: "Provincia",
model: "address.province",
required: true,
featured: true,
maxlength: 2,
validator: VueFormGenerator.validators.string,
styleClasses: 'col-6'
},
{
type: "input",
inputType: "text",
label: "Paese",
model: "address.country",
required: true,
featured: true,
maxlength: 32,
validator: VueFormGenerator.validators.string,
styleClasses: 'col-6'
},
{
type: "input",
inputType: "text",
label: "CAP",
model: "address.CAP",
required: true,
featured: true,
min: 5,
maxlength: 8,
validator: VueFormGenerator.validators.string,
styleClasses: 'col-6'
},
{
type: "input",
inputType: "text",
visible: false,
label: "Regione",
model: "address.state",
required: true,
featured: true,
maxlength: 32,
validator: VueFormGenerator.validators.string,
styleClasses: 'col-6'
},
]
},
secondTabSchema: {
fields: [{
type: "select",
label: "Tipo di appalto",
model: "contractType",
required: true,
featured: true,
validator: VueFormGenerator.validators.string,
styleClasses: 'col-12',
selectOptions: {
hideNoneSelectedText: true
},
onChanged(event) {
const filterdTypes = vm.installationTypes.filter((element) => {
return element.contractType === event.contractType
})
let installation = document.getElementById('insediamento')
installation.innerHTML = ''
installation.disabled = false
for (let i = 0; i < filterdTypes.length; i++) {
installation.options[i] = new Option(
filterdTypes[i].name,
filterdTypes[i].id
)
}
installation.value = ""
let intervention = document.getElementById('tipologia-di-intervento')
intervention.value = ""
},
values: () => {
return this.contractTypes
},
},
{
type: "select",
disabled: "true",
label: "Insediamento",
model: "installationType",
required: true,
featured: true,
validator: VueFormGenerator.validators.string,
styleClasses: 'col-12',
selectOptions: {
hideNoneSelectedText: true
},
onChanged(event) {
const filterdTypes = vm.interventionTypes.filter((element) => {
return element.installationType === event.installationType
})
let intervention = document.getElementById('tipologia-di-intervento')
intervention.innerHTML = ''
intervention.disabled = false
for (let i = 0; i < filterdTypes.length; i++) {
intervention.options[i] = new Option(
filterdTypes[i].name,
filterdTypes[i].id
)
}
intervention.value = ""
},
values: () => {
return this.isModifying ? this.installationTypes : []
},
},
{
type: "select",
disabled: "true",
noneSelectedText: "",
label: "Tipologia di intervento",
model: "interventionType",
required: true,
featured: true,
validator: VueFormGenerator.validators.string,
styleClasses: 'col-12',
selectOptions: {
hideNoneSelectedText: true
},
values: () => {
return this.isModifying ? this.interventionTypes : []
},
},
{
type: "select",
label: "Referente di progetto",
model: "contactPerson",
required: true,
featured: true,
validator: VueFormGenerator.validators.string,
styleClasses: 'col-12',
selectOptions: {
hideNoneSelectedText: true
},
hint: '<div id="new-contact-creation-project"><i class="mdi mdi-account-multiple-plus"></i> <span>Crea nuovo referente</span></div>',
values: () => {
return this.contactPersons
},
},
{
type: "textArea",
label: "Descrizione",
model: "description",
featured: true,
maxlength: 512,
validator: VueFormGenerator.validators.string,
styleClasses: 'col-12'
}
]
}
}
},
components: {
FormWizard,
TabContent,
'vue-form-generator-component': VueFormGenerator.component,
VueGoogleAutocomplete
},
computed: {
isModifying() {
return (this.$router.currentRoute.name == 'builderHome') ? false : true
},
},
methods: {
...contractTypesMethods,
...installationTypesMethods,
...interventionTypesMethods,
...contactsMethods,
...projectsMethods,
...projectManagementMethods,
onComplete: function (json) {
if (this.isModifying) {
this.updateProject({
projectId: this.currentProject().id,
name: this.model.projectName,
description: this.model.description,
address: this.model.address.partialStreet,
streetNumber: this.model.address.streetNumber,
city: this.model.address.city,
province: this.model.address.province,
country: this.model.address.country,
zipCode: this.model.address.CAP,
contactPerson: this.model.contactPerson,
contractType: this.model.contractType,
installationType: this.model.installationType,
interventionType: this.model.interventionType
}).then(() => location.reload())
} else {
this.addProject(json)
.then(response => {
if (response) {
this.$router.push({
name: 'BOMUpload',
params: { projectId: response.data.data.createProject.project.id }
})
}
})
}
},
validateFirstTab: function () {
if (!this.model.projectName) {
return alert('Il nome del progetto è obbligatorio')
}
return this.$refs.firstTabForm.validate();
},
validateSecondTab: function () {
return this.$refs.secondTabForm.validate();
},
newContactPersonCreation() {
this.$emit('new-contact-person-creation')
},
getAddressData: function (addressData, placeResultData) {
this.address = addressData;
this.model.address.country = addressData.country;
this.model.address.city = addressData.locality;
if (placeResultData.address_components[4].short_name == 'IT') {
this.model.address.province = placeResultData.address_components[2].short_name
} else if (placeResultData.address_components[4].short_name.length > 2) {
this.model.address.province = placeResultData.address_components[3].short_name
} else {
this.model.address.province = placeResultData.address_components[4].short_name
}
this.model.address.partialStreet = addressData.route;
this.model.address.streetNumber = addressData.street_number;
this.model.address.CAP = addressData.postal_code;
this.model.address.state = addressData.administrative_area_level_1;
},
getContacts() {
fetchContacts()
.then(response => {
this.contactPersons = response.map(contact => {
return { id: contact.node.id, name: contact.node.name }
})
this.model.contactPerson = this.contactPersons.slice(-2).pop().id
if (this.isModifying) {
this.model.contactPerson = this.currentProject().contactPerson.id
}
})
.catch(err => console.error('Riga 417 ProjectWizard.vue', err))
}
},
mounted() {
if (this.isModifying) {
this.model.projectName = this.currentProject().name
this.model.address.partialStreet = this.currentProject().address.address
this.model.address.streetNumber = this.currentProject().address.streetNumber
this.model.address.city = this.currentProject().address.city
this.model.address.province = this.currentProject().address.province
this.model.address.country = this.currentProject().address.country
this.model.address.CAP = this.currentProject().address.zipCode
this.model.description = this.currentProject().description
}
var newContact = document.querySelector("#new-contact-creation-project")
newContact.onclick = () => {
this.newContactPersonCreation()
};
// CONTRACT TYPES
this.fetchContractTypes()
.then(response => {
if (response) {
let processedContractTypes = []
this.contractTypes = this.allContractTypes()
this.contractTypes.forEach(contractType => {
let contractTypeObj = { id: contractType.node.id, name: contractType.node.name }
processedContractTypes.push(contractTypeObj)
})
this.contractTypes = processedContractTypes
if (this.isModifying){
this.model.contractType = this.currentProject().contractType.id
}
} else {
alert('Not working fetchContractTypes')
}
})
// INSTALLATION TYPES
this.fetchInstallationTypes()
.then(response => {
if (response) {
let processedInstallationTypes = []
this.installationTypes = this.allInstallationTypes()
this.installationTypes.forEach(installationType => {
let installationTypeObj = {
id: installationType.node.id,
name: installationType.node.name,
contractType: installationType.node.contractType.id
}
processedInstallationTypes.push(installationTypeObj)
})
this.installationTypes = processedInstallationTypes
if (this.isModifying){
this.model.installationType = this.currentProject().installationType.id
}
} else {
alert('Not working fetchInstallationTypes')
}
})
// INTERVENTION TYPES
this.fetchInterventionTypes()
.then(response => {
if (response) {
let processedInterventionTypes = []
this.interventionTypes = this.allInterventionTypes()
this.interventionTypes.forEach(interventionType => {
let interventionTypeObj = {
id: interventionType.node.id,
name: interventionType.node.name,
installationType: interventionType.node.installationType.id,
}
processedInterventionTypes.push(interventionTypeObj)
})
this.interventionTypes = processedInterventionTypes
if (this.isModifying){
this.model.interventionType = this.currentProject().interventionType.id
}
} else {
alert('Not working fetchInterventionTypes')
}
})
// CONTACT PERSONS
this.getContacts()
},
}
</script>
this is my jest configuration file:
module.exports = {
verbose: true,
roots: ["<rootDir>/src/", "<rootDir>/src/specs/"],
moduleFileExtensions: ['js', 'jsx', 'json', 'vue'],
moduleNameMapper: {
'^#/(.*)$': '<rootDir>/$1',
"~(.*)$": "<rootDir>/$1"
},
transform: {
"^.+\\.js$": "babel-jest",
'.+\\.(css|styl|less|sass|scss|png|jpg|ttf|woff|woff2|svg)$': 'jest-transform-stub',
"^.+\\.vue$": "vue-jest"
},
snapshotSerializers: [
"<rootDir>/node_modules/jest-serializer-vue"
],
transformIgnorePatterns: [
'<rootDir>/node_modules/(?!vue-google-autocomplete)',
'<rootDir>/(?!)'
]
}
and finally this is the code in the spec file:
import { mount } from '#vue/test-utils'
import Vue from 'vue'
import BootstrapVue from 'bootstrap-vue'
import Component from '#/src/components/builder/ProjectWizard'
Vue.use(BootstrapVue)
describe('ProjectWizard', () => {
it('should render a card for each project received from its parent', () => {
const wrapper = mount(Component)
console.log(wrapper)
})
})
I dont't understand why Jest isn't able to find those functions since the module's location is right.
I am writing a function to return an id based on a few various things aligning. The code mostly works except that because there is no break; for a forEach. I believe I need to use a different filter or find option on the array.
function getDefaultId(prod) {
var defaultId;
prod.images.forEach( function(image) {
defaultId = image.isPrimary ? image.id : undefined;
});
return defaultId;
}
var prod.images = [
0: {
isPrimary: false,
id: 1234
},
1: {
isPrimary: true,
id: 1235
},
2: {
isPrimary: false,
id: 1236
}
]
Essentially I'm trying to return the corresponding id for isPrimary. The result should be 1236 but I'm getting undefined because the forEach is not breaking and thus is resetting the variable to undefined on the next iteration.
You could use Array#some and exit early.
function getDefaultId(prod) {
var defaultId;
prod.images.some(function (image) {
if (image.isPrimary) {
defaultId = image.id;
return true;
}
});
return defaultId;
}
var prod = { images: [{ isPrimary: false, id: 1234 }, { isPrimary: true, id: 1235 }, { isPrimary: false, id: 1236 } ]};
console.log(getDefaultId(prod));
var images = [
{
isPrimary: false,
id: 1234
},
{
isPrimary: true,
id: 1235
},
{
isPrimary: false,
id: 1236
}
]
let result = images.filter(img => img.isPrimary === true)
console.log(result)
You could use .filter() and to get an array of objects which have isPrimary as true, and then return the id of the first item found like so:
function getDefaultId(prod) {
var primaryImg = prod.images.filter(function(img) {
return img.isPrimary;
});
return primaryImg[0].id;
}
var prod = {};
prod.images = [{isPrimary: false, id: 1234 }, {isPrimary: true, id: 1235}, {isPrimary: false, id: 1236}];
console.log(getDefaultId(prod));
Give it a try using map.
var images = [
{
isPrimary: false,
id: 1234
},
{
isPrimary: true,
id: 1235
},
{
isPrimary: false,
id: 1236
}
];
function getDefaultId() {
var defaultId;
images.map(function (image) {
if (image.isPrimary) {
defaultId = image.id;
}
});
return defaultId;
}
console.log(getDefaultId());
I have something like this :
let user = [
{
name: "step-one",
values: {companyName: "Name", address: "company address"}
},
{
name: "step-two",
values: {name: "User", mobile: 0123}
},
{
name: "step-three",
values: [
{file: "companyLogo", values: {active: true, fileName: "some name"}},
{file: "avatar", values: {active: true, fileName: "file name"}}
]
}
]
I want to get only values and put them into a new object. Thus, something like :
let wantedResult = {
companyName: "Name",
address: "company address",
name: "User",
mobile: 0123,
files: [
{file: "companyLogo", values: {active: false, fileName: "some name"}},
{file: "avatar", values: {active: false, fileName: "file name"}}
]
};
Any advice how I can do that?
You can try this!
let user = [{
name: "step-one",
values: {
companyName: "Name",
address: "company address"
}
}, {
name: "step-two",
values: {
name: "User",
mobile: 0123
}
}, {
name: "step-three",
values: [{
file: "companyLogo",
values: {
active: true,
fileName: "some name"
}
}, {
file: "avatar",
values: {
active: true,
fileName: "file name"
}
}]
}]
var wantedResult = Object.assign({}, user[0].values, user[1].values, {files: user[2].values})
console.log(wantedResult)
It is a bit hacky because of the files array, but i would do it like that:
var wantedResult = user.reduce((result, step) => {
var values = Array.isArray(step.values) ? { files: step.values } : step.values;
return Object.assign({}, result, values)
}, {});
Of course it'll work only for that kind of structure you provided. If you have more objects that have an array in the 'values' property, you'll need to rethink the approach.
Step 3 is inconsistent with the others. If possible, make it consistent to have: values: files: [ { file1_data }, { file2_data } ].
After fixing the inconsistency, you can iterate through each of the steps and add the new properties to the result.
let wantedResult = user.reduce(function(result, spec) {
Object.keys(spec.values).forEach(function(key) {
result[key] = spec.values[key];
});
return result;
}, {});
If not possible to change step 3, you can make it a bit less clean:
let wantedResult = user.reduce(function(result, spec) {
if (spec.name === "step-three") {
result.files = spec.values;
}
else {
Object.keys(spec.values).forEach(function(key) {
result[key] = spec.values[key];
});
}
return result;
}, {});