How do I use Jest and the Testing Library for unit testing in JavaScript?

I use Jest and dom testing library and I DON’T USE REACT.

Also I use webpack in my project. I keep on geting the same problem:

expect(element).toBeInTheDocument()
element could not be found in the document

How can I test if a button is in the document? And how can I correctly test the modules of the project if I use static HTML with no scripts? Should I manually add the scripts? I do it for the first time, please help me

My test file:

import { getByRole } from '@testing-library/dom';
import '@testing-library/jest-dom';
import '@testing-library/jest-dom/extend-expect';

function getExampleDOM() {
  const div = document.createElement('div');
  div.innerHTML = `
      <div class="screen">
        <h1 class="game__title">GAME 2048</h1>
        <button type="button" class="btn btn-start">Start</button>
      </div>
      <div class="screen">
        <h2 class="game__title">Choose board size</h2>
        <ul class="size-list">
          <li>
            <button type="button" class="btn btn-size" data-size="3">3 x 3</button>
          </li>
          <li>
            <button type="button" class="btn btn-size" data-size="4">4 x 4 (classic)</button>
          </li>
          <li>
            <button type="button" class="btn btn-size" data-size="5">5 x 5</button>
          </li>
        </ul>
      </div>
      <div class="game__wrapper">
        <h2 class="game__score-title">Your score:<span class="game__score">0</span></h2>
        <div class="game-board"></div>
      </div>
  `;
  return div;
}

describe('startGame', () => {
  test('renders all necessary elements', () => {
    const container = getExampleDOM();
    const startBtn = getByRole(container, 'button', { name: /start/i });
    expect(startBtn).toBeInTheDocument();
  });
});

my package.json:

{
  "name": "2048",
  "version": "1.0.0",
  "repository": {
    "url": "https://github.com/EkaterinaMuz/GAME2048.git"
  },
  "description": "",
  "scripts": {
    "test": "jest --w",
    "build": "webpack --mode development",
    "start": "webpack-dev-server --mode development --open",
    "predeploy": "npm run build",
    "deploy": "gh-pages -d dist"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/eslint-parser": "^7.21.8",
    "@babel/polyfill": "^7.12.1",
    "@babel/preset-env": "^7.21.5",
    "@testing-library/user-event": "^14.4.3",
    "babel-loader": "^9.1.2",
    "clean-webpack-plugin": "^4.0.0",
    "css-loader": "^6.7.4",
    "eslint": "^8.2.0",
    "eslint-config-airbnb-base": "^15.0.0",
    "eslint-config-prettier": "^8.8.0",
    "eslint-plugin-import": "^2.27.5",
    "eslint-plugin-jest-dom": "^4.0.3",
    "eslint-plugin-prettier": "^4.2.1",
    "eslint-plugin-testing-library": "^5.11.0",
    "eslint-webpack-plugin": "^4.0.1",
    "file-loader": "^6.2.0",
    "gh-pages": "^5.0.0",
    "html-webpack-plugin": "^5.5.1",
    "jest": "^29.5.0",
    "jest-webpack": "^0.5.1",
    "style-loader": "^3.3.3",
    "webpack": "^5.83.1",
    "webpack-cli": "^5.1.1",
    "webpack-dev-server": "^4.15.0"
  },
  "dependencies": {
    "@testing-library/jest-dom": "^5.16.5",
    "hammerjs": "^2.0.8",
    "jest-environment-jsdom": "^29.5.0"
  }
}

Also I added Jest config

const config = {
  testEnvironment: 'jsdom',
  testEnvironmentOptions: {
    html: '<html lang="zh-cmn-Hant"></html>',
    url: 'https://jestjs.io/',
    userAgent: 'Agent/007',
  },
};

module.exports = config;

And also I have webpack in the project:

const path = require('path');
const HTMLWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
// const ESLintPlugin = require('eslint-webpack-plugin');

module.exports = {
  mode: 'development',
  context: path.resolve(__dirname, 'src'),
  entry: ['@babel/polyfill', './scripts/index.js'],
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js',
    assetModuleFilename: 'assets/[name][ext][query]',
  },
  devServer: {
    port: 3000,
  },
  plugins: [
    new HTMLWebpackPlugin({
      template: './index.html',
    }),
    new CleanWebpackPlugin(),
    // new ESLintPlugin({
    //   fix: true,
    // }),
  ],
  module: {
    rules: [
      {
        test: /.css$/,
        use: ['style-loader', 'css-loader'],
      },
      // {
      //   test: /.(png|jpg)$/,
      //   type: 'asset/resource',
      // },
      {
        test: /.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env'],
          },
        },
      },
    ],
  },
};

