Unit testing DOM elements outside directive - jasmine

How to test DOM elements outside directive like add and remove 'active' class to the tabs based on input. Help me to write unit test case for angular.element('.active').removeClass('active');
<div ng-controller="myCtrl">
<div id="tabs">
<div id="tab1" class="active" tab-navigation>Tab 1</div>
<div id="tab2" tab-navigation>Tab 2</div>
<div id="tab3" tab-navigation>Tab 3</div>
</div>
<div class="active" id="tab">
<input type="text" ng-model=inputvalue" my-directive/>
<button value="submit"/>
</div>
</div>
app.directive('myDirective',function(){
return{
require:'ngModel',
link:function(scope,element,attr,ngModelCtrl){
ngModelCtrl.$parsers.unshift(function(inputValue)
{
if(inputValue==='') {
angular.element('.active').removeClass('active');
}
};
});

Related

Multiple reusable modals vue 3 - how to keep track of paging? be more in control of modal functions

I'm trying to create a reusable modal in Vue 3 using the composition API. I'm finding it difficult due to a lack of knowledge to keep track of the modals that are shown because at the end when I submit my data using Inertia with Laravel I want the errors to display on the relevant modal.
I want to be able to keep track of which modal is open. I want to be able to close specific modals and open specific modals with a method. I would like to display the modal page where errors occur. For example, page 1 of 3 contains validation errors. Or an alternative to clicking next and getting errors on the fly for the current scope?
Any suggestions are welcome.
Here is my reusable modal vue component:
<script setup>
import {onMounted, reactive, watch} from 'vue'
import {Modal} from 'bootstrap'
const modal = reactive({});
let props = defineProps({
id: {
type: String,
required: true,
},
showModal: {
type: Boolean,
default: false,
},
});
onMounted(() => {
modal.value = new Modal('#' + props.id);
})
watch(
() => props.showModal,
show => {
modal.value.show()
},
)
</script>
<template>
<teleport to="body">
<div
:id="id"
class="modal fade"
tabindex="-1"
aria-hidden="true"
>
<div class="modal-dialog modal-dialog-centered max_630">
<div class="modal-content">
<div
v-if="$slots.title"
class="modal-header"
>
<h5 class="modal-title">
<slot name="title"/>
</h5>
<a
type="button"
data-bs-dismiss="modal"
aria-label="Close"
><span
class="iconify"
data-icon="ant-design:close-outlined"
/></a>
</div>
<div
v-if="$slots.body"
class="modal-body"
>
<slot name="body"/>
</div>
<div
v-if="$slots.footer"
class="modal-footer"
>
<slot name="footer"/>
</div>
</div>
</div>
</div>
</teleport>
</template>
This is how im using the reusable modal by defining 3 of them for 3 pages of inputs and the final page being the submission:
<script setup>
import Modal from '#/Components/Modal';
import {defineExpose, ref} from 'vue'
import {useForm} from "#inertiajs/inertia-vue3";
import BreezeInput from '#/Components/Input.vue';
import BreezeLabel from '#/Components/Label.vue';
import InputError from '#/Components/InputError.vue';
import Button from '#/Components/Button';
const form = useForm({
company: {
brand_name: null,
trading_name: null,
registered_name: null,
reg_no: null,
vat_no: null,
email: null,
telephone: null,
website_url: null
},
address: {
line1: null
}
})
const submit = () => {
form.post(route('dealership.store'), {
onError: (err) => {
// form.errors
},
onSuccess: () => {
}
});
};
let props = defineProps({
showModal: {
type: Boolean,
default: false,
},
});
</script>
<template>
<Button
class="blue_bg_button"
#click="showModal = !showModal"
>
<span
class="iconify"
data-icon="dashicons:plus-alt2"
/>
{{ __('Create Dealership') }}
</Button>
<Modal :id="'page1'" :showModal="showModal">
<template #title>
Create New Dealership
</template>
<template #body>
<h6 class="font_600 mb-4">Dealership Information</h6>
<div class="row">
<div class="col-6">
<div class="form-wrapper-block mb-4">
<BreezeLabel class="form-label" for="brand_name" value="Brand Name"/>
<BreezeInput id="brand_name" type="text" class="form-control" v-model="form.company.brand_name" placeholder="Brand Name"/>
<InputError :message="form.errors['company.brand_name']"></InputError>
</div>
</div>
<div class="col-6">
<div class="form-wrapper-block mb-4">
<BreezeLabel class="form-label" for="trading_name" value="Dealership Trading Name"/>
<BreezeInput id="trading_name" type="text" class="form-control" v-model="form.company.trading_name" placeholder="Trading Name"/>
<InputError :message="form.errors['company.trading_name']"></InputError>
</div>
</div>
</div>
<div class="row">
<div class="col-6">
<div class="form-wrapper-block mb-4">
<BreezeLabel class="form-label" for="registered_name" value="Dealership Registration Name"/>
<BreezeInput id="registered_name" type="text" class="form-control" v-model="form.company.registered_name" placeholder="Dealership Registration Name"/>
<InputError :message="form.errors['company.registered_name']"></InputError>
</div>
</div>
<div class="col-6">
<div class="form-wrapper-block mb-4">
<BreezeLabel class="form-label" for="reg_no" value="Registration Number"/>
<BreezeInput id="reg_no" type="text" class="form-control" v-model="form.company.reg_no" placeholder="00/000/000"/>
<InputError :message="form.errors['company.reg_no']"></InputError>
</div>
</div>
</div>
<div class="row">
<div class="col-6">
<div class="form-wrapper-block mb-4">
<BreezeLabel class="form-label" for="vat_no" value="VAT Number"/>
<BreezeInput id="vat_no" type="text" class="form-control" v-model="form.company.vat_no" placeholder="4333455555"/>
<InputError :message="form.errors['company.vat_no']"></InputError>
</div>
</div>
<div class="col-6">
</div>
</div>
<hr>
<h6 class="font_600 mb-4">Location</h6>
<div class="form-wrapper-block mb-4">
<BreezeLabel class="form-label" for="line1" value="Address Line"/>
<BreezeInput id="line1" type="text" class="form-control" v-model="form.address.line1" placeholder="12 Harrington Street, Cape Town, Cape Town City Centre"/>
<InputError :message="form.errors['address.line1']"></InputError>
</div>
<div class="pagination-wrapper">
<div class="pagination">
<span class="active"></span>
<span></span>
<span></span>
</div>
</div>
</template>
<template #footer>
<button type="button" class="blue_bg_button" data-bs-dismiss="page1" data-bs-toggle="modal" data-bs-target="#page2">Next</button>
<button type="button" class="edit_button" data-bs-dismiss="modal">Cancel</button>
</template>
</Modal>
<Modal :id="'page2'">
<template #title>
Create New Dealership
</template>
<template #body>
<h6 class="font_600 mb-4">Dealership Contact Details</h6>
<div class="row">
<div class="col-6">
<div class="form-wrapper-block mb-4">
<BreezeLabel class="form-label" for="dealer_email" value="Dealership Email"/>
<BreezeInput id="dealer_email" type="email" class="form-control" v-model="form.company.email" placeholder="Dealership Email"/>
<InputError :message="form.errors['company.email']"></InputError>
</div>
</div>
<div class="col-6">
<div class="form-wrapper-block mb-4">
<BreezeLabel class="form-label" for="telephone" value="Contact Number"/>
<BreezeInput id="telephone" type="text" class="form-control" v-model="form.company.telephone" placeholder="012 234 6789"/>
<InputError :message="form.errors['company.telephone']"></InputError>
</div>
</div>
</div>
<div class="row">
<div class="col-6">
<div class="form-wrapper-block mb-4">
<BreezeLabel class="form-label" for="website_url" value="Dealership Website"/>
<BreezeInput id="website_url" type="text" class="form-control" v-model="form.company.website_url" placeholder="www.dealership.com"/>
<InputError :message="form.errors['company.website_url']"></InputError>
</div>
</div>
<div class="col-6">
</div>
</div>
<div class="pagination-wrapper">
<div class="pagination">
<span class="active"></span>
<span class="active"></span>
<span></span>
</div>
</div>
</template>
<template #footer>
<div class="d-flex align-items-center">
<a href="#" class="gray_7" data-bs-dismiss="modal" data-bs-toggle="modal" data-bs-target="#page1"><span class="iconify prev_ico" data-icon="ant-design:arrow-left-outlined"></span>
Previous</a>
</div>
<div>
<button type="button" class="edit_button" data-bs-dismiss="modal">Cancel</button>
<button type="button" class="blue_bg_button" data-bs-dismiss="modal" data-bs-toggle="modal" data-bs-target="#page3">Next</button>
</div>
</template>
</Modal>
<Modal :id="'page3'">
<template #title>
Create New Dealership
</template>
<template #footer>
<div class="d-flex align-items-center">
<a href="#" class="gray_7" data-bs-dismiss="modal" data-bs-toggle="modal" data-bs-target="#page2"><span class="iconify prev_ico" data-icon="ant-design:arrow-left-outlined"></span>
Previous</a>
</div>
<div>
<button type="button" class="edit_button" data-bs-dismiss="modal">Cancel</button>
<button type="submit" class="blue_bg_button" :disabled="form.processing" #click="submit()">Add dealership</button>
</div>
</template>
</Modal>
</template>

vue js in laravel..Computed method is undefined

I tried to get data but it says computed method is undefined in vue dev tool
my methods are
<script>
export default{
name:"about",
mounted(){
this.$store.dispatch('getFrontAbouts');
},
computed:{
about(){
return this.$store.getters.about;
}
},
}
</script>
store2.js file where i get those data by axios call
export default{
state: {
aboutData:[],
},
getters:{
about(state){
return state.aboutData;
},
},
actions:{
getFrontAbouts(data){
axios.get("get-front-about").then((response)=>{
data.commit('about',response.data.about);
}).catch((error)=>{
})
},
},
mutations: {
about(state,data){
return state.aboutData = data;
},
}
}
my controller file where i am fetching data
public function about(){
$about = About::where('publication_status',1)->orderBy('id','ASC')->take(1)->first();
return response()->json(['about',$about],200);
}
here is my vue component where computed about method is being executed
<div class="row topmargin bottommargin gutter-lg-50 align-items-center">
<div class="col-lg-12 p-lg-5">
<div class="heading-block border-bottom-0 mb-0">
<h2 class="nott font-weight-semibold mb-4 text-secondary" style="color: #1ABC9C;">Our Story</h2>
<p v-if="about">{{about.about_us}}</p>
<div class="row">
<div class="col-6 col-sm-6 mb-4">
<div class="counter color font-weight-semibold"><span data-from="1" data-to="3" data-refresh-interval="2" data-speed="600"></span>+</div>
<h5 class="mt-0 font-weight-medium">Branches</h5>
</div>
<div class="col-6 col-sm-6 mb-4">
<div class="counter color font-weight-semibold"><span data-from="1" data-to="37" data-refresh-interval="11" data-speed="900"></span>+</div>
<h5 class="mt-0 font-weight-medium">Single Studios</h5>
</div>
<div class="col-6 col-sm-6 mb-4">
<div class="counter color font-weight-semibold"><span data-from="1" data-to="21" data-refresh-interval="3" data-speed="1000"></span>+</div>
<h5 class="mt-0 font-weight-medium">Events per Month</h5>
</div>
<div class="col-6 col-sm-6 mb-4">
<div class="counter color font-weight-semibold"><span data-from="100" data-to="4500" data-refresh-interval="100" data-speed="1500"></span>+</div>
<h5 class="mt-0 font-weight-medium">Active Members</h5>
</div>
</div>
</div>
</div>
</div>
</div>
<div>
<div class="row justify-content-center topmargin-sm">
<div class="col-md-5 offset-md-1">
<h3 class="text-dark"><i class="icon-line-circle-check color mr-1 position-relative" style="top: 2px;color: #1ABC9C;"></i> Why do you choose DreamsEye?</h3>
<p v-if="about">{{about.choice_us}}</p>
</div>
<div class="col-md-5 pl-md-5">
<h3 class="text-dark"><i class="icon-line-circle-check color mr-1 position-relative" style="top: 2px;color: #1ABC9C;"></i> Our Address</h3>
<p v-if="about">{{about.address}}</p>
</div>
<div class="clear"></div>
</div>
</div>
here is my vue dev tool screenshot
enter image description here
here is my response screenshot
enter image description here
You are accessing the computed property using about, but the computed property is defined as About.
JavaScript is case sensitive.
First it is a typo change this About() to thisabout() . it is because vuejs is case sensitive.
Second as you are geting about in array type you need to loop through it to get the data of each column so try this
<div v-for="abt in about" :key="abt.id"class="heading-block border-bottom-0 mb-0">
<h2 class="nott font-weight-semibold mb-4 text-secondary" style="color: #1ABC9C;">Our Story</h2>
<p v-if="about">{{abt.about_us}}</p>
you guys just look at my methods and vue component...But the actual problem was in my controller where...
$about = About::where('publication_status',1)->orderBy('id','ASC')->take(1)->first();
return response()->json(['about',$about],200);
to
$about = About::where('publication_status',1)->orderBy('id','ASC')->take(1)->first();
return response()->json(['about'=>$about],200);

vuejs stop propagation of click when clicked outer div

I am trying to create a search show hide feature. I have a click event that shows the search bar, but if I click somewhere in the put it get removed again. I tried with click.stop but it doesn't work. I am using vue.js inside a laravel project.
Here is my code
<template>
<div>
<div class="menu_srch d-flex" #click.stop="dos">
<i class="fa fa-search search_btn"></i>
<div class="header_serch " v-if="showSearch">
<div class="header_serch_input">
<input type="" name="" placeholder="Search">
</div>
<div class="header_serch_i">
<i class="fa fa-search"></i>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data(){
return {
showSearch : false,
}
},
methods: {
dos(){
this.showSearch = !this.showSearch
}
},
}
</script>
using click.self doesn't even work.. dos method doesn't run when click.self is used.
Vue.js version : "^2.6.11"
You can capture the click event end to stop the propagation one level down.
<template>
<div>
<div class="menu_srch d-flex" #click="dos">
<i class="fa fa-search search_btn"></i>
<div #click.stop class="header_serch" v-if="showSearch">
<div class="header_serch_input">
<input type name placeholder="Search">
</div>
<div class="header_serch_i">
<i class="fa fa-search"></i>
</div>
</div>
</div>
</div>
</template>
Or you need to restructure your template.
<template>
<div>
<div class="menu_srch d-flex" #click="dos">
<i class="fa fa-search search_btn"></i>
</div>
<div class="header_serch" v-if="showSearch">
<div class="header_serch_input">
<input type name placeholder="Search">
</div>
<div class="header_serch_i">
<i class="fa fa-search"></i>
</div>
</div>
</div>
</template>

Cypress: can't log in in the Cypress browser

I'm trying to set up E2E testing of a Vue application with Cypress.
I can log into the app with my regular Chrome browser. However, the browser opened up by Chrome won't let me log in. Both the automatic login via Cypress and manual login fail.
Is there a setting I'm missing?
My Vue element:
<template>
<div class="d-flex justify-content-center">
<div class="field is-horizontal">
<div class="field-label is-normal">
<label class="label">Username</label>
</div>
<div class="field-body">
<div class="field">
<div class="control">
<input v-model="username" class="input" type="text"
placeholder="Your username">
</div>
</div>
</div>
</div>
<div class="field is-horizontal">
<div class="field-label is-normal">
<label class="label">Password</label>
</div>
<div class="field-body">
<div class="field">
<div class="control">
<input v-model="password" class="input" type="password"
placeholder="Your password">
</div>
</div>
</div>
</div>
<div class="field is-horizontal">
<div class="field-label">
<!-- Left empty for spacing -->
</div>
<div class="field-body">
<div class="field">
<div class="control text-center">
<button v-on:click="login()" class="button is-primary">
Login
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
My test file:
describe('Logging in', () => {
it('Logs in as admin', () => {
cy.visit('/')
.get('input[type="text"]')
.type('Admin')
.get('input[type="password"]')
.type('Pass1234')
.get('button').click()
.location().should((loc) => {
expect(loc.pathname).to.eq('/dashboard-main/dashboard');
})
})
})
Update: some suggestions here: https://github.com/cypress-io/cypress/issues/1759#issuecomment-391729559
Do you get to see anything during the e2e test when it runs? Like Cypress typing in that fields?
Besides the fact that I wouldn't use very generic locators, I would stop in the .click() and then check the new path with cy.url()

jquery ajax, array and json

I am trying to log some input values into an array via jquery and then use those to run a method server side and get the data returned as JSON.
The HTML looks like this,
<div class="segment">
<div class="label">
<label>Choose region: </label>
</div>
<div class="column w190">
<div class="segment">
<div class="input">
<input type="checkbox" class="radio" value="Y" name="area[Nationwide]" id="inp_Nationwide">
</div>
<div class="label ">
<label for="inp_Nationwide">Nationwide</label>
</div>
<div class="s"> </div>
</div>
</div>
<div class="column w190">
<div class="segment">
<div class="input">
<input type="checkbox" class="radio" value="Y" name="area[Lancashire]" id="inp_Lancashire">
</div>
<div class="label ">
<label for="inp_Lancashire">Lancashire</label>
</div>
<div class="s"> </div>
</div>
</div>
<div class="column w190">
<div class="segment">
<div class="input">
<input type="checkbox" class="radio" value="Y" name="area[West_Yorkshire]" id="inp_West_Yorkshire">
</div>
<div class="label ">
<label for="inp_West_Yorkshire">West Yorkshire</label>
</div>
<div class="s"> </div>
</div>
<div class="s"> </div>
</div>
I have this javascript the detect whether the items are checked are not
if($('input.radio:checked')){
}
What I dont know is how to get the values of the input into an array so I can then send the information through AJAX to my controller. Can anyone help me?
You can use jQuery's each() function.
$('input.radio:checked').each(function() {
//put each of the selected check boxes into an array
});
You need to serialize your input with - serialize()
var data = $('#MYFORM').serialize();

Resources