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

When a base html tag is dynamically added, the browser mistakenly loads assets twice

When managing relative paths on a website, I utilize the <base> tag within the <head> section of each page. Although all resources loaded via relative-like paths in the documents are displayed correctly, my observations show that browsers such ...

How can you resize a circle in Three.js without resizing its outline?

I'm currently using a THREE.Path to generate a Circular path and then utilizing a TubeGeometry to form a circle with transparent fill and an adjustable stroke thickness. My main query revolves around the process of scaling up the Circular path dynamic ...

Securing your Node.js connect-rest REST API with OAuth: A comprehensive guide

After conducting an extensive search on Google for examples related to my query, I was left empty-handed due to the generic name of the "connect-rest" package. My objective is to secure a server side API that I have built using the Node module "connect-re ...

Transform colored svg:image elements into grayscale when clicked upon by utilizing d3

Visit this site I'm attempting to change all SVG images created using d3.select to grayscale by using the following function: JavaScript: <script> function convert() { d3.selectAll("image") .style('filter', 'graysc ...

React JS Calendar

I'm currently working on a project where I need to create a calendar component using React. The design requires the days to be displayed like in the Windows calendar, starting from Sunday even if it's another month and ending with Saturday. The ...

Express router failing to catch parameters in node application

So, here's the scenario: router.put('/user:resourceId', function(req, res) { User.findOneAndUpdate({resourceId: req.params.resourceId}, req.body, function(err, user) { if (err) res.send(err); ...

What is the best method for fetching data returned by AJAX using PHP?

I have a data structure similar to the one below, which is returned via AJAX to another file: $data = array(); $data['message'] = "You are searching: $domain!"; $data['domain:name'] = "domain.tld"; $data['domain:registrar ...

"Dilemma with Displaying a 3-Digit Number in DaisyUI Using Next.Js Countdown Component

Hey there, I'm encountering an issue with the countdown component on my Next.js website using daisyUI. When the number of days exceeds 99, it's not rendering correctly as shown below: Initially, I have a straightforward countdown setup: const t ...

Modifying attributes for individual components in Vue.js classes

Recently, I integrated a reusable component called "LightBox" into my website, which displays images in higher resolution. The LightBox functionality is linked to each element having a thumbnail. However, I encountered an issue. There are multiple elements ...

Selenium - Activating a flash button

Currently, I am facing an issue while trying to load a URL using Selenium on Mozilla browser. The webpage contains a 'Login' button created in flash that I need to click on. I have explored the following resources: 1.How to click an element in Se ...

Fixing the Angular2 glitch: 'Uncaught TypeError: Cannot read property 'apply' of undefined'

Seeking solutions: How can I fix the "Uncaught TypeError: Cannot read property 'apply' of undefined" error that keeps showing up in the console of my Angular2 application? Any helpful insights are appreciated! ...

Challenge faced with the existence of multiple foreign keys belonging to a single model

I just started using sequelize and I'm trying to retrieve a list of nearby users. However, I encountered the following error: AggregateReview is associated with a User using an alias. You've specified an alias (test), but it doesn't match t ...

Should you hold off on moving forward until the asynchronous task finishes?

My goal is to retrieve location coordinates using the Google Maps JavaScript API in an asynchronous manner. Below is the function I've created for this purpose: function fetchCoordinates(address) { var geocoder = new google.maps.Geocoder(); ...

Enhancing Material UI v4 Themes using TypeScript

I am attempting to implement my own custom palette option in the theme section, but I am struggling with how to do the augmentation part using TypeScript. So far, I have created a file named "material-ui.d.ts" and inside it, I only have: import { PaletteO ...

Tips for updating and triggering useEffect when the router changes in React JS

I have a ChartPage function that is being called three times within three different routers. Inside the ChartPage function, I am using "useEffect" to update some variables based on the selected route. However, for some reason, it only triggers once, and wh ...

Guide to implementing optional localization strings in React-Router paths

Incorporating react-router, I aim to implement internationalization for links following this format: domain.com/langISO/countryISO2/page Here are some examples of valid routes: domain.com/ -> Home Page domain.com/en/us -> Home Page domain.com/fr/f ...

Exploring the boundaries of HTML data manipulation using JavaScript or jQuery

In my HTML (within a Twig template), there is the following code snippet: <li id="{{folder.id}}" data-jstree='{"icon":"glyphicon glyphicon-tags", "type":"folder"}' ><a href="#">{{folder.name}}</a> I'm attempting to extrac ...

"Ensure div remains at the bottom of the page even while

In order to implement a feature where the menu sticks to the top when scrolling down, you can use the following JS code. You can view a live example of this functionality on this Plunker by widening the preview window to see the columns side by side. wi ...

Exploring the DRY method in dealing with Nested Express Routes

Is there a way to create an API that can retrieve nested attributes of a person? router.get('/person/:id', fun.. router.get('/person/:id/name, fun... router.get('/person/:id/address, fun... All three are part of the same object in a ...

How to adjust the size of the text on a button in jQuery mobile using custom

I am facing an issue with my jQuery mobile buttons that are placed inside a fieldset. Specifically, I need to adjust the font-size of one of the buttons. Despite attempting to add an inline style, it did not have the desired effect. Furthermore, I tried u ...