Find a way to incorporate social media features into a web application that functions intermittently

Currently, I am in the process of developing a social media app and working on integrating a search feature to enable users to find friends. The code I have below seems to be functional at times but not consistent (quite frustrating!) The issue seems to stem from the asynchronous nature of JavaScript. I tried addressing this by using a 'then' function for the second search. Basically, the code should first search based on users' first names, then their last names, push the results into an array called users, flatten it out, extract unique user objects, and finally pass them to handlebars for display. The problem appears to arise with tests that involve more than one word where sometimes the second word is searched for and other times not:

  1. The search should return results for each word entered
  2. The search should not be affected by non-alphanumeric characters

Controller

const User = require("../models/user");

const SearchController = {
  Index: (req, res) => {
    const users = [];
    User.find().then((user) => {
      users.push(user);
      const merged = [].concat.apply([], users);
      const uniqueArray = merged.filter((value, index) => {
        const _value = JSON.stringify(value);
        return (
          index ===
          merged.findIndex((obj) => {
            return JSON.stringify(obj) === _value;
          })
        );
      });
      res.render("search/index", { users: uniqueArray });
    });
  },
  Create: (req, res) => {
    const searchArray = req.body.message.replace(/[\W_]+/g, " ").split(/[ ,]+/);

    const users = [];
    searchArray.forEach((name) => {
      User.find({
        firstName: { $regex: name, $options: "i" },
        // lastName: { $regex: name, $options: "i" },
      }).then((user) => {
        users.push(user);
        User.find({
          // firstName: { $regex: name, $options: "i" },
          lastName: { $regex: name, $options: "i" },
        }).then((user) => {
          users.push(user);
          const merged = [].concat.apply([], users);
          const uniqueArray = merged.filter((value, index) => {
            const _value = JSON.stringify(value);
            return (
              index ===
              merged.findIndex((obj) => {
                return JSON.stringify(obj) === _value;
              })
            );
          });
          res.render("search/index", { users: uniqueArray });
        });
      });
    });
  },
};

module.exports = SearchController;

Cypress Tests

describe("Searching users", () => {
  beforeEach(() => {
    cy.signUp();
    cy.signUp("Chris", "Coding", "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="2f4c475d465c6f4c404b464148014c4042">[email protected]</a>", "12345");
    cy.signUp("Paul", "Coding", "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="403021352c00232f24292e276e232f2d">[email protected]</a>", "12345");
    cy.signUp("Adam", "Woodcock", "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="ceafaaafa38eb9a1a1aaada1ada5e0ada1a3">[email protected]</a>", "12345");
    cy.signUp("Kathleen", "Woodcock", "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="4e252f3a26222b2b200e3921212a2d212d25602d2123">[email protected]</a>", "12345");
    cy.signUp("George", "Hett", "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="92f5f7fde0f5f7d2faf7e6e6bcf1fdff">[email protected]</a>", "12345");
    cy.signUp("Rob", "Oman", "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="4634292406292b27286825292b">[email protected]</a>", "12345");
  });

  it("Users can be searched by entering a name", () => {
    cy.login();
    cy.get("#searchBox").type("george");
    cy.get("#searchButton").click();

    cy.get(".user-container").first().should("contain", "George Hett");
  });

  it("Users can be searched by entering a last name", () => {
    cy.login();
    cy.get("#searchBox").type("woodcock");
    cy.get("#searchButton").click();

    cy.get(".user-container").should("have.length", 2);
    cy.get(".user-container").should("contain", "Adam Woodcock");
    cy.get(".user-container").should("contain", "Kathleen Woodcock");
  });

  it("A blank search returns all users", () => {
    cy.login();
    cy.get("#searchButton").click();

    cy.get(".user-container").should("have.length", 7);
    cy.get(".user-container").should("contain", "Adam Woodcock");
    cy.get(".user-container").should("contain", "Kathleen Woodcock");
    cy.get(".user-container").should("contain", "Chris Coding");
    cy.get(".user-container").should("contain", "Paul Coding");
    cy.get(".user-container").should("contain", "Rob Oman");
    cy.get(".user-container").should("contain", "George Hett");
    cy.get(".user-container").should("contain", "Barry Barry-Barroldsson");
  });

  it("Visiting the search page without going through the search bar returns all users", () => {
    cy.login();
    cy.visit("/search");

    cy.get(".user-container").should("have.length", 7);
    cy.get(".user-container").should("contain", "Adam Woodcock");
    cy.get(".user-container").should("contain", "Kathleen Woodcock");
    cy.get(".user-container").should("contain", "Chris Coding");
    cy.get(".user-container").should("contain", "Paul Coding");
    cy.get(".user-container").should("contain", "Rob Oman");
    cy.get(".user-container").should("contain", "George Hett");
    cy.get(".user-container").should("contain", "Barry Barry-Barroldsson");
  });

  it("The search should not be impacted by special characters", () => {
    cy.login();
    cy.get("#searchBox").type("Chris   /.,[]   Coding");
    cy.get("#searchButton").click();

    cy.get(".user-container").should("have.length", 2);
    cy.get(".user-container").should("contain", "Chris Coding");
    cy.get(".user-container").should("contain", "Paul Coding");
  });

  it("Each word entered should return relevant search results", () => {
    cy.login();
    cy.get("#searchBox").type("Chris Woodcock");
    cy.get("#searchButton").click();

    cy.get(".user-container").should("have.length", 3);
    cy.get(".user-container").should("contain", "Adam Woodcock");
    cy.get(".user-container").should("contain", "Kathleen Woodcock");
    cy.get(".user-container").should("contain", "Chris Coding");
  });
});

