Getting “Jest did not exit one second after the test run has completed” error for test script which was originally passing

I’m getting Jest did not exit one second after the test run has completed. error in my test scripts which were working before I added the port settings to app.js which were in www before. Now I can’t figure out what’s wrong but when I run npm test 4 out of 8 scripts pass and others get a port already in use error. When I try to run the failing scripts individually getting the above error. Following are my app.js and one of the failing yet earlier passed scripts.

`var express = module.exports = require(“express”);
const path = require(“path”);
var cookieParser = require(“cookie-parser”);
const http = require(“http”);
const socketIo = require(“socket.io”);
var debug = require(‘debug’)(‘tutormeister-app:server’);

var app = express();
const session = require(“express-session”);

Create HTTP server using Express app
const server = http.createServer(app);

Pass the server object to Socket.IO
const io = socketIo(server);

Set up Socket.IO in your app
app.set(“io”, io);

const socketsConnected = new Set();

io.on(‘connection’, (socket) => {
socketsConnected.add(socket.id);
io.emit(‘clients-total’, socketsConnected.size);

socket.on(‘disconnect’, () => {
socketsConnected.delete(socket.id);
io.emit(‘clients-total’, socketsConnected.size);
});

socket.on(‘message’, (data) => {
socket.broadcast.emit(‘chat-message’, data);
});

socket.on(‘feedback’, (data) => {
socket.broadcast.emit(‘feedback’, data);
});
});

var loginRouter = require(“./routes/login_router”);
var signupRouter = require(“./routes/signup_router”);
var createCourseRouter = require(“./routes/create_course_router”);
var insHomeRouter = require(“./routes/ins_home_router”);
var insViewCourseRouter = require(“./routes/ins_view_course_router”);
var accountEditRouter = require(“./routes/account_edit_router”);
var stuHomeRouter = require(“./routes/stu_home_router”);
var insStudentViewRouter = require(“./routes/ins_student_view_router”);
var studentMyCourseRouter = require(“./routes/studentMyCourse_router”);
var existingStudentCourseRouter = require(“./routes/existing_student_course_router”);
var stuCourseHomeRouter = require(“./routes/stu_course_home_router”);
var acceptStudentRouter = require(“./routes/accept_student_router”);
var communityRouter = require(“./routes/community_router”);

app.set(“views”, path.join(__dirname, “views”));
app.set(“view engine”, “ejs”);

app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, “public”)));

app.use(
session({
secret: “your-secret-key”,
resave: false,
saveUninitialized: false,
cookie: { maxAge: 3600000 },
})
);

app.use((req, res, next) => {
Helper function to determine active status
res.locals.active = (path) => (req.path === path ? “active” : “”);
next();
});

app.use((req, res, next) => {
const isLoginPage = req.path === “/login”;
const isLoginPage2 = req.path === “/”;
const isInstructorSignupPage = req.path === “/instructor-register”;
const isStudentSignupPage = req.path === “/student-register”;

const isLoggedIn = req.session && req.session.instructorId;

if (
(isLoginPage ||
isLoginPage2 ||
isInstructorSignupPage ||
isStudentSignupPage) &&
isLoggedIn
) {
Destroy the session only if the user is already logged in and accessing /login, /instructor-register, or /student-register
req.session.destroy((err) => {
if (err) {
console.error(“Error destroying session:”, err);
}
Redirect to the respective page after destroying the session
if (isLoginPage) {
res.redirect(“/login”);
else if (isInstructorSignupPage) {
res.redirect(“/instructor-register”);
else {
res.redirect(“/student-register”);
}
});
else {
Continue to the next middleware or route handler
next();
}
});

app.get(“/”, loginRouter);
app.post(“/”, loginRouter);

app.get(“/health”, loginRouter);

app.get(“/login”, loginRouter);
app.post(“/login”, loginRouter);

app.get(“/logout”, loginRouter);

app.get(“/instructor-register”, signupRouter);
app.post(“/instructor-register”, signupRouter);

app.get(“/student-register”, signupRouter);
app.post(“/student-register”, signupRouter);

app.get(“/create-course”, createCourseRouter);
app.post(“/create-course”, createCourseRouter);

app.get(“/instructor-home”, insHomeRouter);
app.post(“/instructor-home”, insHomeRouter);

app.get(“/instructor-account-edit”, accountEditRouter);
app.post(“/instructor-account-edit”, accountEditRouter);

app.get(“/student-account-edit”, accountEditRouter);
app.post(“/student-account-edit”, accountEditRouter);

app.get(“/viewCourse”, insViewCourseRouter);

app.get(“/student-home”, stuHomeRouter);
app.post(“/student-home”, stuHomeRouter);

app.get(“/studentMyCourse”, studentMyCourseRouter);
app.post(“/studentMyCourse”,studentMyCourseRouter);

app.get(“/existingStudentCourse”, existingStudentCourseRouter);
app.post(“/existingStudentCourse”,existingStudentCourseRouter);

app.get(“/instructor-student-view”, insStudentViewRouter);
app.post(“/instructor-student-view”, insStudentViewRouter);

app.get(“/student-course-home”, stuCourseHomeRouter);
app.post(“/student-course-home”, stuCourseHomeRouter);

app.get(“/acceptStudent”, acceptStudentRouter);
app.post(“/acceptStudent”, acceptStudentRouter);
app.post(“/rejectStudent”, acceptStudentRouter);

app.get(“/chat”, communityRouter);

app.set(‘port’, normalizePort(5000));

/**
Normalize a port into a number, string, or false.
*/

function normalizePort(val) {
var port = parseInt(val, 10);

if (isNaN(port)) {
named pipe
return val;
}

if (port >= 0) {
port number
return port;
}

return false;
}

/**
Event listener for HTTP server “error” event.
*/

function onError(error) {
if (error.syscall !== ‘listen’) {
throw error;
}
var port = normalizePort(app.get(‘port’));
var bind = typeof port === ‘string’
? ‘Pipe ‘ + port
: ‘Port ‘ + port;

handle specific listen errors with friendly messages
switch (error.code) {
case ‘EACCES’:
console.error(bind + ‘ requires elevated privileges’);
process.exit(1);
break;
case ‘EADDRINUSE’:
console.error(bind + ‘ is already in use’);
process.exit(1);
break;
default:
throw error;
}
}

/**
Event listener for HTTP server “listening” event.
*/

function onListening() {
var addr = server.address();
var bind = typeof addr === ‘string’
? ‘pipe ‘ + addr
: ‘port ‘ + addr.port;
debug(‘Listening on ‘ + bind);
}

/**
Start the HTTP server.
*/

server.listen(app.get(‘port’), “0.0.0.0”);
server.on(‘error’, onError);
server.on(‘listening’, onListening);

`
Create Course Test Script