////////////////////////////////////

can I use regex in proxy configuration in webpack devserver?

In my Angular 16 project, I utilize a proxy by defining it in the configuration file "proxyConfig": "src/proxy.conf.json":

   "serve": {
      "executor": "@angular-devkit/build-angular:dev-server",
      "configurations": {
        "production": {
          "browserTarget": "ng-app:build:production"
        },
        "development": {
          "browserTarget": "ng-app:build:development",
          "proxyConfig": "src/proxy.conf.json",
          "port": 4200
        }
      },
      "defaultConfiguration": "development"
    },

The proxy.conf.json file contains the following content:

{
  "/rest/api": {
    "target": "https://to-api.example.com",
    "secure": true,
    "changeOrigin": true,
    "logLevel": "debug"
  },
  "/client-a/rest/api": {
    "target": "https://to-api.example.com",
    "secure": true,
    "changeOrigin": true,
    "logLevel": "debug"
  },
  "/client-b/rest/api": {
    "target": "https://to-api.example.com",
    "secure": true,
    "changeOrigin": true,
    "logLevel": "debug"
  },
  ....

As you can see, I repeat the client-n key with the same data, and when I want to add a new client, I need to edit this file and add the entry.

Basically, they are the same pattern: <client-x>/rest/api so it is possible to do regex or a function that does something like this?

  "/(<regex that match any word here>)/rest/api": {
    "target": "https://to-api.example.com",
    "secure": true,
    "changeOrigin": true,
    "logLevel": "debug"
  },

while validating email form from jqueryvalidationlibrary it’s blocking because it’s integrated with database error message

I am facing an issue while validating form field in client side in asp.net core validation message is not working and also some error message coming from database but If you I am doing validation in HTML CSS and javascript it’s working fine.

Here, what I have done so far

<form class="ht_form" id="ht_form" action="" method="post">
                <div class="row ht_input-login">
                    <div class="col-12">
                        <div class="row mb-3 form-group">
                            <div class="col-sm-12 ht_form-control form-label">
                                <input type="email" name="email" id="email" class="form-control textbox-size"  value="@ValidEmail.Replace("@@", "@")"
                                       placeholder="Email ID" aria-describedby="emailError" autocomplete="off" required />
                            </div>
                        </div>
                       
                        <div class="row ht_sign-in">
                            <div class="col-sm-6 col-6">
                                <button type="submit" class=" btn text-white w-100 mb-3 ">Submit</button>
                            </div>
                        </div>

                      
                       



                    </div>
                </div>
            </form>
              @if (!IsvalidEmail)
                        {
                        
                                     <label class="row mb-3">
                                <p style="text-align:center;color:#a32035;margin-top:15px">
                                    Entered email id is not registered..
                                </p>
                            </label>
                                
                          
                        }

let me show validation done for this form

$.validator.addMethod(
    "regex",
    function (value, element, regexp) {
        if (regexp && regexp.constructor != RegExp) {
            regexp = new RegExp(regexp);
        }
        else if (regexp.global) regexp.lastIndex = 0;
        return this.optional(element) || regexp.test(value);
    }, "Please enter a valid email like [email protected]"
);

$().ready(function () {
    $("#ht_form").validate({
        rules: {
            email: {
                required: true,
                email: true,
                regex: /^b[A-Z0-9._%+-]+@[A-Z0-9.-]+.[A-Z]{2,4}b$/i
            },
        },
        messages: {
            email: {
                required: "Please enter email address",
            },
        },
        errorElement: 'span',
        errorPlacement: function (error, element) {
            error.addClass('invalid-feedback');
            element.closest('.form-group').append(error);
        },


    });
});

JS function completing without throwing error yet further code doesn’t execute

I am trying to prepare some data & I am returning correct data with no errors yet none of the further code executes. prepareBuyAndSellData completes, returns an object, & then nothing else happens, not even the hello console.log.

await prepareBuyAndSellData(buySellParam)
    .then((result) => {
        console.log('hello')
        console.log(result)
        buyTx(result.buyData, overloadsBuy)
        sellTx(result.sellData, overloadsSell)
        console.log("Buy & sell sent.")
    })
    .catch((error) => {
      console.log('Error:', error)
    })

I have tried logging everything, returning different data structure, catching any & all errors, etc.

How can I get data out of a nested axios.get call in JavaScript?

Thank you for looking at my question. I making two requests to complete a data fetch and I am trying to get the data returned from the inner axios call out of the function. Sorry for the begginerness of this question I just cant see what Im missing anymore.

Thank you!

`
let allArtic = [];

function articCall() {
return axios
.get(https://api.artic.edu/api/v1/artworks/search?q=${searchTerm})
.then((res) => {
res.data.data.map((entry) => {
axios
.get(
https://api.artic.edu/api/v1/artworks/${entry.id}?fields=id,title,image_id
)
.then((res) => {
const url = ${res.data.config.iiif_url}/${res.data.data.image_id}/full/843,/0/default.jpg;

          const artObj = {
            name: searchTerm,
            title: res.data.data.title,
            img: url,
          };

          allArtic.push(artObj);
          return allArtic;
        });
    });
  })
  .catch((error) => {
    console.log(error);
  });

}

console.log(“all”, allArtic);` => GET desired data

I have done a similar approach with a single axios call and it has worked. I tried to add the data in each iteration to an outside array but this has resulted in an empty array.

Content not visible in Google Search Console due to AJAX loading, impacting GTMatrix performance. How to solve this issue?

Content not visible in Google Search Console due to AJAX loading, impacting GTMatrix performance. How to solve this issue?

I have an ecommerce site built on Laravel, MySQL, JavaScript, jQuery, and Bootstrap. According to GTMatrix, the performance is at 89%. However, when inspecting the URL in Google Search Console, some content is not visible in the search results test.

I understand why the content is not visible in Google Search Console. It is because I initially use an AJAX call to load products for faster loading. To address this issue in Google Search Console, I can render the content directly in the blade file instead of using an AJAX call. However, this solution negatively affects the performance in GTMatrix, bringing it down to 60%.

While my site is still loading quickly, I need to make changes for it to be properly displayed in Google Search Results. How can I solve this problem?

Including anchor tag validation in HTML Validation logic

I’ve written a piece of code for my system that checks whether or not a string has proper opening (“<“) and closed (“>”) brackets for any HTML tag. For example, if the string looks like this:

<i>hello<i>

my logic throws an error because there is no proper closing tag (</i>) in the string.

I am trying to incorporate validation for any anchor tags in this as well. Currently, if there are any properly formatted anchor tags present in the string, my code throws an error. For example, if a string includes something like this:

"<a href=https://example.com>Website</a>"

my logic thinks that there should be a matching closing tag somewhere after the “< a href=,” but obviously that’s not how an anchor tag is structured. How can I incorporate this into my current logic for all anchor tags? Here is what I have right now, but this only works for simple HTML tags (ex: <b></b>, <i></i>, etc.):

var errMsg = "";
var message = "";
var text = "<a href=https://example.com>Website</a>"
var regex = /<[^>]+>/g;
var foundArr = text.match(regex);
var size = foundArr.length;
var reset = false;

for (var i = 0; i <= size; i++) {

    if (reset) {
        i = 0;
    }
    reset = false;
    var arr1 = foundArr[i] + "";

    if (arr1.indexOf("/>") >= 0) {

        foundArr.splice(foundArr.indexOf(arr1), 1);
        reset = true;
        continue;
    } else {
        var words = arr1.split('<');
        var x = '</' + words[1];

        for (var j = i + 1; j < foundArr.length; j++) {
            var arr2 = foundArr[j];
            if (x == arr2) {
                foundArr.splice(foundArr.indexOf(arr1), 1);
                foundArr.splice(foundArr.indexOf(arr2), 1);
                reset = true;
                break;
            }
        }
    }
    size = foundArr.length;
}
if (foundArr.length > 0) {
    message = "<li>" + "The text has invalid tags: " + foundArr.toString().replace(/</g, "").replace(/>/g, "") + " </li>";
}

console.log(message)

Multiline text when using multiple ternary operators in Template literals

I want to create multiline text using multiple ternary operators within a single Template literal.

const toolTipText = `${2 * 5 === 10 ? "The value is same" : ""}
  ${"a" === "b" ? "" : "Different letters"}`;

For example, in the code above, I want The value is same in one line & Different letters in the next line. However, they are both in the same line. I am basically trying to add lines on text based on conditions.

How to achieve it?

Order of form submission and fetchAPI communication [duplicate]

There is a part that combines form submission and fetchAPI communication with a certain onclick attribute.

The expected result is the value updated by fetchAPI communication after the form has been sent and the data has been registered in the database.

However, the fetchAPI actually fetches the data before the form submission updates the database.

How can I wait for the data to update on form submission?
Form submission → database update complete → fetchAPI → see updated data

For various reasons, submit cannot be processed asynchronously.

<form action="post" name="formTest">
  <button type="button" onclick="A(B)" id="test">test</button>
</form>

<script>
function A(B) {
  formTest.submit();
  B();
}

function B() {
  fetch("test.php",
      {
          method: "GET",
          headers: { "Content-Type": "application/json" }
      }
  )
      .then(function (response) {
          if (!response.ok) {
              throw new Error(response)
          }
          return response.json();
      })
      .then(function (data) {
          if (parseInt(data.check) === 1) {
              window.alert('success')
          }
      })
      .catch(function (error) {
          console.log(error);
      });
}
</script>

How to serialize SQL records into JavaScript objects given aliased properties

This isn’t much of a question, but more of a solution, as I have not been able to find anything out there on this topic.

I am building an ORM model in JavaScript, and the biggest issue I was having was serializing returned records into a format that a User would expect.

It’s easy to serialize objects that were queried from a single table, however, serializing records queried from joined tables makes it pretty difficult, as it is a single-depth object containing the results.

Take the following query result for example:

[
  {
      PlaylistId: 1,
      Name: 'Music',
      PlaylistTracks_PlaylistId: 1,
      PlaylistTracks_TrackId: 1,
      PlaylistTracks_Track_TrackId: 1,
      PlaylistTracks_Track_Name: 'For Those About To Rock (We Salute You)',
      PlaylistTracks_Track_AlbumId: 1,
      PlaylistTracks_Track_MediaTypeId: 1,
      PlaylistTracks_Track_GenreId: 1,
      PlaylistTracks_Track_Composer: 'Angus Young, Malcolm Young, Brian Johnson',
      PlaylistTracks_Track_Milliseconds: 343719,
      PlaylistTracks_Track_Bytes: 11170334,
      PlaylistTracks_Track_UnitPrice: '0.99'
    },
    {
      PlaylistId: 1,
      Name: 'Music',
      PlaylistTracks_PlaylistId: 1,
      PlaylistTracks_TrackId: 2,
      PlaylistTracks_Track_TrackId: 2,
      PlaylistTracks_Track_Name: 'Balls to the Wall',
      PlaylistTracks_Track_AlbumId: 2,
      PlaylistTracks_Track_MediaTypeId: 2,
      PlaylistTracks_Track_GenreId: 1,
      PlaylistTracks_Track_Composer: null,
      PlaylistTracks_Track_Milliseconds: 342562,
      PlaylistTracks_Track_Bytes: 5510424,
      PlaylistTracks_Track_UnitPrice: '0.99'
    },
    {
      PlaylistId: 1,
      Name: 'Music',
      PlaylistTracks_PlaylistId: 1,
      PlaylistTracks_TrackId: 3,
      PlaylistTracks_Track_TrackId: 3,
      PlaylistTracks_Track_Name: 'Fast As a Shark',
      PlaylistTracks_Track_AlbumId: 3,
      PlaylistTracks_Track_MediaTypeId: 2,
      PlaylistTracks_Track_GenreId: 1,
      PlaylistTracks_Track_Composer: 'F. Baltes, S. Kaufman, U. Dirkscneider & W. Hoffman',
      PlaylistTracks_Track_Milliseconds: 230619,
      PlaylistTracks_Track_Bytes: 3990994,
      PlaylistTracks_Track_UnitPrice: '0.99'
    },
]

Assuming you also have access to the keys that were joined on and information telling you about the type of relationship, (one-to-one or one-to-many)…

How would it be possible to serialize that into something like this?

[
  {
    "PlaylistId": 1,
    "Name": "Music",
    "PlaylistTracks": [
      {
        "PlaylistId": 1,
        "TrackId": 1,
        "Track": {
          "TrackId": 1,
          "Name": "For Those About To Rock (We Salute You)",
          "AlbumId": 1,
          "MediaTypeId": 1,
          "GenreId": 1,
          "Composer": "Angus Young, Malcolm Young, Brian Johnson",
          "Milliseconds": 343719,
          "Bytes": 11170334,
          "UnitPrice": "0.99"
        }
      },
      {
        "PlaylistId": 1,
        "TrackId": 2,
        "Track": {
          "TrackId": 2,
          "Name": "Balls to the Wall",
          "AlbumId": 2,
          "MediaTypeId": 2,
          "GenreId": 1,
          "Composer": null,
          "Milliseconds": 342562,
          "Bytes": 5510424,
          "UnitPrice": "0.99"
        }
      },
      {
        "PlaylistId": 1,
        "TrackId": 3,
        "Track": {
          "TrackId": 3,
          "Name": "Fast As a Shark",
          "AlbumId": 3,
          "MediaTypeId": 2,
          "GenreId": 1,
          "Composer": "F. Baltes, S. Kaufman, U. Dirkscneider & W. Hoffman",
          "Milliseconds": 230619,
          "Bytes": 3990994,
          "UnitPrice": "0.99"
        }
      },
   ...
]

That’s where it took me a while, working with random solutions. Eventually I got to something that felt like it worked, but edge cases were still there for weirdly configured related tables.

Finally, I approached a nice solution. Here it is

    /**
     * Recursively maps relating records into a single record.
     * @param {any[]} records All records returned from a SQL query.
     * @param {any} record Record that is being worked on (this is handled recursively)
     * @param {string} prepend String to prepend onto the key for the original record's value.
     * @returns {(record: any) => TTableModel} Function for use in a JavaScript `<Array>.map()` function for use on an array of the records filtered to only uniques by main primary key.
     */
    #map(records, record=records[0], prepend="") {
        return r => {
            /** @type {any} */
            const mapping = {};
            const processedTables = new Set();
            for(const key in record) {
                const [table] = key.split("_");
                if(processedTables.has(table)) continue;
                processedTables.add(table);
                if(table === key) {
                    mapping[key] = r[`${prepend}${key}`];
                } else {
                    const entries = Object.keys(record).map(k => k.startsWith(`${table}_`) ? [k.replace(`${table}_`, ""), {}] : [null, null]).filter(([k]) => k != null);
                    if (this.#state.relationships[table].type === "1:1") {
                        const map = this.#map(records, Object.fromEntries(entries), `${prepend}${table}_`);
                        mapping[table] = map(r);
                    } else {
                        const pKey = this.#state.relationships[table].primaryKey;
                        const fKey = this.#state.relationships[table].foreignKey;
                        const map = this.#map(records, Object.fromEntries(entries), `${prepend}${table}_`);
                        mapping[table] = records.filter(_r => r[pKey] === _r[`${prepend}${table}_${fKey}`]).map(map);
                    }
                }
            }
    
            return mapping;
        }
    }

    /**
     * Serializes a given array of records, `records`, into object notation that a User would expect.
     * @param {any[]} records Records to filter.
     * @returns {TTableModel[]}
     */
    #serialize(records) {
        if (records.length <= 0) return records;
        console.log({records});
        const map = this.#map(records);
        return this.#filterForUniqueRelatedRecords(records).map(map);
    }

    /**
     * Filters out duplicates of records that have the same primary key.
     * @param {any[]} records Records to filter.
     * @returns {any[]} A new array of records, where duplicates by primary key are filtered out. If no primary key is defined, then `records` is returned, untouched.
     */
    #filterForUniqueRelatedRecords(records) {
        const pKey = this.#getPrimaryKey();
        if(pKey === undefined) return records;
        const uniques = new Set();
        return records.filter(r => {
            if(uniques.has(r[pKey])) {
                return false;
            }
            uniques.add(r[pKey]);
            return true;
        });
    }