I would appreciate any recommendations on how to improve and fix the issues in this code

Answer №1

If you're looking for a more effective solution, I haven't encountered any issues related to asynchronous processing failures.

Assuming that User.find() is returning a promise.

const promises = searchArray.map((name) => {
  return User.find({
    firstName: { $regex: name, $options: "i" },
    lastName: { $regex: name, $options: "i" },
  })
})

Promise.all(promises).then((values) => {
  const uniqueArray = values
    .flat()
    .filter((value, index, arr) => arr.indexOf(value) === index)
  res.render("search/index", { users: uniqueArray });
})

The

cy.get(".user-container").should("have.length", 3);
will address any delay in the test execution, but consider extending the timeout if the multi-level search may exceed 4 seconds.

cy.get(".user-container", {timeout:10000})
  .should("have.length", 3);

Answer №2

After some restructuring, I successfully resolved my own query by making adjustments to the code above. Instead of using a for each loop, I modified it to construct the final query and passed it to a find statement before rendering. The outcome was quite satisfying. Additionally, I made improvements to the index route.

const User = require("../models/user");

const SearchController = {
  Index: (req, res) => {
    User.find().then((users) => {
      res.render("search/index", { users: users });
    });
  },
  Create: (req, res) => {
    const searchArray = req.body.message.replace(/[\W_]+/g, " ").split(/[ ,]+/);
    const findQuery = [];
    searchArray.forEach((name) => {
      const first = { firstName: { $regex: name, $options: "i" } };
      const second = { lastName: { $regex: name, $options: "i" } };
      findQuery.push(first, second);
    });

    User.find({ $or: findQuery }).then((users) => {
      res.render("search/index", { users: users });
    });
  },
};

module.exports = SearchController;

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

How to access the onchange text in a react-select search component

I'm currently working on implementing search select functionality in my webpage using the react-select-search npm package. This is my main component: import React, { Component } from "react"; import Task from "./task"; // Rest of ...

The button attached to the jQuery .toggle() function requires two clicks to activate

My objective is twofold: To dynamically load the Disqus script embed.js only when the "Show Comments" button is clicked. To toggle the visibility of the disqus_thread div using the same button while also changing the button's text. The issue I am f ...

Retrieve an image from the database and associate it with corresponding features or news in PHP

I have retrieved a value from the database, displayed it as an image, and made it a link. So, I want that when a user clicks on the different image, they get the result from the query related to the image. I hope everyone understands. <?php // Connect ...

Tips for accessing the firebase user's getIdToken method in Next.js after a page reload

Currently, I am developing a Next.js project and implementing user authentication using Firebase's signInWithPhoneNumber method for phone number verification. After successful verification, I receive a Firebase user with the getIdToken method to retri ...

Ways to emphasize the index navigation link when on the main page