`const supertest = require(‘supertest’);
const app = require(‘../app’);

Mocking the database connection
jest.mock(‘../common/database’);
const db = require(‘../common/database’);
const createCourseQuery = require(‘../querymanager/createCourseQuery’);
const createCourseController = require(‘../backend/create_course_controller’);
const { validationResult } = require(‘express-validator’);

describe(‘Create Course Controller’, () => {
test(‘createCourse should render “createCourse” view’, async () => {
const mockSession = {
instructorId: 1,
};
const mockReq = { session: mockSession };
const mockRes = {
render: jest.fn(),
redirect: jest.fn(),
};

await createCourseController.createCourse(mockReq, mockRes);

expect(mockRes.render).toHaveBeenCalledWith(‘createCourse’);
});

test(‘createCoursePost should redirect to “/instructor-home” on successful course creation’, async () => {
const mockSession = {
instructorId: 1,
};
const mockConnection = {
connect: jest.fn(),
query: jest.fn().mockImplementation((query, values, callback) => {
callback(null, { insertId: 1 }); // Mocking successful course insertion
}),
end: jest.fn(),
};

db.getMySQLConnection.mockReturnValueOnce(mockConnection);
jest.mock(‘express-validator’, () => ({
…jest.requireActual(‘express-validator’),
validationResult: jest.fn(() => ({ isEmpty: true })),
}));

const mockReq = {
session: mockSession,
body: {
courseName: ‘Math 101’,
subject: ‘Mathematics’,
eduLevel: ‘High School’,
level: ‘Intermediate’,
teachingStyle: ‘Interactive’,
teachingFormat: ‘Online’,
teachingMode: ‘Live’,
video: ‘https://example.com/math101’,
description: ‘Introduction to mathematics.’,
},
};
const mockRes = {
redirect: jest.fn(),
render: jest.fn(),
send: jest.fn(),
};

await createCourseController.createCoursePost(mockReq, mockRes);

expect(mockConnection.connect).toHaveBeenCalled();
expect(mockConnection.query).toHaveBeenCalledWith(
createCourseQuery.ADD_COURSE,
[
‘Math 101’,
‘Mathematics’,
‘High School’,
‘Intermediate’,
‘Interactive’,
‘Online’,
‘Live’,
‘https://example.com/math101’,
1, // instructorId
‘Introduction to mathematics.’,
],
expect.any(Function)
);
expect(mockRes.redirect).toHaveBeenCalledWith(‘/instructor-home’);
expect(mockReq.session.courseId).toBe(1);
expect(mockConnection.end).toHaveBeenCalled();
});

});

I tried –force-exit and –detectOpenHandles but nothing worked.

How to modify object parsed from a sample JSON body then use that object to append properly in JSON builder?

While trying to parse the sample JSON body and modify that object according to my preference, I’m having trouble appending it to the existing JSON body that it came from initially. The problem is that when I append it the previous object in array also changed according to the newest object that I modified.

I have tried multiple ways to append it to the existing body and trying to modify a copy of the object but ultimately results in the same problem. I think I’m missing something important and I’m quite new in JS/Groovy Script

Col fromCurr 
row 1 = EUR
row 2 = CAD
int rows = rateCurrencyList.getRowNumbers() /* not being used yet to iterate to all records */
def saveDiffRateSetJsonBody = '''[
    {
        "fromcurrency": "EUR",
        "invConvRate": "1.09",
        "convRate": "1",
        "sourceCode": "MANUAL",
        "tocurrency": "USD",
    }
]'''

def jsonData = (new JsonSlurper()).parseText(saveDiffRateSetJsonBody)
def newRate = jsonData[0]
                
for(int i = 0; i < 2 ; i++) {

    newRate.fromcurrency = rateCurrencyList.getValue("fromCurr", i + 1) /* COL NAME, ROW */
    newRate.toCurrency = "USD"
    newRate.invConvRate = 1.09
    newRate.convRate = 1
    newRate.sourceCode = "MANUAL"
    newRate.exchangeRateSetCd = "TDM_USD_RATE_SET"
    
    jsonData[i] = newRate
}

saveDiffRateSetJsonBody = (new JsonBuilder(jsonData)).toPrettyString()

println saveDiffRateSetJsonBody

Result is:

[
    {
        "fromcurrency": "CAD",
        "invConvRate": 1.09,
        "convRate": 1,
        "sourceCode": "MANUAL",
        "tocurrency": "USD",
    },
    {
        "fromcurrency": "CAD",
        "invConvRate": 1.09,
        "convRate": 1,
        "sourceCode": "MANUAL",
        "tocurrency": "USD",
    }
]

I’m expecting:

[
    {
        "fromcurrency": "EUR",
        "invConvRate": 1.09,
        "convRate": 1,
        "sourceCode": "MANUAL",
        "tocurrency": "USD",
    },
    {
        "fromcurrency": "CAD",
        "invConvRate": 1.09,
        "convRate": 1,
        "sourceCode": "MANUAL",
        "tocurrency": "USD",
    }
]

I can do this multiple more object and all the object parameters will be the same. I will add that I will be doing this to more complex Json body with multiple arrays, parameters and objects but I wanted to pick a specific array/object/parameter and modify it accordingly. So basically, I will have a source body for a default parameter and use that to create a new JSON body to use for the new request.

Uncaught ReferenceError: sendMessage is not defined at HTMLDocument.

Basically I was developing a chatApp using ws module and facing some issue on the frontend side regarding the the code not able to get a function in its scope.
Index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Real-Time Chat</title>
  <link rel="stylesheet" href="styles.css">
</head>
<body>
  <div class="container">
    <div id="chat-window" class="chat-box"></div>
    <div class="input-container">
      <input type="text" id="message-input" placeholder="Type your message...">
      <!-- Corrected onclick syntax -->
      <button id="send-btn">Send</button>
    </div>
  </div>
  <!-- Include client.js script -->
  <script src="client.js"></script>
  <script>
    document.addEventListener('DOMContentLoaded', () => {
      const sendButton = document.getElementById('send-btn');
      // Corrected event listener registration without invoking the function
      sendButton.addEventListener('click', sendMessage);
    });
  </script>
</body>
</html>

this is the html code I am using on the frontend
style.css

body {
    font-family: Arial, sans-serif;
    background-color: #fffdd0; /* Light yellow background */
    margin: 0;
    display: flex;
    justify-content: center; /* Aligns content horizontally */
    align-items: center; /* Aligns content vertically */
    height: 100vh; /* Full viewport height */
  }
  
  .container {
    max-width: 600px;
    width: 100%;
    background-color: #fff;
    border-radius: 10px;
    box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.1);
    padding: 20px;
  }
  
  .chat-box {
    height: 300px;
    overflow-y: scroll;
    border: 1px solid #ccc;
    padding: 10px;
    margin-bottom: 10px;
  }
  
  .input-container {
    display: flex;
  }
  
  #message-input {
    flex: 1; /* Takes remaining space */
    padding: 10px;
    border-radius: 5px;
    border: 1px solid #ccc;
    margin-right: 10px;
  }
  
  button {
    padding: 10px;
    border-radius: 5px;
    border: none;
    background-color: #007bff; /* Blue button color */
    color: #fff;
    cursor: pointer;
  }
  
  /* Message bubble styling */
  .message-bubble {
    background-color: #007bff;
    color: #fff;
    border-radius: 10px;
    padding: 10px;
    margin-bottom: 5px;
    max-width: 80%;
    word-wrap: break-word;
  }
  
  .message-container {
    display: flex;
    justify-content: flex-end; /* Aligns sent messages to the right */
  }

this is styles.css code which is used with html code for better view.
client.js

// client.js
document.addEventListener('DOMContentLoaded', () => {
  const chatWindow = document.getElementById('chat-window');
  const messageInput = document.getElementById('message-input');
  const ws = new WebSocket('ws://localhost:3000');

  // Event handler for incoming messages
  ws.onmessage = event => {
    const messageData = JSON.parse(event.data);
    const { message, sender } = messageData;

    if (sender !== 'self') {
      appendMessage(message);
    }
  };

  // Function to send a message
  function sendMessage() {
    const message = messageInput.value.trim();
    if (message !== '') {
      ws.send(JSON.stringify({ message }));
      messageInput.value = '';
    }
  }

  // Function to append a message to the chat window
  function appendMessage(message) {
    const messageElement = document.createElement('div');
    messageElement.textContent = message;
    messageElement.classList.add('message-bubble');
    chatWindow.appendChild(messageElement);
    chatWindow.scrollTop = chatWindow.scrollHeight;
  }
});

These were all components of the frontend and the error it is giving as soon as we click the send button is
Uncaught ReferenceError: sendMessage is not defined at HTMLDocument.<anonymous> ((index):24:44)

How do I select a value using the slide bar?

Can someone please help me with this project I am working on? I want to select either one of the two divs (KgDiv, LDiv) by clicking it, then use the slide bar to select a value between 0 and the maximum value of the Kilograms/ Liters paragraph, then use the Sell button to convert Kg or L to € at a rate of 1 to 1. Also the quantity (kg or l) selected using the slide var should be displayed next to the slide bar.

<div id="KgDiv">
<p id="Kilograms">Kilograms</p>
<input type="button" onClick="AddKg()" value="+400Kg"></input>
</div>
<div id="LDiv">
<p id="Liters">Liters</p>
<input type="button" onClick="AddL()" value="+340L"></input>
</div>

<input type="button" onClick="Sell()" value="Sell"></input>
<p id="Money">€ 0</p>

<input id="SlideBar" type="range" min="0" max="100" value="50"></input>
var KilogramsV=0;
var LitersV=0;
function AddKg(){
KilogramsV+=400;
document.getElementById("Kilograms").innerHTML=KilogramsV +" "+ "Kilograms";
}
function AddL(){
LitersV+=340;
document.getElementById("Liters").innerHTML=LitersV +" "+ "Liters";
}

This is what I have so far.
Thanks!

I have watched yt videos but couldn’t find anything helpful.

Tabulator v5.6, doubts regarding setValue() and editor:”List”

First doubt:

In my tabulator table I have my columns ‘price’, ‘price 2’, ‘discount’, at a given moment in my cellEdited() of the ‘discount’ column I do a setValue() on the ‘price’ column, this triggers the cellEdited () which does a setValue() on the ‘price2’ column, and this triggers cellEdited() which does a setValue() on the ‘discount’ column… The problem here is that this ends up causing a loop (‘Column 1’ calls > ‘Column 2’ calls > ‘Column 3’ which calls > ‘Column 1’ and stays in this loop), I wanted to know if there is a way to do a ‘silent’ setValue() (without triggering cellEdited()) from column?

Currently I’m controlling it with the global variable ‘triggered = true’ which I set the value when doing setValue() and in cellEdited() I only execute things if the global variable doesn’t have the value ‘true’, but it doesn’t seem like the best option.

Second doubt:

I have my ‘product’ column which is editor: “list”, but I want that as I type I ‘repopulate’ the list options “cellEditing()” and “cellEdited()” do not work in this case, because as it says in documentation “cellEditing()” is for when editing of the selected value begins and “cellEdited()” is after finishing editing, in the documentation it has ‘valuesURL: “http://myvalues.com”, //a url to load the values from’ (https://tabulator.info/docs/5.6/edit#editor-list), but in my case I don’t have a url, I will do a select in a view from my database, any tips on how to do this? I’m quite lost in this situation.

mqtt over tls using mqtt.js

I have a eclipse-mosquitto container running on a server which I want to connect to over wss.

I have the following configuration on the server

allow_anonymous false
password_file /mosquitto/config/passwd

persistence true
persistence_location /mosquitto/data/

log_type all
log_dest file /mosquitto/log/mosquitto.log
log_dest stdout

listener 1883
protocol mqtt

listener 8083
protocol websockets
websockets_log_level all
socket_domain ipv4

listener 8883
protocol mqtt
require_certificate false
cafile /mosquitto/cert/ca.crt
certfile /mosquitto/cert/server.crt
keyfile /mosquitto/cert/server.key
tls_version tlsv1.2

listener 8084
protocol websockets
require_certificate false
cafile /mosquitto/cert/ca.crt
certfile /mosquitto/cert/server.crt
keyfile /mosquitto/cert/server.key
tls_version tlsv1.2
websockets_log_level all
socket_domain ipv4

user mosquitto

And the following docker-compose config

  mosquitto:
    container_name: mosquitto
    image: eclipse-mosquitto:latest
    restart: unless-stopped
    hostname: "${ENV_TYPE}-mosquitto"
    ports:
      - 1883:1883
      - 8883:8883
      - 8083:8083
      - 8084:8084
    volumes:
      - ./volumes/mosquitto/data:/mosquitto/data
      - ./volumes/mosquitto/log:/mosquitto/log
      - ./volumes/mosquitto/config:/mosquitto/config
      - ./volumes/mosquitto/cert:/mosquitto/cert

And using MQTT Explorer I am able to connect just fine over tls

mqtt conection

But when trying to connect to it using the mqtt.js library I fail to get a wss connection. ws over port 8083 works just fine, just as connecting to a a different broker over wss.

<body>
  <script src="https://unpkg.com/mqtt/dist/mqtt.js"></script>
  <script>
    const id = Math.random().toString(36).substring(7);
    const topic = "topic";
    const connection = "wss://username:[email protected]:8084"
    // const connection = "ws://username:[email protected]:8083" // Works
    // const connection = "wss://public:[email protected]" // Works
    const client = mqtt.connect(connection, {
      rejectUnauthorized: false,
    });

    client.on("message", messageReceived);
    client.on("connect", function () {
      println("connected!");
      client.subscribe("topic");
      client.publish("topic", "Hello from HTML");
    });
    client.on("error", function (error) {
      println("Error: " + error);
    });
    client.on('end', function() {
      println("Disconnected");
    })


    function messageReceived(topic, message) {
      println(topic + ": " + message);
    }
    function println(message) {
      const p = document.createElement("p");
      p.textContent = message;
      document.querySelector("body").append(p);
    }
  </script>
</body>

Firefox scrolling sometimes linked to previous scroll position

I have a website where there is a link at the footer to a particular page state, e.g. the Rules. I say page state since the site is a single HTML page and individual “pages” are simply states of that one HTML page with certain content displayed and other content hidden. The footer content is the same and visible on all page states.

Regardless of what page state one is on, the link from the footer ought to navigate one to the top of the Rules page. And it does this except when the footer link is clicked from one particular page, in which case it goes to the end of the Rules page.

This anomaly is not experienced in either Chrome or Edge, in either desktop or mobile versions of such browsers.

The code script associated with the link to the Rules page is:

/** Moves browser to the Governance page and scrolls to the top of the page
*/
const switchToRulesPage = () => 
{
    if ('scrollRestoration' in history)         
    {
        history.scrollRestoration = 'manual';                                                                           
    }   

    window.scrollTo(0,0);                                                                                               

    switchPage('about-link', 'governance-cont', false);                                                                                     
}

I have tried re-ordering the above code so that the page state switch is done first and then the scroll to the top. But there is no change in browser behaviour.

For what it’s worth, I’ve removed all errors from the HTML page via W3C Validator.

Slick slider – smooth scroll with different slide widths

I’d like to build a smooth scroll slider (Slick slider) when I have different slide widths (variableWidth: true).

Is there a way that my 2nd slider will have the same speed all time (as the first slider with equal slide widths).

$('.gallery').slick({
  arrows: false,
  variableWidth: true,
  autoplay: true,
  autoplaySpeed: 0,
  speed: 3000,
  pauseOnHover: false,
  cssEase: 'linear',
  infinite: true
});
.gallery {
margin-bottom: 20px;
}
<link href="https://cdn.jsdelivr.net/npm/[email protected]/slick/slick.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/slick/slick.min.js"></script>
<div class="gallery">
  <img src="http://placehold.it/100x100">
  <img src="https://placehold.co/100x100/00ff00/FFF">
  <img src="https://placehold.co/100x100/0000ff/FFF">
  <img src="https://placehold.co/100x100/ff0000/FFF">
  <img src="http://placehold.it/100x100">
  <img src="https://placehold.co/100x100/00ff00/FFF">
  <img src="https://placehold.co/100x100/0000ff/FFF">
  <img src="https://placehold.co/100x100/ff0000/FFF">
</div>
<div class="gallery">
  <img src="http://placehold.it/100x100">
  <img src="https://placehold.co/100x100/00ff00/FFF">
  <img src="https://placehold.co/100x100/0000ff/FFF">
  <img src="https://placehold.co/600x100/00ff00/FFF">
  <img src="https://placehold.co/1600x100/0000ff/FFF">
  <img src="https://placehold.co/50x100/ff0000/FFF">
  <img src="http://placehold.it/100x100">
  <img src="https://placehold.co/600x100/00ff00/FFF">
  <img src="https://placehold.co/1600x100/0000ff/FFF">
  <img src="https://placehold.co/50x100/ff0000/FFF">
</div>

How can I prevent items from being duplicated? Javascript

I have this code that customizes a json, but returns duplicate items, which will be necessary, so that duplicate items are not returned

I think that with the value of nid you could prevent items from being duplicated
any solution

Is there any easy way to do this.

Please have a look

Thanks for the help

let result = {};

   for (let item of data) {
     for (let subItem of item.itemsSlider) {
       if (!result[subItem.language]) {
         result[subItem.language] = [];
       }
       result[subItem.language].push(subItem);
     }
   }
   return result

this is the json
DATA:

const data = [
 {
    "itemsSlider": [
      {
        "nid": "61626",
        "status": "1",
        "titleNode": "01Additional Suitcase - EN",
        "language": "en_US"
      },
      {
        "nid": "61234",
        "status": "1",
        "titleNode": "01Additional Suitcase - EN",
        "language": "en_US"
      }
    ]
  },
  {
    "nid": "61567",
    "title": "K02 - Kiosk Slider - EN",
    "itemsSlider": [
      {
        "nid": "616098",
        "status": "1",
        "titleNode": "01Additional Suitcase - EN",
        "language": "es_MX"
      },
      {
        "nid": "616321",
        "status": "1",
        "titleNode": "01Additional Suitcase - EN",
        "language": "es_MX"
      }
    ]
  },
  {
    "nid": "61629",
    "title": "K02 - Kiosk Slider - EN",
    "itemsSlider": [
      {
        "nid": "616347",
        "status": "1",
        "titleNode": "01Additional Suitcase - EN",
        "language": "fr_FR"
      },
      {
        "nid": "61555",
        "status": "1",
        "titleNode": "01Additional Suitcase - EN",
        "language": "fr_FR"
      }
    ]
  },
  {
    "nid": "61629",
    "title": "K02 - Kiosk Slider - Mix",
    "itemsSlider": [
      {
        "nid": "616567",
        "status": "1",
        "titleNode": "01Additional Suitcase - EN",
        "language": "es_MX"
      },
      {
        "nid": "61626",
        "status": "1",
        "titleNode": "01Additional Suitcase - EN",
        "language": "en_US"
      }
    ]
  }
]

use hook keep calling the async function recursively

the getStudentData keeps getting called recursively for no reason

const studentDataPromise = useMemo(() => { return getStudentData(reviews); }, []);

const studentData = use(studentDataPromise);

async function getStudentData(reviews) {

if (!(reviews instanceof Array)) return {};

if (!reviews.length) return {};

const studentData = {};

const unDuplicatedStudentIds = [ ...new Set(reviews?.map(({ ownerId }) => ownerId)), ];

console.log({ unDuplicatedStudentIds });

const studentDataArray = [];

for (let i = 0; i < unDuplicatedStudentIds.length; i++) { const studentId = unDuplicatedStudentIds[i]; const studentDoc = getDoc(doc(db, "students", studentId)).catch((error) => { console.log({ StudentsData: error }); }); studentDataArray.push(studentDoc); }

console.log({ studentDataArray });

const resolvedStudentsData = await Promise.all(studentDataArray);

for (let j = 0; j < resolvedStudentsData.length; j++) { const studentDoc = resolvedStudentsData[j]; if (!(studentDoc instanceof DocumentSnapshot)) continue; if (!studentDoc.exists()) continue; const photoURL = await getPhotoUrl(studentDoc.id); studentData[studentDoc.id] = { id: studentDocyour text.id, ...studentDoc.data(), photoURL, }; }

return studentData; }

get the studentDataPromise resolved and display the data in the ui

How to align two html tables with same headers

I have two html tables, first one is two rows 1 for headers and one for buttons to hide columns in table 2.

    <table id="buttons" style="width: 100%;">
        <tbody>
            <tr>
                <td>Header 1</td>
                <td>Header 2</td>
                <td style="text-align:center"><strong>Header 3</strong></td>
                <td style="text-align:center"><strong>Header 4</strong></td>
                <td style="text-align:center"><strong>Header 5</strong></td>
                <td style="text-align:center"><strong>Header 6</strong></td>
                <td style="text-align:center"><strong>Header 7</strong></td>
                <td style="text-align:center"><strong>Header 8</strong></td>
                <td style="text-align:center"><strong>Header 9</strong></td>
                <td style="text-align:center"><strong>Header 10</strong></td>
                <td style="text-align:center"><strong>Header 11</strong></td>
                <td style="text-align:center"><strong>Header 12</strong></td>
                <td style="text-align:center"><strong>Header 13</strong></td>
                <td style="text-align:center"><strong>Header 14</strong></td>
                <td style="text-align:center"><strong>Header 15</strong></td>
                <td style="text-align:center"><strong>Header 16</strong></td>
                <td style="text-align:center"><strong>Header 17</strong></td>
                <td style="text-align:center"><strong>Header 18</strong></td>
                <td style="text-align:center"><strong>Header 19</strong></td>
                <td>Header 20</td>
                <td style="text-align:center"><strong>Header 21</strong></td>
                <td>Header 22</td>
                <td>Header 23</td>
            </tr>
            <tr>
                <td></td>
                <td></td>

                <td style="text-align:center">

                    <label>

                        <input type="checkbox" checked="" onchange="javascript:show_hide_column(2);" class="">

                        <span class="slider round"></span>

                    </label>
                </td>


                <td style="text-align:center">

                    <label>

                        <input type="checkbox" checked="" onchange="javascript:show_hide_column(3);">

                        <span class="slider round"></span>

                    </label>
                </td>


                <td style="text-align:center">

                    <label>

                        <input type="checkbox" checked="" onchange="javascript:show_hide_column(4);">

                        <span class="slider round"></span>

                    </label>
                </td>


                <td style="text-align:center">

                    <label>

                        <input type="checkbox" checked="" onchange="javascript:show_hide_column(5);">

                        <span class="slider round"></span>

                    </label>
                </td>


                <td style="text-align:center">

                    <label>

                        <input type="checkbox" checked="" onchange="javascript:show_hide_column(6);">

                        <span class="slider round"></span>

                    </label>
                </td>


                <td style="text-align:center">

                    <label>

                        <input type="checkbox" checked="" onchange="javascript:show_hide_column(7);">

                        <span class="slider round"></span>

                    </label>
                </td>


                <td style="text-align:center">

                    <label>

                        <input type="checkbox" checked="" onchange="javascript:show_hide_column(8);">

                        <span class="slider round"></span>

                    </label>
                </td>


                <td style="text-align:center">

                    <label>

                        <input type="checkbox" checked="" onchange="javascript:show_hide_column(9);">

                        <span class="slider round"></span>

                    </label>
                </td>


                <td style="text-align:center">

                    <label>

                        <input type="checkbox" checked="" onchange="javascript:show_hide_column(10);">

                        <span class="slider round"></span>

                    </label>
                </td>


                <td style="text-align:center">

                    <label>

                        <input type="checkbox" checked="" onchange="javascript:show_hide_column(11);">

                        <span class="slider round"></span>

                    </label>
                </td>


                <td style="text-align:center">

                    <label>

                        <input type="checkbox" checked="" onchange="javascript:show_hide_column(12);">

                        <span class="slider round"></span>

                    </label>
                </td>


                <td style="text-align:center">

                    <label>

                        <input type="checkbox" checked="" onchange="javascript:show_hide_column(13);">

                        <span class="slider round"></span>

                    </label>
                </td>


                <td style="text-align:center">

                    <label>

                        <input type="checkbox" checked="" onchange="javascript:show_hide_column(14);">

                        <span class="slider round"></span>

                    </label>
                </td>


                <td style="text-align:center">

                    <label>

                        <input type="checkbox" checked="" onchange="javascript:show_hide_column(15);">

                        <span class="slider round"></span>

                    </label>
                </td>


                <td style="text-align:center">

                    <label>

                        <input type="checkbox" checked="" onchange="javascript:show_hide_column(16);">

                        <span class="slider round"></span>

                    </label>
                </td>


                <td style="text-align:center">

                    <label>

                        <input type="checkbox" checked="" onchange="javascript:show_hide_column(17);">

                        <span class="slider round"></span>

                    </label>
                </td>


                <td style="text-align:center">

                    <label>

                        <input type="checkbox" checked="" onchange="javascript:show_hide_column(18);">

                        <span class="slider round"></span>

                    </label>
                </td>

                <td></td>

                <td style="text-align:center">

                    <label>

                        <input type="checkbox" checked="" onchange="javascript:show_hide_column(20);">

                        <span class="slider round"></span>

                    </label>
                </td>

                <td></td>
                <td></td>
            </tr>
        </tbody>
    </table>
    <table class="relative-table wrapped confluenceTable" style="width: 100%;">
        <tbody>
            <tr>
                <td class="highlight-#b3d4ff confluenceTd" title="Background color : Light blue 100%"
                    data-highlight-colour="#b3d4ff"><strong>Header 1</strong></td>
                <td class="highlight-#b3d4ff confluenceTd" title="Background color : Light blue 100%"
                    data-highlight-colour="#b3d4ff"><strong>Header 2</strong></td>
                <td class="highlight-#b3d4ff confluenceTd" data-highlight-colour="#b3d4ff" style=""><strong>Header
                        3</strong>
                </td>
                <td class="highlight-#b3d4ff confluenceTd" data-highlight-colour="#b3d4ff"><strong>Header 4</strong>
                </td>
                <td class="highlight-#b3d4ff confluenceTd" data-highlight-colour="#b3d4ff"><strong>Header 5</strong>
                </td>
                <td class="highlight-#b3d4ff confluenceTd" title="Background color : Light blue 100%"
                    data-highlight-colour="#b3d4ff"><strong>Header 6</strong></td>
                <td class="highlight-#b3d4ff confluenceTd" title="Background color : Light blue 100%"
                    data-highlight-colour="#b3d4ff"><strong>Header 7</strong></td>
                <td class="highlight-#b3d4ff confluenceTd" title="Background color : Light blue 100%"
                    data-highlight-colour="#b3d4ff"><strong>Header 8</strong></td>
                <td class="highlight-#b3d4ff confluenceTd" title="Background color : Light blue 100%"
                    data-highlight-colour="#b3d4ff"><strong>Header 9</strong></td>
                <td class="highlight-#b3d4ff confluenceTd" title="Background color : Light blue 100%"
                    data-highlight-colour="#b3d4ff"><strong>Header 10</strong></td>
                <td class="highlight-#b3d4ff confluenceTd" title="Background color : Light blue 100%"
                    data-highlight-colour="#b3d4ff"><strong>Header 11</strong></td>
                <td class="highlight-#b3d4ff confluenceTd" title="Background color : Light blue 100%"
                    data-highlight-colour="#b3d4ff"><strong>Header 12</strong></td>
                <td class="highlight-#b3d4ff confluenceTd" title="Background color : Light blue 100%"
                    data-highlight-colour="#b3d4ff"><strong>Header 13</strong></td>
                <td class="highlight-#b3d4ff confluenceTd" title="Background color : Light blue 100%"
                    data-highlight-colour="#b3d4ff"><strong>Header 14</strong></td>
                <td class="highlight-#b3d4ff confluenceTd" data-highlight-colour="#b3d4ff"><strong>Header 15</strong>
                </td>
                <td class="highlight-#b3d4ff confluenceTd" title="Background color : Light blue 100%"
                    data-highlight-colour="#b3d4ff"><strong>Header 16</strong></td>
                <td class="highlight-#b3d4ff confluenceTd" data-highlight-colour="#b3d4ff"><strong>Header 17</strong>
                </td>
                <td class="highlight-#b3d4ff confluenceTd" data-highlight-colour="#b3d4ff"><strong>Header 18</strong>
                </td>
                <td class="highlight-#b3d4ff confluenceTd" data-highlight-colour="#b3d4ff"><strong>Header 19</strong>
                </td>
                <td class="highlight-#b3d4ff confluenceTd" title="Background color : Light blue 100%"
                    data-highlight-colour="#b3d4ff"><strong>Header 20</strong></td>
                <td class="highlight-#b3d4ff confluenceTd" title="Background color : Light blue 100%"
                    data-highlight-colour="#b3d4ff"><strong>Header 21</strong></td>
                <td class="highlight-#b3d4ff confluenceTd" title="Background color : Light blue 100%"
                    data-highlight-colour="#b3d4ff"><strong>Header 22</strong></td>
                <td class="highlight-#b3d4ff confluenceTd" title="Background color : Light blue 100%"
                    data-highlight-colour="#b3d4ff"><strong>Header 23</strong></td>
            </tr>
            <tr>
                <td>23</td>
                <td>45</td>
                <td>12</td>
                <td>67</td>
                <td>89</td>
                <td>34</td>
                <td>56</td>
                <td>78</td>
                <td>90</td>
                <td>32</td>
                <td>43</td>
                <td>21</td>
                <td>76</td>
                <td>88</td>
                <td>35</td>
                <td>54</td>
                <td>78</td>
                <td>45</td>
                <td>67</td>
                <td>23</td>
                <td>12</td>
                <td>56</td>
                <td>89</td>
            </tr>
            <tr>
                <td>23</td>
                <td>45</td>
                <td>12</td>
                <td>67</td>
                <td>89</td>
                <td>34</td>
                <td>56</td>
                <td>78</td>
                <td>90</td>
                <td>32</td>
                <td>43</td>
                <td>21</td>
                <td>76</td>
                <td>88</td>
                <td>35</td>
                <td>54</td>
                <td>78</td>
                <td>45</td>
                <td>67</td>
                <td>23</td>
                <td>12</td>
                <td>56</td>
                <td>89</td>
            </tr>
            <tr>
                <td>This_is_a_very_long_text_to_display_what_my_real_table_looks_like</td>
                <td>45</td>
                <td>12</td>
                <td>67</td>
                <td>89</td>
                <td>34</td>
                <td>56</td>
                <td>78</td>
                <td>90</td>
                <td>32</td>
                <td>43</td>
                <td>21</td>
                <td>76</td>
                <td>88</td>
                <td>35</td>
                <td>54</td>
                <td>78</td>
                <td>45</td>
                <td>67</td>
                <td>23</td>
                <td>12</td>
                <td>56</td>
                <td>89</td>
            </tr>
        </tbody>
    </table>

This is what it looks like
output_of_html_code

I want the columns to align with each other so each column in table 1 is equal to its respective column in table 2
I tried setting column groups to be equal to each other using the following JS code:

document.getElementById('buttons').style.width = document.getElementsByClassName('relative-table wrapped confluenceTable')[0].style.width
    colgroup = document.getElementsByClassName('relative-table wrapped confluenceTable')[0].getElementsByTagName('colgroup')[0]   
    document.getElementById('buttons').getElementsByTagName('colgroup')[0].innerHTML = colgroup.innerHTML

yet no luck.

I also hard coded the column groups, using both pixels and percentages, into both tables and still no luck:

     <colgroup>
            <col style="width: 8.10965%;">
            <col style="width: 4.71625%;">
            <col style="width: 2.70322%;">
            <col style="width: 2.70322%;">
            <col style="width: 2.93328%;">
            <col style="width: 3.04831%;">
            <col style="width: 3.04831%;">
            <col style="width: 3.04831%;">
            <col style="width: 3.04831%;">
            <col style="width: 3.04831%;">
            <col style="width: 3.04831%;">
            <col style="width: 3.04831%;">
            <col style="width: 3.04831%;">
            <col style="width: 3.27837%;">
            <col style="width: 3.3934%;">
            <col style="width: 3.3934%;">
            <col style="width: 3.22085%;">
            <col style="width: 3.16334%;">
            <col style="width: 4.1411%;">
            <col style="width: 7.24692%;">
            <col style="width: 14.7814%;">
            <col style="width: 5.11886%;">
            <col style="width: 8.22468%;">
        </colgroup>

How can I do this using vanilla html, css and js?
Note: the second table is a confluence page

Is it possiable to get source of a HTML element of a partiulcar area/part of a web page?

Is it possible to get the source of an HTML element of a particular area/part of a web page? Like sometimes we open our browser open a website hover over a button or element and inspect it and we can see all the code for example <div class="fs-body2 bb bc-black-225 bg-black-100 p12"> Introduce the proble </div> and we can see that particular element code in my case I hover over ‘ Introduce the problem’ and just inspect it and I get that source.

Currently, my code doesn’t work on every HTML code it return null in most cases if the HTML code is too large.

import fs from "fs";
import { JSDOM } from "jsdom";

function findTextInHTML(filePath, targetText) {
  const htmlCode = fs.readFileSync(filePath, "utf8");
  const dom = new JSDOM(htmlCode);
  const document = dom.window.document;

  function searchText(element) {
    if (element.textContent.includes(targetText)) {
      return element;
    }

    if (element.outerHTML.includes(targetText)) {
      for (const child of element.children) {
        const result = searchText(child);
        if (result) {
          return result;
        }
      }

      return element;
    }

    return null;
  }

  const foundElement = searchText(document.body);

  return foundElement ? foundElement.tagName.toLowerCase() : null;
}

const htmlFilePath = "index.html";
const searchText = "Get Started";
const result = findTextInHTML(htmlFilePath, searchText);
console.log(result);

How do I create a 3d array in JavaScript initialised to be full of zeroes, with XYZ dimensions 5x5x64

I’ve written what i thought would create an array of 5 arrays each containing 5 arrays of 64 zeroes, but when i write the resulting array to the console, i do not get what i expected to see, yet the code makes sense to me.

Here is my code:

    const C = new Array(5);

    for (let x = 0; x < 5; x++) {
        for (let y = 0; y < 5; y++) {
            for (let z = 0; z < 64; z++) {
                C[x,y,z] = 0;
            }
        }
    }

    console.log(C);

logging C presents me with one array of 64 zeroes. What is wrong?