How can I create role based testing in Cypress? - vue.js

I have a project that needs to be tested via Cypress. I am new in "Cypressing" by the way..
I have problem to find a solution about role-based testing where something like this happen:
If the xhr response gave a user data with role admin, it will redirect to dashboard/admin. Otherwise, if the xhr response gave a user data a role user, it will redirect to dashboard/user.
After that, each views may have different actions & behavior regarding to what kind of user who has logged in.
Please have a look at my script:
const BASE_URL = Cypress.env('BASE_URL')
const APP_NAME = Cypress.env('APP_NAME')
const AUTH_ID = Cypress.env('AUTH_ID')
const PASSWORD = Cypress.env('PASSWORD')
describe('Login Test', () => {
it('can perform a login action', () => {
cy.visit(BASE_URL)
cy.contains(APP_NAME)
cy.get('input[name="contact"]')
.type(AUTH_ID)
.should('have.value', AUTH_ID)
cy.get('input[name="password"]')
.type(PASSWORD)
.should('have.value', PASSWORD)
cy.get('#submit-button').click()
cy.url().should('contain', 'dashboard')
})
})
and please have a look at my Vue.js script too:
<template>
<div id="login">
<div class="login-card p-4">
<h1 class="text-center font-weight-bold text-primary py-5">STTKD</h1>
<!-- phone number input -->
<div class="form-group">
<label for="contact">Nomor Telepon</label>
<input
name="contact"
type="number"
class="form-control"
min="0"
placeholder="08xxx atau 628xxxx"
v-model="user.contact"
/>
</div>
<!-- password-input -->
<div class="form-group">
<label for="password">Password</label>
<input
name="password"
type="password"
class="form-control"
placeholder="Masukkan password"
v-model="user.password"
/>
</div>
<div class="form-group text-right">
Forgot password?
</div>
<!-- login-button -->
<div class="form-group">
<button
id="submit-button"
type="button"
class="btn btn-primary btn-block"
#click="onSubmit"
>LOGIN</button>
</div>
<div class="form-group text-center">
<p class="mb-0">
Don't have account?
<router-link :to="{ name: 'register' }" class="text-primary">Create a new one!</router-link>
</p>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
user: {
contact: "",
password: ""
}
};
},
methods: {
onSubmit() {
axios
.post("auth/login", this.user)
.then(resp => {
VueCookies.set("access_token", resp.data.access_token);
VueCookies.set("token_type", resp.data.token_type);
VueCookies.set("expires_at", resp.data.expires_at);
// redirect with" user" param if the roles array from the response includes "user"
if (resp.data.user.roles.includes("user")) {
this.$router.replace({
name: "dashboard",
params: {
role: "user"
}
});
return;
}
// else, redirect with "admin" param
this.$router.replace({
name: "dashboard",
params: {
role: "admin"
}
});
})
.catch(err => console.error(err));
}
}
};
</script>
As you see above, its running without problem but I have no idea about what to do next because the user behavior is kindof dynamic.
Please help me to solve this problem, any references are good for me if there is.
Thanks in advance.

Related

testing api sending OPTIONS method and getting 405 error [duplicate]

