How to rectify this type of warning when run (npm t) node_modules/#vue/test-utils/dist/vue-test-utils.js:1704 This error in Vue.js? - vue.js

i have one component which is responsible for Registering the user, i write test cases for that component by using vue-jest , i write some test cases for that Register component, when i run npm t it's showing following[errors] but all the test cases should be passed, How to fix this errors please help me to fix this issue
Register.spec.js
import Register from '../../src/Pages/Register.vue';
import { createLocalVue, shallowMount} from '#vue/test-utils'
describe('Register.vue', ()=>{
let wrapper;
beforeEach(() => {
const localVue = createLocalVue();
wrapper = shallowMount(Register, localVue);
});
test('setup correctly', () => {
expect(true).toBe(true)
})
it('renders a vue instance', () => {
expect(shallowMount(Register).vm).toBeTruthy();
})
it('has an image', () => {
expect(wrapper.contains('#side-img')).toBe(true);
});
it('has a side content',()=>{
expect(wrapper.contains('#side-content')).toBe(true);
});
it('has a two title sections',()=>{
expect(wrapper.contains('#signup')).toBe(true);
expect(wrapper.contains('#login')).toBe(true);
});
it('has a full name input box',()=>{
expect(wrapper.contains('#name-input')).toBe(true);
});
it('has a email input box',()=>{
expect(wrapper.contains('#Email-input')).toBe(true);
});
it('has a password input box',()=>{
expect(wrapper.contains('#passField')).toBe(true);
});
it('has a eye icons',()=>{
expect(wrapper.contains('#togglePassword')).toBe(true);
});
it('has a mobile input field',()=>{
expect(wrapper.contains('.telephone')).toBe(true);
});
it('has a button field',()=>{
expect(wrapper.contains('.btn-section')).toBe(true);
})
})
Register.vue
<template>
<div class="main">
<div class="container">
<img id="side-img" src="../assets/sideImg.png" alt="notFound" />
<p id="side-content">Online Book Shopping</p>
<div class="box">
<div class="headings">
<h5 class="signin" id="login" :class="{ active: isLogin }" #click="isLogin = true">Login</h5>
<h5 class="signup" id="signup" :class="{ active: !isLogin }" #click="isLogin = false">signup</h5>
</div>
<form ref="myForm" #submit.prevent="handlesubmit">
<div class="fullname">
<p>FullName</p>
<input type="name" id="name-input" class="namebox" required v-model="fullName" autocomplete="off" pattern="[A-Za-z]{3,12}">
</div>
<div class="username">
<p>EmailID</p>
<input type="email" id="Email-input" class="emailbox" required v-model="email" pattern="^[a-z0-9._%+-]+#[a-z0-9.-]+\.[a-z]{2,4}$">
</div>
<div class="password-section">
<p>Password</p>
<input :type="password_type" class="password" :class="{'password-visible': isPasswordVisible }" id="passField" v-model="password" pattern="^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[#$!%*?&])[A-Za-z\d#$!%*?&]{6,}$" required>
<i class="bi bi-eye-slash" id="togglePassword" #click="togglePassword();"></i>
</div>
<div class="mobile">
<p>MobileNumber</p>
<input type="tel" class="telephone" v-model="mobile" id="tel" pattern="^\d{10}$" required>
</div>
<button class="btn-section" id="btn" type="submit">Signup</button>
</form>
</div>
</div>
</div>
</template>
<script>
import service from '../service/User'
export default {
name: 'Register',
}

The warning itself and the docs for contains describe how to address the problem:
Deprecation warning
Using contains is deprecated and will be removed in future releases. Use find for DOM nodes (using querySelector syntax), findComponent for components, or wrapper.get instead.
Since all of your tests are using contains with querySelector syntax, replace wrapper.contains with wrapper.find, and replace toBe(true) with toBeTruthy().

Related

Vue Computed Value Filter (script setup)