Currently, there is a web design project that I am tackling and have encountered a slight hiccup that needs resolving. The issue revolves around highlighting different navigation links based on the URL of the current page. This functionality works seamless ...

The mystery of the unassigned value in $(this).data(value) when using the jQuery click() method

In my Rails 5 application, I am working on creating a dynamic menu that will guide users to different parts of the site based on their location. The idea is that when they click on a specific menu item from the home page, a modal will appear allowing them ...

Securely store files by encrypting them with Node.js before saving to the disk

At the moment, I am making use of the multer library to store files on the File system. This particular application is built using Node and Express. I currently have a process in place where I save the file on the server first and then encrypt it. After e ...

Angular: Modifying the parent scope from a child component

Hey there! So I'm a beginner in this whole programming thing, but I'm currently working on a small application where I can add and update items with details using Ionic, Cordova, and AngularJS. However, I've hit a roadblock with the followin ...

Error: The variable 'err' is not declared in this scope.at line app.post

Tools I am Using Windows 10 Firebase (Firestore) Postman JavaScript, Express I'm learning from this video(https://www.youtube.com/watch?v=-vo7cu0xP4I) Situation Description I attempted to make a post request using Postman for testing purposes, b ...

Encountering an error message stating "Please enable JavaScript to run this application" when making React API calls after deploying a ReactJs app on the Firebase server

I'm currently working on a React JS app that calls various APIs. The backend of this application is a NodeJs server deployed in GCloud. While everything runs smoothly when I test the React app locally, I encountered an issue after deploying it to Fir ...

Sending JSON data from PHP to JavaScript using Ajax

Currently, I am attempting to transfer a JSON object from a PHP script to a JavaScript file using Ajax. The code I have been using successfully for a single string is now being modified to accommodate multiple strings within a JSON object. Below are snippe ...

Is there a way to toggle a single Reactstrap Collapse component?

Currently, I am working on a Next.JS application that displays a list of Github users. The goal is to have each user's information box toggle open and close when clicked, using Reactstrap's Collapse component. However, the issue I'm facing i ...

Reconstruct the altered block with the help of external scripts

I am in a situation where I must utilize a framework that modifies the DOM structure of my HTML. An example snippet of the HTML code being used is as follows: <div id="testID" ng-show="example === 'show'">Some Content</div> The fram ...

How can I effectively send a form with the value of 'put' using Laravel and Ajax?

I have been working on a function that utilizes AJAX to validate and send responses to the view when an edit form is submitted. However, I am encountering an issue where the page loads on a new URL like localhost:8000/comment/id, and I want the page to dis ...

Using TypeScript: Implementing array mapping with an ES6 Map

If I have an array of key-value objects like this: const data = [ {key: "object1", value: "data1"}, {key: "object2", value: "data2"}, {key: "object3", value: "data3"}, ] const mappedData = data.map(x => [x.key, x.value]); const ES6Map = n ...

When using electron-build, the node-adodb encountered an error stating: 'Failed to spawn C:WINDOWSSysWOW64cscript.exe'

Utilizing node-adodb.js for reading .mdb files with the following code: const db = require('node-adodb') ipcMain.on('query', (e, p) => { if (!p) return appendFileSync('a.log', new Date().getTime() + ' ' + p.t ...

Canvas drawImage function not displaying image at specified dimensions

I'm having trouble loading an image into a canvas using the drawImage function. Additionally, I've implemented drag functionality but found that when moving the image inside the canvas, it doesn't follow the mouse cursor in a linear manner. ...

Update: Cannot mark as invalid a nested document that has not been included in an array

I recently encountered an issue with my upsert query in mongoose. It was functioning perfectly in version 3.8, but ever since I upgraded to version 4, I've been facing the following error: Unable to invalidate a subdocument that has not been added to ...

What is the best way to modify an Li element using the DOM in JavaScript?

Just the other day, I discovered how to use JavaScript and DOM to add and delete Li elements. Now I'm curious about how to edit those Li elements using DOM. Any suggestions? Thank you! ...

What is the best way to switch the CSS class of a single element with a click in Angular 2

When I receive data from an API, I am showcasing specific items for female and male age groups on a webpage using the code snippet below: <ng-container *ngFor="let event of day.availableEvents"> {{ event.name }} <br> <n ...