This solution was able to query from a local database and serialize 18 playlist records with a total of 8719 track records in a whopping 261ms (milliseconds)

For insight, I store table information in an object, #state.relationships where each value is an object that looks like this:

interface Relationship {
  thisTable: string;
  thatTable: string;
  primaryKey: string;
  foreignKey: string;
  type: "1:1"|"1:n";
  included: boolean,
  schema: {[key: string]: SchemaField};
};

I know there’s a lot of code that could be interfaced here to understand more, but the core part I was getting at was using this information to serialize records.

NextJS – Creating a dynamic navbar with a complicated hierarchy of pages

I am creating a NextJS 13 Typescript project with a complicated hierarchy of pages (pages have subpages, and subpages have subpages, etc). I am trying to create a dynamically updating navbar component as I feel like it would be easier to update in the future instead of trying to manually going through the code and adding another subpage.

I have been experimenting in vanilla javascript with arrays like:

const pageHierarchy = 
[
    ["page 1", ["sub-page 1", "sub-page 2", "sub-page 3"], 
    ["page 2", ["sub-page 1", "sub-page 2", "sub-page 3", ["sub-sub-page 1", "sub-sub-page 2"] "subpage4"]], 
    ["page 3"]
]

and using the following code to destruct each array into their individual element:

function printArrayItems(arr) {
    arr.forEach(item => {
        if (Array.isArray(item)) {
            printArrayItems(item);
        } else {
            console.log(item);
        }
    });
}

which would give the following output:

"page 1"
"sub-page 1"
"sub-page 2"
"sub-page 3"
"page 2"
"sub-page 1"
"sub-page 2"
"sub-page 3"
"sub-sub-page 1"
"sub-sub-page 2"
"subpage4"
"page 3"

How would I modify this code to keep track of the page above the each sub-page in the hierarchy of pages?

Also, please tell me if this is a stupid way of going about creating a complicated navbar. Potentially using dynamic routing, etc. This is my first “major” NextJS project.

Thanks,

How can I embed JSX within a string in React native? [duplicate]

I’m creating a simple app that helps learners to memorize words.
In the app, I have phrases.
In a phrase of them, of course there are words.
If a user tap a word, my app will navigate to another screen where you see something like the definition.
But first, I just want to make it touchable. And also I want to use props.
So, I thought it’d be a good idea to use JSX there.
But I tried, but that didn’t work.

Here’s my code:

import { StatusBar } from "expo-status-bar";
import { StyleSheet, Text, View } from "react-native";

export default function App() {
  const phrases = [
    {
      id: 1,
      phrase: `You can tap this BUTTON!`,
    },
  ];

  return (
    <View style={styles.container}>
      <Text style={styles.text}>{phrases[0].phrase}</Text>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#fff",
    alignItems: "center",
    justifyContent: "center",
  },
  text: {
    fontSize: 30,
  },
});