This question already has an answer here:
FastAPI's RedirectResponse doesn't work as expected in Swagger UI
(1 answer)
Closed 5 months ago.
Im new to vue and nuxt, im using this ones to connect them to my API made with fastapi, and whenever i try to create an account via my API with the vue form i get this error
127.0.0.1:52137 - "OPTIONS /user HTTP/1.1" 405 Method Not Allowed
I've seen that sometimes axios sends an OPTION method to "test" the api if i get it.. But how do i solve this problem ?
Im new to this so do not hesitate to ask me more files/code.
Here is the Post method that im trying to reach and my registration page on VUE.
#app.post("/user", response_model=_schemas.UserBis)
async def create_user(user: _schemas.UserIn, db: _orm.Session = fastapi.Depends(_services.get_db)):
db_user_email = await _services.get_user_by_email(email=user.email, db=db)
if db_user_email:
raise fastapi.HTTPException(
status_code=400, detail="User with that email already exists"
)
db_user_username = await _services.get_user_by_username(username=user.username, db=db)
if db_user_username:
raise fastapi.HTTPException(
status_code=400, detail="User with that email already exists"
)
db_user_pseudo = await _services.get_user_by_pseudo(pseudo=user.pseudo, db=db)
if db_user_pseudo:
raise fastapi.HTTPException(
status_code=400, detail="User with that pseudo already exists"
)
user = await _services.create_user(user=user, db=db)
return _schemas.UserBis(data=user)
VUE:
<template>
<section class="section">
<div class="container">
<div class="columns">
<div class="column is-4 is-offset-4">
<h2 class="title has-text-centered">Register!</h2>
<Notification :message="error" v-if="error"/>
<form method="post" #submit.prevent="register">
<div class="field">
<label class="label">Username</label>
<div class="control">
<input
type="text"
class="input"
name="username"
v-model="username"
required
/>
</div>
</div>
<div class="field">
<label class="label">Pseudo</label>
<div class="control">
<input
type="text"
class="input"
name="pseudo"
v-model="pseudo"
required
/>
</div>
</div>
<div class="field">
<label class="label">Email</label>
<div class="control">
<input
type="email"
class="input"
name="email"
v-model="email"
required
/>
</div>
</div>
<div class="field">
<label class="label">Password</label>
<div class="control">
<input
type="password"
class="input"
name="password"
v-model="password"
required
/>
</div>
</div>
<div class="control">
<button type="submit" class="button is-dark is-fullwidth">Register</button>
</div>
</form>
<div class="has-text-centered" style="margin-top: 20px">
Already got an account? <nuxt-link to="/login">Login</nuxt-link>
</div>
</div>
</div>
</div>
</section>
</template>
<script>
import Notification from '~/components/Notification'
export default {
components: {
Notification,
},
data() {
return {
username: '',
pseudo: '',
email: '',
password: '',
error: null
}
},
methods: {
async register() {
try {
await this.$axios.post('user', {
username: this.username,
pseudo: this.pseudo,
email: this.email,
password: this.password
})
await this.$auth.loginWith('local', {
data: {
email: this.email,
password: this.password
},
})
this.$router.push('/')
} catch (e) {
this.error = e.response.data.message
}
}
}
}
</script>
https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
Any non simple POST request triggers a pre flight check (OPTIONS request) to confirm the action is supported. Your API will need to be modified to allow these requests.
I found a slution to my problem here: https://stackoverflow.com/a/66460861/18428648
Allowing all origins solved my problem, just added a few lines of code to my FastAPI API.

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();
})
...

I am unable to pass my v-model data to my backend for radio button type in vue.js ,How to pass that checked radio button value to my backend ??

I developed one page which is responsible for Registering the users previously i submitted the form without radio buttons, now i need to add radio buttons based on checked type button that value should be sent to the backend ,i am unable to figure out where did i mistaken please help me to fix this issue
Register.vue
<template>
<div class="main">
<div v-if="flag==true" 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" v-on:click="flip();" 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" autocomplete="off" 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" autocomplete="off" v-model="mobile" id="tel" pattern="^\d{10}$" required>
</div>
<div class="role-btns">
<input type="radio" id="user" value="user" name="role" v-model="roleUser" >
<label for="user" class="radio-label">user</label>
<input type="radio" id="admin" value="admin" name="role" v-model="roleUser">
<label for="admin">admin</label>
</div>
<button class="btn-section" id="btn" type="submit">Signup</button>
</form>
</div>
</div>
<Login v-if="flag==false" />
</div>
</template>
<script>
import service from '../service/User'
export default {
name: 'Register',
components: {
Login: () => import('./Login.vue')
},
data() {
return {
fullName: '',
email: '',
password: '',
mobile: '',
roleUser:'',
password_type: "password",
isLogin: false,
isPasswordVisible: false,
flag: true,
title: 'Online Book Shopping'
}
},
methods: {
flip() {
this.flag = !this.flag;
},
togglePassword() {
this.password_type = this.password_type === 'password' ? 'text' : 'password'
this.isPasswordVisible = !this.isPasswordVisible
},
handlesubmit() {
let userData = {
fullName: this.fullName,
email: this.email,
password: this.password,
mobile: this.mobile
}
service.userRegister(userData).then(response => {
if (response.status == 201) {
alert("user registered successfully");
this.$refs.myForm.reset();
this.$router.push('/login');
}
return response;
}).catch(error => {
alert("invalid credentials");
return error;
})
}
}
}
</script>
<style lang="scss" scoped>
#import "#/styles/Register.scss";
</style>
let userData = {
fullName: this.fullName,
email: this.email,
password: this.password,
mobile: this.mobile,
roleUser:this.roleUser
}

