Testing in Vue revealed an unexpected absence of data

I am facing difficulties when it comes to creating tests. Currently, I have a view that is supposed to verify an email address using an authentication code. At the moment, the view exists but no connection is established with an email service or code generator. The issue I'm encountering revolves around an expected value of an empty property. Here's the error message:

 verifyUser logs results if correct code (123456) is provided

    expect(jest.fn()).toHaveBeenCalledWith(...expected)

    Expected: "USER:", undefined, {"input": {"username": "123456"}, "verificationCode": null}
    Received
           1: "USER:", undefined
           2: "verificationCode: ", {"input": {"username": "123456"}}

The test file:

import { ref } from "vue";

const verificationCode = null;
const mockVerify = {
  verificationCode,
  input: {
    username: "123456",
  },
};

jest.mock("@vue/apollo-composable", () => ({
  __esModule: true,
  useApolloClient: () => ({
    resolveClient: () => ({
      query: () => ({
        data: { signup: mockVerify },
        loading: false,
        error: null,
      }),
    }),
  }),
}));

test("verifyUser returns undefined if email doesn't meet minimum length", async () => {
  const verificationCode = ref("");
  const { verifyUser } = useVerify(verificationCode);

  const result = await verifyUser();

  expect(result).toBe(undefined);
});

test("verifyUser logs results if correct code (123456) is provided", async () => {
  const consoleSpy = jest.spyOn(console, "log");
  const verificationCode = ref("123456");
  const { verifyUser } = useVerify(verificationCode);

  await verifyUser();

  expect(consoleSpy).toHaveBeenCalledWith("USER:", undefined, mockVerify);
});

the vue file:

  View to validate new user email address from emailed code before completing the registration process.
-->
<template lang="pug">
.Verify
  .Verify__focus
    .Verify__title Verify Your Email
    .Verify__form
      .Verify__field
        va-input.Verify__textInput(
          type="text",
          name="verificationCode",
          placeholder="Verification Code",
          v-model="verificationCode",
          @keyup.enter="verifyUser()"
        )
          template(v-slot:prependInner="")
            va-icon(name="check_circle")

        .Login__buttonRow
          va-button.Login__submitButton(@click="verifyUser") Verify
</template>

<script lang="ts">
import { defineComponent, ref } from "vue";
import useVerify from "@/views/Signup/Verify/useVerify";

/**
 * Assemble the Verify reactivity.
 *
 * @returns Data for the component to use.
 *  - verificationCode: verification code the user is sent
 *  - verifyUser: function to call to carry out the verification operation.
 */
function setup() {
  const verificationCode = ref("");
  const { verifyUser } = useVerify(verificationCode);

  return {
    verificationCode,
    verifyUser,
  };
}

export default defineComponent({
  name: "Verify",
  setup,
});
</script>

<style lang="scss">
.Verify {
  position: fixed;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;

  &__focus {
    width: 360px;
    max-width: 95vw;
  }

  &__field {
    padding-bottom: 0.5em;
  }

  &__buttonRow {
    display: flex;
    justify-content: flex-end;
  }

  &__title {
    font-size: 1.2em;
    padding-bottom: 0.5em;
    text-align: center;
  }
}
</style>

and, finally, the file that I am trying to test:

import { useApolloClient } from "@vue/apollo-composable";
import { ValidatedUser } from "@/models";
import { gql } from "graphql-tag";

const query = gql`
  query Verify($input: Verify) {
    Verify(input: $input) {
      __typename
      token
      user {
        email
        id
      }
    }
  }
`;

/**
 * Retrive apollo client and provide useVerify
 * function to validate input and execute Verify process.
 *
 * @param verificationCode - reactively wrapped email address of the user signing up.
 * @returns useVerify composition functionality.
 */
export default function useVerify(verificationCode: Ref<string>): {
  verifyUser: () => Promise<void>;
} {
  const { resolveClient } = useApolloClient();
  /**
   * Execute the Verify process for the given verification code.
   */
  async function verifyUser(): Promise<void> {
    if (verificationCode.value !== "123456") {
      //TODO: add window that shows the verification code is not valid
      return;
    } else {
      //TODO: link to login page
    }
    const client = resolveClient();

    const variables = {
      input: { username: verificationCode.value },
    };
    const response = await client.query({ query, variables });
    const validatedUser: ValidatedUser = response.data.Verify;
    console.log("USER:", validatedUser);
    console.log("verificationCode: ", variables);
  }
  return { verifyUser };
}

What do I need to do in order to make sure the verificationCode remains empty? How can I get this test to pass successfully?

Answer №1

Here are a few issues that need to be addressed:

  1. The useVerify() function does not return a verificationCode property in the API response, so it should be removed from the mockVerify object:

    //const verificationCode = null
    const mockVerify = {
      // verificationCode, ❌ this is not actually inserted in useVerify()
      input: {
        username: '123456',
      },
    }
    
  2. The useVerify() function expects the API response to have a Verify field, but your mock response sets a signup field instead:

    jest.mock('@vue/apollo-composable', () => ({
      __esModule: true,
      useApolloClient: () => ({
        resolveClient: () => ({
          query: () => ({
            // data: { signup: mockVerify }, ❌ useQuery() reads `data.Verify` (not `data.signup`)
            data: { Verify: mockVerify }, // ✅
            loading: false,
            error: null,
          }),
        }),
      }),
    }))
    
  3. In your second test, you assert that console.log() was called with USER:, undefined, and mockVerify, but the actual call in useVerify() only has two arguments:

    test('verifyUser logs results if correct code (123456) is provided', async () => {
      ⋮
      // expect(consoleSpy).toHaveBeenCalledWith('USER:', undefined, mockVerify) ❌ useVerify() calls console.log() with only 2 args
      expect(consoleSpy).toHaveBeenCalledWith('USER:', mockVerify) // ✅
    })
    

