Jest mocks are not mocking: using `spyOn` or `jest.fn` to replace one method of a module

I’m having trouble testing a module of mine. One of the things I want to test is that calling one function in the module (using certain arguments) results in a call to another function in the module. For this testing, I do not want to test the actual results of the call to the second function. There are details that are beside the point & should be tested separately.

I’ve looked at the docs (incl. mocking partials, spyOn & mockImplementation), lots of github threads (incl this one) and there are actually examples that seem like they test exactly what I want to do. However, they haven’t worked and I’m not sure what the difference in my code is.

greet.js:

export const greetAPerson(person, recognized) {
    if (recognized) return greetByName(person);
    return askForName(person);
}

export const greetByName(person) {
    return `Hello ${person.name}`;
}

export const askForName(person) {
    // real code has implementation details that I don't want to test
    return 'Hello, what is your name?';
}

module.test.js

import * as greet from './greet';

describe('greetings', () => {
    afterAll(() => {
        jest.restoreAllMocks();
    });

    // passes
    test('returns greeting by name for known person', () => {
        const greeting = greet.greetAPerson({ name: 'Batman' }, true);
        expect(greeting).toBe('Hello Batman');
    });

    // passes
    test('greeting an un-regognized person returns request for their name', () => {
        const greeting = greet.greetAPerson({ name: '' }, false);
        expect(greeting).toBe('Hello, what is your name?');
    });

    // fails
    test('greeting an un-regognized person calls askForName (spyOn)', () => {
        const spiedAskForName = jest.spyOn(greet, 'askForName');
        greet.greetAPerson({ name: '' }, false);
        expect(spiedAskForName).toBeCalled();
    });

    // fails
    test('greeting an un-regognized person calls askForName (spyOn + mockImplmentation)', () => {
        const spiedAskForName = jest.spyOn(greet, 'askForName').mockImplementation(() => 'who are you?');
        greet.greetAPerson({ name: '' }, false);
        expect(spiedAskForName).toBeCalled();
    });

    // fails
    test('greeting an un-regognized person returns mocked value (spyOn + mockImplmentation)', () => {
        jest.spyOn(greet, 'askForName').mockImplementation(() => 'who are you?');
        const greeting = greet.greetAPerson({ name: '' }, false);
        expect(greeting).toBe('who are you?');
    });

    // fails
    test('greeting an un-regognized person calls askForName: jest.fn()', () => {
        greet.askForName = jest.fn();
        greet.greetAPerson({ name: '' }, false);
        expect(greet.askForName).toBeCalled();
    });

    // fails
    test('mock entire module, except most of it', () => {
        jest.mock('./greet', () => {
            const greet = jest.requireActual('./greet');
            return {
                __esModule: true,
                ...greet,
                askForName: jest.fn(() => 'who are you?')
            };
        });
        const greeting = greet.greetAPerson({ name: '' }, false);
        expect(greeting).toBe('who are you?');
    });
});

Any ideas what I’m doing wrong?

Why is my code not doubling every odd index?