Cannot read property 'post' of undefined, in nuxt js

I am making registration form in nuxt js, it takes data from api, I have installed axios and auth module, I wrote base url in nuxt.config.js file. It shows TypeError: Cannot read property 'post' of undefined
```template>
<div>
<section class="content">
<div class="register_form m-auto text-center form-group">
<form method="post" #submit.prevent="register" >
<h1 class ="register_title">REGISTER</h1>
<h2 class="register_text">PLEASE REGISTER TO USE THIS WEBSITE</h2>
<input class="form-control" type="text" placeholder = 'USERNAME' v-model="username" name="username" required>
<input class="form-control" type="password" placeholder = 'PASSWORD' v-model="password" name="password" required>
<button type="submit" to="#" class="register_btn">
REGISTER
</button>
</form>
</div>
</section>
</div>
</template>
<script>
export default {
layout: 'loginLayout',
data(){
return {
username: '',
password: ''
}
},
methods: {
async register() {
try {
await this.$axios.post('register', {
username: this.username,
password: this.password
})
this.$router.push('/')
}
catch (e) {
console.log(e)
}
}
}
}
</script>```
try to use
await this.$axios.$post instead of await this.$axios.$post

vue js get multiple values from inputs

So I have 2 blocks of HTML, each containing 2 input fields and when submitting the form, I want to get all values from the inputs, and then create an object from the values...
As of know I've done it with plain vanilla JS and it works as it should, however if feels like to touching the DOM a bit to much, and also are very much depending on a specific DOM struckture, and therefore I was thinking there must be a better way, the VUE way so to speak, however im a bit stuck on how to do this the VUE way, which is why posting the question here in hope of getting some useful tips :)
HTML:
<form novalidate autocomplete="off">
<div class="input-block-container">
<div class="input-block">
<input type="text" placeholder="Insert name" name="name[]" />
<input-effects></input-effects>
</div>
<div class="input-block">
<input type="email" placeholder="Insert email address" name="email[]" />
<input-effects></input-effects>
</div>
</div>
<div class="input-block-container">
<div class="input-block">
<input type="text" placeholder="Insert name" name="name[]" />
<input-effects></input-effects>
</div>
<div class="input-block">
<input type="email" placeholder="Insert email address" name="email[]" />
<input-effects></input-effects>
</div>
</div>
<button class="button button--primary" #click.prevent="sendInvites"><span>Send</span></button>
</form>
JS:
methods: {
createDataObject() {
let emailValues = document.querySelectorAll('input[type="email"]');
emailValues.forEach((email) => {
let name = email.parentNode.parentNode.querySelector('input[type="text"]').value;
if(email.value !== "" && name !== "") {
this.dataObj.push({
email: email.value,
name
});
}
});
return JSON.stringify(this.dataObj);
},
sendInvites() {
const objectToSend = this.createDataObject();
console.log(objectToSend);
//TODO: Methods to send data to server
}
}
You can provide data properties for each of your inputs if you have static content.
data: function() {
return {
name1: '',
email1: '',
name2: '',
email2: ''
}
}
Then use them in your template:
<input type="text" placeholder="Insert name" v-model="name1" />
Access in method by this.name1
Try this
<div id="app">
<h1> Finds </h1>
<div v-for="find in finds">
<input name="name[]" v-model="find.name">
<input name="email[]" v-model="find.email">
</div>
<button #click="addFind">
New Find
</button>
<pre>{{ $data | json }}</pre>
</div>
Vue Component
new Vue({
el: '#app',
data: {
finds: []
},
methods: {
addFind: function () {
this.finds.push({ name: '', email: '' });
}
enter code here
}
});