Here, I want to make the BUTTON to be touchable.

Here is what I tried:

import { StatusBar } from "expo-status-bar";
import { StyleSheet, Text, TouchableOpacity, View } from "react-native";

export default function App() {
  const phrases = [
    {
      id: 1,
      phrase: `You can tap this ${(
        <TouchableOpacity>
          <Text>BUTTON</Text>
        </TouchableOpacity>
      )}!`,
    },
  ];

  return (
    <View style={styles.container}>
      <Text style={styles.text}>{phrases[0].phrase}</Text>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#fff",
    alignItems: "center",
    justifyContent: "center",
  },
  text: {
    fontSize: 30,
  },
});

However, it just shows [object Object] unfortunately.
How would you do something like this?
I actually have more than 1000 objects like this, so it’d be nice if there’s an efficiant way to achive this.

I’d appreciate it if you would give me some hint.

Thank you in advanse.

Merge data based on the key

I have this data:

[
  {
    "key": 111,
    "studentInfo": [
      {
        "details": {
          "calculated_fields": null,
          "status": false
        }
      }
    ]
  },
  {
    "key": 222,
    "studentInfo": [
      {
        "details": {
          "calculated_fields": null,
          "status": false
        }
      }
    ]
  },
  {
    "confidential": {
      "data": {
        "access_control": {
          "private_data": null,
          "users": []
        }
      },
      "key": 111
    }
  },
  {
    "confidential": {
      "data": {
        "access_control": {
          "private_data": null,
          "users": []
        }
      },
      "key": 222
    }
  }
]

Now I need to merge the data based on the key. For suppose if the objects contain the key”111″ all the related info should be displayed as one obj

Example output:

[
  {
    "key": 111,
    "studentInfo": [
      {
        "details": {
          "calculated_fields": null,
          "status": false
        }
      }
    ],
    "confidential": {
      "data": {
        "access_control": {
          "private_data": null,
          "users": []
        }
      },
      "key": 111
    }
  },
  {
    "key": 222,
    "studentInfo": [
      {
        "details": {
          "calculated_fields": null,
          "status": false
        }
      }
    ],
    "confidential": {
      "data": {
        "access_control": {
          "private_data": null,
          "users": []
        }
      },
      "key": 222
    }
  }
]