I’m trying to write a version of Luhn’s algorithm, but why is my code not doubling every odd index here? It seems to be doubling a pattern of index’s but i dont understand how it’s got that pattern from my code.

    const validateCred = (array) => {
      let removeLast = array.pop();
      let reversed = array.reverse();
      console.log(reversed);
      for (let i = reversed[0]; i < reversed.length; i++)
      if (reversed[i] % 2 !== 0) {
        reversed[i] *= 2;
      }
      console.log(reversed)




[ 0, 8, 6, 1, 0, 8, 0, 9, 7, 7, 6, 9, 3, 5, 4 ]
[ 0, 8, 6, 2, 0, 8, 0, 18, 14, 14, 6, 18, 6, 10, 4 ]

As you can see it’s doubling some of the digits, but not the odd ones.

State Sync between components (Vanilla JS or Svelte)

I’m trying to create a basic example of an App in which there’s 2 components: A and B. The goal is to make each component dispatch an event when both conditions are fulfilled:

  • the component is mounted
  • the library they all depend on is loaded

1st attempt: a new LibraryLoader Class

https://svelte.dev/repl/ef7876d4fa8847d1ad1e13eb616b95fa?version=3.46.2

So I thought that I would need a simple class which would be able to dispatch a simple event (not tied to a DOM node). So I decided to create a LibraryLoader class that inherits from a Dispatcher class (to be able to dispatch an event not tied to a DOM node). Below is my attempt

The problem here is that we get 2 instances of the LibraryLoader class (created by A & B) so it’s not working. Maybe a static class which would inherit from the Dispatcher class ?(didn’t find how to to it).

2nd Attempt: LibraryLoader as an object literal

https://svelte.dev/repl/5c9873bb0c59493dbe6dd6ed38bde276?version=3.46.2

Reading some posts about the singleton pattern led me to the idea of transforming the LibraryLoader class into a simple object literal. And it’s working better here.

Components A and B are doing the same thing:

  1. once the component is mounted, it executes checkstate() which will either ask for the Library to load, or just wait if another component has already asked for this.

  2. once the library is mounted, it dispatches a “ready” event

Here it works pretty well. The library is not asked to be loaded twice and both A & B components are dispatching a “ready” event as expected. But there’s one obvious drawback: the code is duplicated in A & B.

3rd attempt: Svelte Action

https://svelte.dev/repl/3a68a7efaa8f43be8bffda12dadb83a3?version=3.46.2

This attempt makes use of svelte action which seemed to be a potential solution as far as I understood how it works.

So, I put the code in loadAndGetReady.js but in the end, component B never gets READY so there’s a catch here.

I’ll take any advice 😀

Thank you in advance

Function as property of another function ES5

I haven’t long written es5, so I forgot. Can you help how to fix this?

let mock = {
  DynamoDB: function() {
    {
        send: function() {console.log('sending...')}
    }
  },
};

then not working.

let client = new mock.DynamoDB();
client.send(); // does not write to console

Sequelize, Javascript TypeError: group.addTask is not a function

I have a Group.js, Task.js model and a db.js file. Group has many Tasks.

When I run the server I get the error TypeError: group.addTask is not a function.

Here are the files:

Task.js

const Sequelize = require("sequelize");

module.exports = function(sequelize,DataTypes){
    const Task = sequelize.define('Task',{
        name: Sequelize.STRING
    })
    return Task;
}

Group.js

const Sequelize = require("sequelize");

module.exports = function(sequelize,DataTypes){
    const Grupa = sequelize.define('Grupa',{
        naziv: Sequelize.STRING
    })
    return Grupa;
}

db.js

const Sequelize = require("sequelize");
const sequelize = new Sequelize("spiralatest","root","password",{host:"127.0.0.1",dialect:"mysql"});
const db = {};

db.Sequelize = Sequelize;
db.sequelize = sequelize;

db.task = require("./models/Task.js")(sequelize);
db.group = require("./models/Group.js")(sequelize);

db.group.hasMany(db.task);

module.exports=db;

And this is what I call from index.js which causes the error above:

const db = require('./db.js');

db.sequelize.sync({ force: true }).then(function () {
    initialize();
    console.log("Tables created and test data set-up");
});

function initialize() {
    db.task.findOrCreate({ where: { name: 'task1' } });
    db.group.findOrCreate({ where: { name: 'group1' } }).then(function (group) {
        db.task.findOne().then(function (x) {
            group.addTask(x);
        });
    });
}

Does anyone know what causes this error?

An easy way to have access to more than one html file, in an electron window?

I’m making a desktop app using electron. What I would like to do is change the colour of a number of different div components in my index.html file, after clicking on an icon in the bar.html file. Is there something that i can add to the browserWindows web preferences, that will allow me to have easy access to all the elements within the index.html file? At the moment i can only manipulate the appearance of the components in my bar.html file, which is no good for what i would like to accomplish.

Below is the code from my index.JS file.

ipcMain.on('state', (event, arg) => {
horizontalWindow(); 
event.returnValue = "toggle not ready test";
})

function horizontalWindow() 
{
sidebar = new BrowserWindow({height:80, width:2000, transparent:true, frame:false, titleBarStyle: 'none',  resizable: false, webPreferences: { nodeIntegration: true, 
contextIsolation: false, enableRemoteModule: true}})
sidebar.loadFile('bar.html')
sidebar.setPosition(0, 100, true)
//sidebar.setSize(1800, 80, true)
sidebar.setMenuBarVisibility(false)
sidebar.setAlwaysOnTop(true, 'floating') 

}

function createWindow(){
mainWindow = new BrowserWindow({ height: 10, width: 100, frame: false,titleBarStyle: 'none', parent:mainWindow, backgroundColor: '#283243', resizable: true, webPreferences: { nodeIntegration: true, 
  contextIsolation: false, enableRemoteModule: true }}) 

mainWindow.setAlwaysOnTop(true, 'normal') 
mainWindow.setVisibleOnAllWorkspaces(true);
mainWindow.loadFile('index.html')
mainWindow.setMenuBarVisibility(false)
mainWindow.setResizable(false)
mainWindow.moveTop()
mainWindow.setPosition(0,0)

}


app.on('ready', () => {
createWindow();

})
app.on('closed', () => {
win = null;
})
app.on('window-all-closed', () => {
app.quit();
})

Renderer.js file:

const State = document.getElementById('state')
State.addEventListener('click', function(){
ipcRenderer.sendSync("State")  
});

Any advice would be much appreciated!, as I’ve been stuck on this for a while now.

Remove autocomplete input fields

I have a form where I remade the bootstrap datepicker a little by inserting my fields with inputs, everything works as it should. The only problem is the autocomplete that is used in browsers, and when you click on the field, the values have already been entered appear, for whom it is not clear what I mean

enter image description here

Maybe I can somehow change the input type so that this autocomplete does not exist? Or how can I fix this problem? It is important that at the same time the date selection in the form remains working

// Initialize datepicker
const dp = $("#month").datepicker({ 
    todayHighlight: true
});

// Show datepicker on <input> click  
$('.input-wrapper > input').on('click', (e) => dp.datepicker("show"));

// On date change
const y  = document.getElementById('year');
const m  = document.getElementById('month');
const d  = document.getElementById('day');

dp.on('changeDate',function(ev){
    const date = dp.datepicker('getDate');
    y.value = date.getFullYear();
    d.value = date.getDate();
    dp.datepicker('hide');
    m.value = date.getMonth() + 1;
})

dp.on('hide',function(ev){
    const date = dp.datepicker('getDate');
    m.value = date.getMonth() + 1;
})
label {
      color: #808694;
      font-family: Montserrat;
      font-size: 10px;
      font-weight: bold;
      letter-spacing: 0;
      line-height: 16px;
      text-transform: uppercase;
}


    
input {
      margin-right: 20px;
      box-sizing: border-box;
      outline: none;
      border: none;
      background-color: #F4F5F8;
      width: 50px;
}

.span-wrapper {
        display: flex;
        align-items: flex-end;
      }
      
span {
        
        color: #808694;
        font-family: Montserrat;
        font-size: 8px;
        font-weight: bold;
        letter-spacing: 0;
        line-height: 16px;
        text-transform: uppercase;
        text-align: center;
        width: 50px;
}

.main-content {
  min-height: 10vh;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet" type="text/css" />
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.3.0/css/datepicker.css" rel="stylesheet" type="text/css" />
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.3.0/js/bootstrap-datepicker.js"></script>


<div class="main-content">
  <p>Main content...</p>
  <p>Main content...</p>
  <p>Main content...</p>
  <p>Main content...</p>
  <p>Main content...</p>
  <p>Main content...</p>
  <p>Main content...</p>
  <p>Main content...</p>
  <p>Main content...</p>
</div>

<div class="contacts-call-form">
    <form class="js-form" action="{{ route('send-comment') }}">
        <div class="col-md-6">
                <div class="call-form-item">
                    <label for="name">Name *</label>
                    <div class="input-wrapper">
                        <input class="js-form-call-name" id="name" type="text" name="name">
                    </div>
                </div>
            </div>
            <div class="col-md-6">
                <div class="call-form-item">
                    <label for="email">Email *</label>
                    <div class="input-wrapper">
                        <input class="js-form-call-email" id="email" type="email" name="email">
                    </div>
                </div>
            </div>
        <div class="col-md-6">
            <div class="call-form-item-date">
                <label for="date">Select a date *</label>
                <div class="input-wrapper">
                    <input class="js-form-month" id="month" type="text" name="month">
                    <input class="js-form-day" id="day" type="text" name="day">
                    <input class="js-form-year" id="year" type="text" name="year">
                    <div id="datepicker" class="input-group date" data-date-format="mm-dd-yyyy" style="display: none">
                        <input class="form-control" type="text" readonly />
                        <span class="input-group-addon"><i class="glyphicon glyphicon-calendar"></i></span>
                    </div>
                </div>
        <div class="span-wrapper">
          <span for="month">Month</span>
          <span for="day">Day</span>
          <span for="year">Year</span>
        </div>
            </div>
        </div>
    </form>
</div>

How to dynamically filter same array between multiple components in React

This is an example array of objects:

[ { "id": 1, "class": "Assault Infantry", "missions": 5, "shots": 28, "hits": 21, "kills": 22, "dead": true, }, { "id": 2, "class": "Field Medic", "missions": 5, "shots": 22, "hits": 17, "kills": 15, "dead": false, }, { "id": 3, "class": "Field Medic", "missions": 3, "shots": 15, "hits": 11, "kills": 8, "dead": true, }, { "id": 4, "class": "Skirmisher", "missions": 7, "shots": 38, "hits": 27, "kills": 25, "dead": false, }, { "id": 5, "class": "Phalanx", "missions": 2, "shots": 5, "hits": 3, "kills": 5, "dead": true, }, { "id": 6, "missions": 6, "shots": 50, "hits": 41, "kills": 31, "dead": false, }, { "id": 7, "class": "Rookie", "missions": 1, "shots": 2, "hits": 1, "kills": 1, "dead": true, },

I am trying to build a component, that parents several other components that receive this array from a parent, then filters the array and returns it to the parent. However, I want all of the child components use the same filtered array and then get the changed array.

This is the parent component:

const Navigation = ({soldiers, sortList}) => {

  const [fullyFiltered, setFullyFiltered] = useState([]);
  const [preFiltered, setPreFiltered] = useState(soldiers);

  const onSort = (data) => {
    setFullyFiltered(preFiltered);
  }

 const onDeadCheck = (data) => {
   setPreFiltered(data);
  }


  useEffect(() => {
    sortList(fullyFiltered);
  },[onDeadCheck, onSort])

  return (
      <div>
        <DeadSelector deadFiltered={onDeadCheck} soldiers={soldiers} />
        <NavigationSort forSort={onSort} soldiers={soldiers}/>
      </div>
  )
};

Then the two child components that filter array by different values.
This one filters the array by chosen value :

const NavigationSort = ({soldiers, forSort}) => {

    const [sortType, setSortType] = useState('kills');
  
    
    console.log(soldiers);

  useEffect(() => {
    const sortArray = type => {
      const types = {
        mvps: 'mvps',
        kills: 'kills',
        shots: 'shots',
        missions: 'missions',
      };


      const sortProperty = types[type];


        if(sortType === "accuracy") {
          const sorted = soldiers.sort((a, b) => (b.hits / b.shots * 100) - (a.hits / a.shots * 100));
          forSort(sorted);

        } else {
          const sorted = soldiers.sort((a, b) => b[sortProperty] - a[sortProperty]);
          forSort(sorted);
        }
    
    };
    sortArray(sortType);
     
  }, [sortType]); 

  return (
      <>
      <p>Sort by</p>
      <ul onClick={(e) => setSortType(e.target.getAttribute("data-id"))}>
            <li data-id="kills" value="kills">
                Kills
            </li>
            <li data-id="missions" value="missions">
                Missions
            </li>
            <li data-id="shots" value="shots">
                Shots
            </li>
            <li data-id="accuracy" value="accuracy">
                Accuracy
            </li>
        </ul>
      </>
  )
};

This one removes the instances that have value of “dead” set as true:

const DeadSelector = ({soldiers, deadFiltered}) => {

    const [isChecked, setIsChecked] = useState(false);


      useEffect(() => {
          let sorted = [];
            (isChecked ? sorted = soldiers.filter((user) => user.dead !== true) : sorted = soldiers);
            deadFiltered(sorted);
            
      },[isChecked])

      const handleOnChange = () => {
        setIsChecked(!isChecked);
      };

    return (
        <div className={classes.dead__checker}>
            <input onChange={handleOnChange} type="checkbox" id="isDead" name="isDead" checked={isChecked} />
            <label htmlFor="isDead">Hide Dead</label>
        </div>
    )
}

My problem is, I can’t figure out a way so that these two components “talk” to each other and do their function once the array is changed through the other child component. I was trying to have a state of preFiltered, where the shared array would be stored, instead what happens is that they change filter the array and return it, disregarding whether it was changed in the other component or not. Any help or at least pushing me to the right path would be much appreciated.

Async/await in Express.js POST handler

I am trying to call an async function in a POST handler.

The function I am trying to call is as follows (this code works):

const seaport = require("./seaport.js");

// This function creates a fixed price sell order (FPSO)
async function createFPSO(ownerAddress, contractAddress, tokenId, startAmount, expirationTime = 0) {
  const fixedPriceSellOrder = await seaport.createSellOrder({
    asset: {
      tokenId: tokenId,
      tokenAddress: contractAddress,
    },
    startAmount: startAmount,
    expirationTime: expirationTime,
    accountAddress: ownerAddress,
  });
  console.log(`Successfully created a fixed-price sell order! ${fixedPriceSellOrder.asset.openseaLink}n`);
}

createFPSO(MY_ADDRESS, NFT_CONTRACT_ADDRESS, "2", 0.01);

Since the code above works, I now try to transfer it to a POST handler, as follows:

const express = require('express');
const app = express();
app.use(express.json());
const seaport = require("./seaport.js");

app.post('/create/fixedprice', async (req, res, next)=> {
  try {
    const fixedPriceSellOrder = await seaport.createSellOrder({
      asset: {
        tokenId: req.body.tokenId,
        tokenAddress: req.body.contractAddress,
      },
      startAmount: req.body.startAmount,
      expirationTime: req.body.expirationTime,
      accountAddress: req.body.ownerAddress,
    });
    console.log(`Successfully created a fixed-price sell order! ${fixedPriceSellOrder.asset.openseaLink}n`);
    res.send(fixedPriceSellOrder);
  } catch (error) {
    return next(error);
  }
});

const port = process.env.PORT || 13579;
app.listen(port, () => console.log(`Service is listening on port ${port}..`));

However, this results in an error (I doubt the error message is relevant, but sharing it nonetheless):

Error: No wallet address found
    at Object.validateAndFormatWalletAddress (/root/opensea/opensea-creatures/node_modules/opensea-js/src/utils/utils.ts:928:11)
    at OpenSeaPort.<anonymous> (/root/opensea/opensea-creatures/node_modules/opensea-js/src/seaport.ts:1994:22)
    at step (/root/opensea/opensea-creatures/node_modules/opensea-js/lib/seaport.js:40:23)
    at Object.next (/root/opensea/opensea-creatures/node_modules/opensea-js/lib/seaport.js:21:53)
    at /root/opensea/opensea-creatures/node_modules/opensea-js/lib/seaport.js:15:71
    at new Promise (<anonymous>)
    at __awaiter (/root/opensea/opensea-creatures/node_modules/opensea-js/lib/seaport.js:11:12)
    at OpenSeaPort._makeSellOrder (/root/opensea/opensea-creatures/node_modules/opensea-js/lib/seaport.js:2038:16)
    at OpenSeaPort.<anonymous> (/root/opensea/opensea-creatures/node_modules/opensea-js/src/seaport.ts:625:30)
    at step (/root/opensea/opensea-creatures/node_modules/opensea-js/lib/seaport.js:40:23)
    at Object.next (/root/opensea/opensea-creatures/node_modules/opensea-js/lib/seaport.js:21:53)
    at /root/opensea/opensea-creatures/node_modules/opensea-js/lib/seaport.js:15:71
    at new Promise (<anonymous>)
    at __awaiter (/root/opensea/opensea-creatures/node_modules/opensea-js/lib/seaport.js:11:12)
    at OpenSeaPort.createSellOrder (/root/opensea/opensea-creatures/node_modules/opensea-js/lib/seaport.js:604:16)
    at /root/opensea/opensea-creatures/scripts/service.js:58:47

The point I am making is, the same functionality that is working in the first listing now breaks down when I transfer it to the POST handler, so I doubt it has anything to do with the OpenSea SDK being broken.

Row Grouping showing empty row with Ag-grid

So I’m using React and JS and have ag-grid table with 5 different rows, everything is working good.
But, when I’m try to have row grouping and I add RowGroupModule to my Modules and rowGroup:true and hide:true to any of my rows, it adds new row, but it completely empty (every other row is showing fine), and it doesn’t show any grouping.

Also, on the ag-grid YouTube channel with the grouping tutorial (https://m.youtube.com/watch?v=gzqjP_kF4NI), someone in the comments asked the same question, and ag-grid replied that this is enterprise feature. But I have this enterprise and license key for that, so not sure why this is not working, also I have 23.2.1 version.

Do you guys know what could be the issue? Thank you!

Vue JS / Vue Router – v-list-group active class not working properly when url contains more than one level?

I’m coming across an interesting problem.

I have a menu…

<!-- Performance Management-->
                    <v-list-group
                        prepend-icon="mdi-account-group"
                        class="nav-item-hover"
                        group="/performance-management"
                        v-if="checkPermission(['pm_is_line_manager', 'pm_is_line_managed', 'pm_whole_school_oversight'])"
                    >

                        <template v-slot:activator>
                            <v-icon slot="prependIcon" large color="primary"></v-icon>
                            <v-list-item-title>Performance</v-list-item-title>
                        </template>

                        <router-link tag="v-list-item" link to="/performance-management/whole-school" class="ml-5" v-if="checkPermission('pm_whole_school_oversight')">
                            <v-list-item-icon>
                                <v-icon>mdi-domain</v-icon>
                            </v-list-item-icon>
                            <v-list-item-title>Whole School</v-list-item-title>
                        </router-link>

                        <router-link tag="v-list-item" link to="/performance-management/my-staff" class="ml-5" v-if="checkPermission('pm_is_line_manager')">
                            <v-list-item-icon>
                                <v-icon>mdi-account-multiple</v-icon>
                            </v-list-item-icon>
                            <v-list-item-title>My Staff</v-list-item-title>
                        </router-link>

                    </v-list-group>

                    <!-- Administration-->
                    <v-list-item class="header-nav-custom mt-4">
                        <v-list-item-icon>
                            <v-icon>mdi-cog</v-icon>
                        </v-list-item-icon>
                        <v-list-item-title>Administration</v-list-item-title>
                    </v-list-item>

                    <!-- User Management-->
                    <v-list-group
                        prepend-icon="mdi-account-cog"
                        class="nav-item-hover"
                        group="/users"
                        v-if="checkPermission('users_view')"
                    >

                        <template v-slot:activator>
                            <v-icon slot="prependIcon" large color="primary"></v-icon>
                            <v-list-item-title>Users</v-list-item-title>
                        </template>

                        <router-link tag="v-list-item" link to="/users/add" class="ml-5" v-if="checkPermission('users_add')">
                            <v-list-item-icon>
                                <v-icon>mdi-account-plus</v-icon>
                            </v-list-item-icon>
                            <v-list-item-title>Add User</v-list-item-title>
                        </router-link>

                        <router-link tag="v-list-item" link to="/users" :class="[$route.path.includes('/users/profile') ? 'router-link-exact-active' : 'no-active-class']" class="ml-5" v-if="checkPermission('users_view')">
                            <v-list-item-icon>
                                <v-icon>mdi-account-details</v-icon>
                            </v-list-item-icon>
                            <v-list-item-title>Manage Users</v-list-item-title>
                        </router-link>

                        <router-link tag="v-list-item" link to="/users/permissions" class="ml-5" v-if="checkPermission('users_permissions')">
                            <v-list-item-icon>
                                <v-icon>mdi-lock-open-check</v-icon>
                            </v-list-item-icon>
                            <v-list-item-title>Bulk Permissions</v-list-item-title>
                        </router-link>

                    </v-list-group>

                    <!-- Performance Management Settings-->
                    <v-list-group
                        prepend-icon="mdi-account-wrench"
                        class="nav-item-hover"
                        group="/settings/performance-management"
                        v-if="checkPermission('users_view')"
                    >

                        <template v-slot:activator>
                            <v-icon slot="prependIcon" large color="primary"></v-icon>
                            <v-list-item-title>Performance</v-list-item-title>
                        </template>

                        <router-link tag="v-list-item" link to="/settings/performance-management" class="ml-5" v-if="checkPermission('super_admin')">
                            <v-list-item-icon>
                                <v-icon>mdi-file-document-multiple</v-icon>
                            </v-list-item-icon>
                            <v-list-item-title>Manage Sets</v-list-item-title>
                        </router-link>

                    </v-list-group>

                    <router-link tag="v-list-item" link to="/settings/cycles" class="ml-5 nav-single-item" v-if="checkPermission('super_admin')">
                        <v-list-item-icon>
                            <v-icon>mdi-clock-time-four</v-icon>
                        </v-list-item-icon>
                        <v-list-item-title>Cycles</v-list-item-title>
                    </router-link>

                </v-list>

The sub menus are remaining open properly for both “/users” and “/performance-management” as shown below:

This is an image
This is an image

However, when I click a sub-menu item for “/settings/performance-management” it opens up the sub-menu for “/performance-management” as shown below:

This is an image

However, strangely, when I refresh the page it displays correctly:

This is an image

Am I missing something silly here? Logically, in my head at least, this should be working fine?

Build a website with map and gis information

I would like to build a website that will have a page with a map.
In that map I would like to dynamic add points with coordinates and lines between them.
I am a .NET developer and I am familiar with Javacript.
What is the right way to go?

With a little search I found arcGIS API for Javascript but it seems that it is not free.
Any ideas and suggestions on better or more appropriate solutions?

jQuery selector fails when ID contains square brackets

I have a php script that creates a number of inputs whose ID’s are in an array. I am trying to check the value in the clicked one but it fails due to the selector being an array, I think. The code I’m using is below. The amt var is undefined. If I change the code to not use arrays, it works. Is there a way to access an ID that is an array element? Here is my jsfiddle.

$(".map-price").keyup(function(event) {
  var id = event.target.id;
  var amt = $("#" + id).val();
  console.log(id + ' ' + amt);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div>
  <input type="input" name="map_price[1]" id="products_map_price[1]" class="map-price">
</div>
<div>
  <input type="input" name="map_price[2]" id="products_map_price[2]" class="map-price">
</div>