Check out the demo here

Note: Relying on console.log() for testing may result in fragile tests. It's best to only test for logging if it's an expected feature.

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

Uncover the content of a base64 encoded string and convert it into

A JSON response has been linked on the user's request to retrieve an excel document. The structure of the response is as follows: { "format": // file extn ----only xls "docTitle": //file name "document" :// base 64 encoded data } The attem ...

Using Vuejs 2 to switch the .active class on and off

Check out this HTML code: <nav class="nav nav-pills"> <li v-bind:class="{ 'active': isActive }" class="text-center"> <img class="img-responsive" src="{{ FuImg::asset(&apo ...

Angular 8 Issue: Absence of _body and Headers in Response

Our back-end code is written in C# within the .NET environment, targeting the 4.6.1 framework. Recently, our front-end was upgraded from Angular 4 to Angular 8. During this upgrade, webpack transitioned from version 2.3 to version 4.41 and typescript from ...

Using Angular Ionic for a click event that is triggered by a specific class

I am utilizing Highcharts and would like to click on the legend upon loading. With the use of Angular Ionic, how can I trigger a click on the .highcharts-legend-item class within the ngOnInit() {} method? I am aiming to click on this class as soon as the ...

Can I restrict access to all routes except one in vue-router? Is this a safe practice? Should I explore alternative methods for achieving this?

I am looking to create an online exam consisting of 5 pages, each with a countdown timer set at 120 seconds and 4 questions on each page. Once the timer runs out, users will be automatically redirected to the next page, or they can manually click the "next ...

Issues with utilizing Jquery datepicker within a Vue.js component's v-for loop in Laravel

I am facing an issue with the Jquery date picker inside a v-for loop in my vue.js component. The date picker works fine outside of the loop, but inside the loop it does not behave as expected. Here is a snippet of code where the date picker is working cor ...

Generate a library using Vue CLI from a component and then import it into your project

When using vue-cli to build my lib, I run the following command: "build": "vue-cli-service build --target lib --name myLib ./src/component.vue" After the build, how can I import my component from the dist folder? Importing from path-to-myLib/src/compone ...

Developing J2EE servlets with Angular for HTTP POST requests

I've exhausted my search on Google and tried numerous PHP workarounds to no avail. My issue lies in attempting to send POST parameters to a j2ee servlet, as the parameters are not being received at the servlet. Strangely though, I can successfully rec ...

What is the method for including a dynamic image within the 'startAdornment' of MUI's Autocomplete component?

I'm currently utilizing MUI's autocomplete component to showcase some of my objects as recommendations. Everything is functioning correctly, however, I am attempting to include an avatar as a start adornment within the textfield (inside renderInp ...

typescript - transforming text into numerical values

newbalance = (Number(this.balance)) + (Number(this.pastAmount)); The result for my newbalance calculation is coming back as undefined, even though this.balance is 34 and this.pastAmount is 23. I've set this up in the controller and I'm trying t ...

Angular is not programmed to automatically reflect updates made to my string array

let signalRServerEndPoint = 'https://localhost:44338'; this.connection = $.hubConnection(signalRServerEndPoint); this.proxy = this.connection.createHubProxy('MessagesHub'); this.proxy.on("ReceiveMessage", (message) => { ...

Error message stating 'Module not found' is displaying in the browser console

As a beginner with Angular CLI, I recently executed the following commands at the root of my Angular project. issue-management\src\webui>ng generate module pages\dashboard issue-management\src\webui>ng generate component pag ...

Join and Navigate in Angular 2

Attempting to retrieve information from a JSON file has been an issue for me. Here is the code snippet: ngOnInit() { this.http.get('assets/json/buildings.json', { responseType: 'text'}) .map(response => response) .subsc ...

What is the best way to change between different Angular 2 material tabs using typescript?

I need help with switching tabs using buttons <md-tab-group> <md-tab label="Tab 1">Content 1</md-tab> <md-tab label="Tab 2">Content 2</md-tab> </md-tab-group> <button md-button (click)="showTab1()">Show Tab 1< ...

Angular 2/Typescript experiencing a glitch with Jquery carousel functionality

After properly installing and importing jquery in my project, I encountered a specific issue. Within my application code, there is a line that reads as follows: $('#myCarousel').carousel("next"); Upon running npm start, an error is thrown: ...

JavaScript alert box

I'm fairly new to the world of web development, with knowledge in CSS & HTML and currently learning TypeScript. I'm attempting to create a message icon that opens and closes a notifications bar. Here's where I'm at so far: document.getE ...

Angular: Failure in receiving EventEmitter's event with .subscribe method

My current challenge involves handling an event coming from NgLoopDirective within the method EV of NgDNDirective. I am attempting to achieve this by passing the EventEmitter object by reference and then calling .subscribe() as shown in the code snippet be ...

Tips on implementing zod schema types with remapped fields using the toZod method

I'm currently working on mapping a schema key to a different name in my database interface Country { isoCode: string, nameEn: string, nameDe: string, phone: string, bla: string } const CountryJson = { i ...

Extracting information from various tables when exporting in Laravel

I currently have two tables on hand: Accessory Request Table Accessory Details Table It's worth noting that one accessory request can have multiple entries in the accessory details table. However, when I attempt to export the data, only information ...

Unable to access the .env file in Vue.js when executing cross-env NODE_ENV=development webpack-dev-server --open --hot

I'm attempting to utilize an .env file for storing local variables, but I am encountering an issue where they appear as undefined when I try to log them. Here is a snippet from my .env file (located at the root of my project): VUE_APP_STRAPI_HOST=htt ...