I can't find anything relevant online. The relevant answers online dont use the tag.
Does it even work with script setup?
<template>
<div class="bg-white md:container md:mx-auto w-10">
<ul class="flex flex-wrap p-2 justify-center bg-black text-white">
<li class="p-2">
Filter
</li>
<li class="p-2">
Search
</li>
</ul>
<div class="flex flex-wrap justify-center h-52 content-center">
<div class="flex justify-center">
<div class="mb-3 xl:w-96">
<label
for="exampleSearch2"
class="form-label inline-block mb-2 text-gray-700"
>Search</label
>
<input
v-model="searchValue"
type="search"
class="form-control block w-full px-3 py-1.5 text-base font-normal text-gray-700 bg-white bg-clip-padding border border-solid border-gray-300 rounded transition ease-in-out m-0 focus:text-gray-700 focus:bg-white focus:border-blue-600 focus:outline-none"
id="exampleSearch2"
placeholder="Type query"
/>
<div class="flex flex-wrap">
<div>Test: {{ searchValue }}</div>
</div>
</div>
</div>
</div>
<div class="grid lg:grid-cols-4 md:grid-cols-3 gap-8">
<dogCard v-for="breed in breedsArray" :key="breed.id" :breed="breed" />
</div>
</div>
</template>
<script setup>
import dogCard from "../components/dogCard.vue";
import { ref, onMounted, computed } from "vue";
import searchBox from "./searchBox.vue";
let URL = "https://api.thedogapi.com/v1/breeds";
const searchValue = ref("");
let breedsData = ref([]);
// Fetching API Data
function getBreedsArray() {
fetch(URL)
.then((response) => response.json())
.then((data) => {
breedsData.value = data;
console.log("Data Fetched", breedsData.value);
})
.catch((error) => {
console.error(error);
});
}
onMounted(() => {
getBreedsArray();
});
const breedsArray = computed({
get() {
return breedsData.value;
},
set(val) {
breedsData.value = breedsData.value.filter((breed) => breed.name.includes() == searchValue);
},
});
let isVisible = ref(false);
</script>
Im trying to filter the dogCard through a Searchbox. I just don't know how to do it.
The Data of 'breedsData' should change on when something is entered in the Searchbox.
Thanks in advance, I'm stuck for so long now, an i dont how to fix this.
In the filter() in the computed setter, you do:
(breed) => breed.name.includes() == searchValue
But you probably want to use the value of the ref instead of the ref itself, and put it into includes():
(breed) => breed.name.includes(searchValue.value)
Note that this would permanently remove filtered breeds, as you change the breedsData.value. A better approach might be to just use the computed getter (I don't think the setter works the way you want it to anyway):
const breedsArray = computed(() => searchValue.value ?
breedsData.value.filter( breed => breed.name.includes(searchValue.value)) :
breedsData.value
)
Since searchValue is reactive, a change to it will trigger an update of the breedsArray.

how can I update a vue child-component from the vuex-store

My application shows a window where player can enter name and passcode to enter
When the player exists and has a card, I want to show the card as well.
When the player exists, I make the card visible. Then in 'created'I call fetchSpelerCards. This is successful but shows in the VUE console as pending...
I hope some experienced vue user reads this and can help me with a hint, reference or explanation.
For that I have in the following code:
<h2>Meld je aan</h2>
<form #submit.prevent="register" class="mb-3">
<div class="form-group">
<input type="text" class="form-control m-2" placeholder="naam" v-model="name">
</div>
<div class="form-group">
<input type="text" class="form-control m-2" placeholder="kies inlogcode" v-model="pass_code">
</div>
<button type="submit" #click="checkSpeler()" class="btn btn-primary btn-block" style="color:white">Save</button>
</form>
<p class="alert alert-danger" v-if="errorMessage !== ''"> {{errorMessage}} </p>
<p class="alert alert-success" v-if="successMessage !== ''"> {{successMessage}} </p>
<CardsSpeler v-if="spelerCorrect"></CardsSpeler>
</div>
</template>
The component looks as follows:
<h2>Cards 1</h2>
<form #submit.prevent="addCard" class="mb-3">
<div class="form-group">
<input type="text" class="form-control" placeholder="title" v-model="card.title">
</div>
<div class="form-group">
<textarea class="form-control" placeholder="description" v-model="card.description">
</textarea>
</div>
<div>
<input type="file" v-on:change="onFileChange" ref="fileUpload" id="file_picture_input">
</div>
<button type="submit" class="btn btn-primary btn-block" style="color:white">Save</button>
</form>
<div class="card card-body mb-2" v-for="card in cards" v-bind:key="card.id">
<h3> {{currentSpelerCard.title}} </h3>
<p> {{currentSpelerCard.description}}</p>
<img class="img-circle" style="width:150px" v-bind:src="currentSpelerCard.picture" alt="Card Image">
</div>
</div>
</template>
<script>
import { mapState, mapActions } from 'vuex';
export default {
mounted(){
console.log('component mounted');
},
computed: {
...mapState([
'currentSpeler' ,'currentSpelerCard'
]),
},
data() {
return{
cardExists:false,
successMessage:'',
errorMessage:'',
}
},
created(){
this.fetchSpelerCards();
},
methods: {
...mapActions([ 'getGames', 'addGame', 'fetchSpelerCards' ]),
fetchSpelerCards(){
this.$store.dispatch('fetchSpelerCards', this.currentSpeler.speler.id )
.then(res => {
this.cardExists = true;
this.successMessage = res;
console.log(res);
})
.catch(err => {
this.errorMessage = err;
this.cardExists = false;
});
},
The corresponding action, in actions.js is:
export const fetchSpelerCards = ({commit}, speler_id) => {
return new Promise((resolve, reject) => {
let status = '';
let data ={};
fetch(`api/cardsBySpeler/${speler_id}`)
.then(res => {
status = res.status;
data = res.json();
})
.then(res=>{
if ( status === 200) {
commit('SET_PLAYER_CARD', data);
resolve('Kaart gevonden');
}
else {
reject('Er is geen kaart beschikbaar')
}
});
})
}
In the vuex-store I see (viewed with VUE add-on of chrome browser):
currentSpelerCard: Promise
Yet, the response of the fetch command was successful, and the card was pulled in, as I see also in the console: status 200, I can see name, title, image address etc..
I was under the assumption that, when the promise eventually resolves, the store is updated and the card becomes available because of the:
computed: { ...mapState([ 'currentSpeler' ,'currentSpelerCard' ]),
Can anyone help me and explain what I am doing wrong?
fetchSpelerCards in Vuex commits SET_PLAYER_CARD with data, this will be a pending promise. You need to await the promise.
You can solve this in a few different ways.
Making the function async and await res.json() would be the easiest.
...
fetch(`api/cardsBySpeler/${speler_id}`)
.then(async res => {
status = res.status;
data = await res.json();
})
...

How can I make my section hide only after the submit button is pressed. right now the section disappears after I press one letter

vue.js, how can I make my section hide only after the submit button is pressed. right now the section disappears after I press one letter. I want the V-if and V-else to activate only after the user has submitted their request. or if routing the results on to a different page would easier id like to go that route also.
<template>
<div class="home">
<section id="whiteClawVideo" class="videoWrapper d-block w-100">
<div class="video-container fluid">
<iframe width="100%" height="600" src="https://www.youtube.com/embed/JORN2hkXLyM?
autoplay=1&loop=1" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope;
picture-in-picture" allowfullscreen></iframe>
</div>
</section>
<form #submit.prevent="SearchMovies()" class="search-box">
<input type="text" placeholder="What are you looking for? " v-model="search" />
<input type="submit" value="Search">
</form>
<div class="movies-list" v-if="search !== ''" >
<div class="container">
<div class="row">
<div class="col-3" v-for="movie in movies" :key="movie.imdbID">
<router-link :to="'/movie/'+movie.imdbID" class="movie-link">
<img class="movieImg" height="100%" :src="movie.Poster" alt="Movie Poster" />
<div class="type">{{ movie.Type }}</div>
<div class="detail">
<p class="year">{{movie.Year}}</p>
<h3>{{ movie.Title }}</h3>
<p>{{movie.imdbID}}</p>
</div>
</router-link>
</div>
</div>
</div>
</div>
<div class="container" v-else>
<MovieSection />
<SecondMovieSection />
</div>
</div>
</template>
import { ref } from 'vue';
import env from '#/env.js';
import MovieSection from '#/components/MovieSection.vue';
import SecondMovieSection from '#/components/SecondMovieSection.vue'
export default {
components: {
MovieSection,
SecondMovieSection
},
setup () {
const search = ref("");
const movies = ref([]);
const SearchMovies = () => {
if (search.value !== "") {
fetch(`API_HERE`)
.then(response => response.json())
.then(data => {
console.log(data)
movies.value = data.Search;
})
}
}
return {
search,
movies,
SearchMovies
}
}
}
Well, it closes once you type a single character because search is a model - it updates on every keypress you do within input it's bound to. What you wanna do instead is hide form based on whether you have entries in your movies array or not, so try changing v-if="search !== ''" to v-if="!movies.length"

Vee-Validate Showing a BlankPage when doing the configurations

I using Vue3.0 and also use Vee-validate to validate my form. But I don't know why it keep showing blank page just like in this picture
I already do what they said in the documentations, here's my code
<form class="wrap" id="signup-form col-lg-5" #submit.prevent="processForm">
<div class="row mb-5">
<router-link :to="{'name': 'Home'}">
<span class="iconify" data-icon="ion:return-up-back-outline" data-width="25" data-height="25"></span>
<button class="btn">Back</button>
</router-link>
</div>
<!-- full name -->
<div class="form-group row">
<label for="name">Full Name <span class="text-danger">*</span></label>
<ValidationProvider rules="positive|odd" v-slot="err">
<input type="text" class="form-control" v-model.trim="name">
<span>{{ err.errors[0] }}</span>
</ValidationProvider>
</div>
<!-- submit button -->
<div class="row d-flex align-items-center">
<button type="submit" class="btn btn-outline-dark col-sm-4">Submit</button>
<p style="cursor:pointer;" class="col-sm-7">
<router-link :to="{name:'Login'}">Has an account? Login</router-link>
</p>
</div>
</form>
And here's my script
<script>
import { ValidationProvider } from 'vee-validate';
import { extend } from 'vee-validate';
extend('odd', value => {
return value % 2 !== 0;
});
extend('positive', value => {
return value >= 0;
});
export default {
name: 'RegisterForm',
components: {
ValidationProvider
},
data: function(){
return{
name: '',
}
},
methods: {
processForm() {
this.$emit('form-submit',
{
'name': this.email,
'password': this.password,
})
}
}
}
</script>
What should I change from the code? By the way, Is Vee-Validator should be assigned in main.js?
Looks like you are using vee-validate v3.x, it isn't compatible with Vue 3
vee-validate v4 was released recently that supports Vue 3, but with a completely different API
https://vee-validate.logaretm.com/v4/

Method Updating Data Twice on Form Submission

I have a component that is a form that I input a name and it updates a value on a field on the backend based on which input the name is. Right now I have two inputs (host and scout) and they work fine if I just fill one input. My problem is, when I fill both inputs, the name on the host input will always get updated twice while the name on the scout field will work just fine. Not sure if I was clear enough.
Here is the code for the component so far
<template>
<div class="add-wave">
<h3>Add Wave</h3>
<div class="row">
<form #click.prevent="addwave()" class="col s12">
<div class="row">
<div class="input-field col s12">
<input type="text" v-model="host" />
<label class="active">Host</label>
</div>
</div>
<div class="row">
<div class="input-field col s12">
<input type="text" v-model="scout" />
<label class="active">Scout</label>
</div>
</div>
<button type="submit" class="btn">Submit</button>
<router-link to="/member" class="btn grey">Cancel</router-link>
</form>
</div>
</div>
</template>
<script>
import { db, fv } from "../data/firebaseInit";
export default {
data() {
return {
host: null,
scout: null
};
},
methods: {
addwave() {
this.addhost();
db.collection("members")
.where("name", "==", this.scout)
.get()
.then(querySnapshot => {
querySnapshot.forEach(doc => {
doc.ref.update({
scout: fv.increment(1),
total: fv.increment(1)
});
});
});
},
addhost() {
db.collection("members")
.where("name", "==", this.host)
.get()
.then(querySnapshot => {
querySnapshot.forEach(doc => {
doc.ref.update({
host: fv.increment(1),
total: fv.increment(1)
});
});
});
}
}
};
</script>
I'm not sure why is it updating twice only when I fill both input fields.