Set up Element Plus in Cypress component testing - cypress

I have read through Styling Components on the Cypress Guide and set up my component-index.html and component.ts.
My app structure is:
src/
├─ ...
├─ App.vue
├─ main.ts
cypress/
├─ ...
├─ support/
│ ├─ component.ts
│ ├─ component-index.html
index.html
...
main.ts
import { createApp } from "vue";
import "./styles/element/index.scss";
import ElementPlus from "element-plus";
import "element-plus/dist/index.css";
import App from "./App.vue";
import "./styles/style.scss";
import { createRouter, createWebHashHistory } from "vue-router";
import routes from "~pages";
import "virtual:fonts.css";
const router = createRouter({
history: createWebHashHistory(),
routes,
});
createApp(App)
//custom directive
//now we can use `v-focus-on-mount` on template elements
//to make it focus on mount.
.directive("focus-on-mount", {
mounted(element: HTMLElement) {
element.focus();
},
})
.use(ElementPlus)
.use(router)
.mount("#app");
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>CM</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
component-index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<title>Components App</title>
</head>
<body>
<div data-cy-root id="app"></div>
<script type="module" src="../../src/main.ts"></script>
</body>
</html>
I saw that I am mounting ElementPlus in main.ts so I included main.ts in my component-index.html just as I do in index.html. However, my el- components are not being rendered correctly.
Below is my cypress.config.ts if it helps. I couldn't find a way to change the devServer to include UI libraries like ElementPlus on the documentation.
import { defineConfig } from "cypress";
export default defineConfig({
projectId: "1dtt7y",
e2e: {
baseUrl: "http://localhost:3000",
setupNodeEvents(on, config) {
// implement node event listeners here
},
},
component: {
devServer: {
framework: "vue",
bundler: "vite",
},
},
});
So, the main question is:
How do I correctly mount ElementPlus when component testing in cypress?

Related

Vue doesn't render anymore components in production after moving from webpack to Vite

The vue method app.component() called on an app instance (i.e., obtained through createApp()) doesn't work anymore in production as expected (as does in the dev environment).
For example, the following code works in the dev environment but not in production:
app.js
import Foo from './Foo.vue';
const app = createApp({});
app.component('foo', Foo)
.mount('#app');
app.blade.php
<!DOCTYPE html>
<html lang="en">
<head>
#vite('resources/js/app.js')
</head>
<body>
<div id="app">
<foo />
</div>
</body>
</html>
Vue replaces the above div#app with <!---->.
However, the following code works fine in both:
app.js
import Foo from './Foo.vue';
createApp(Foo).mount('#app');
app.blade.php
<!DOCTYPE html>
<html lang="en">
<head>
#vite('resources/js/app.js')
</head>
<body>
<div id="app"></div>
</body>
</html>
Now, the problem is that I need the first js code working because I'm passing data from Blade to Vue components, or I would have to make a porting of multiple Blade files into Vue.
This is my vite.config.js:
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import vue from '#vitejs/plugin-vue';
export default defineConfig({
plugins: [
laravel({
input: [
'resources/js/app.js',
],
}),
vue({
template: {
transformAssetUrls: {
base: null,
includeAbsolute: false,
},
},
}),
],
});

[Vue warn]: Failed to resolve component: app at <App> Laravel 8 & Vue 3

I have the following problem which repeats a lot to me when using Vue 3 and Laravel somewhere. I'm just getting started and have a virtually clean app and can still see this issue exist. Namely, Vuejs 3 from Laravel 8 do not work for me.
I get an error in the console:
[Vue warn]: Failed to resolve component: app
at app.js:13797
app.js
require('./bootstrap');
import { createApp } from 'vue';
import App from './App.vue';
const app = createApp({App});
app.mount("#app");
App.vue
<template>
<h1>{{ greeting }}</h1>
</template>
<script>
export default {
setup: () => ({
greeting: 'Hello World from Vue 3!'
})
}
</script>
<style scoped>
</style>
webpack.mix.js
const mix = require('laravel-mix');
const tailwindcss = require('tailwindcss');
mix.js('resources/js/app.js', 'public/js')
.vue()
.sass('resources/sass/app.scss', 'public/css', {}, [tailwindcss('./tailwind.config.js')])
.version();
welcome.blade.php
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link href="{{ asset('css/app.css') }}" rel="stylesheet">
<title>Document</title>
</head>
<body>
<div id="app">
<app>
</app>
</div>
<script src="{{ url('js/app.js') }}"></script>
</body>
</html>
Please help me with this.
:)
It should be createApp(App), not {App}, which is a shorthand for {App: App}.

Laravel - Fresh VueJS and Inertia app giving error: Do not mount Vue to <html> or <body> - mount to normal elements instead

I have just done a fresh install of inertia on an app with vuejs (v2) and am getting this error:
[Vue warn]: Do not mount Vue to <html> or <body> - mount to normal elements instead.
But I don't see why it's trying to mount on those elements? As far as I can tell I've followed the inertia installation guide....
web.php
Route::get('test', function(){return \Inertia\Inertia::render('master');});
app-ihf.js
import { App, plugin } from '#inertiajs/inertia-vue'
import Vue from 'vue'
import { InertiaProgress } from '#inertiajs/progress'
Vue.use(plugin)
const el = document.getElementById('app')
new Vue({
render: h => h(App, {
props: {
initialPage: JSON.parse(el.dataset.page),
resolveComponent: name => require(`./Pages/${name}`).default,
},
}),
}).$mount(el)
InertiaProgress.init()
master.blade.php
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="/css/app-ihf.css">
<script src="{{ mix('/js/app-ihf.js') }}"></script>
</head>
<body>
#inertia
</body>
</html>
Can anyone see what's going wrong here? This is the html when you visit that route
<html><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="/css/app-ihf.css?id=fc17ae1fae0b57440a59">
<script src="/js/app-ihf.js?id=fa7eba2a2c660c498a3e"></script>
</head>
<body>
<div id="app" data-page="{"component":"master","props":{"errors":{}},"url":"\/test","version":"3993c0d73e25e92aa0e15607a6c438ef"}"></div>
</body></html>
I had the exact same issue and it's because I didn't put defer into the script tag so the JavaScript in app.js was running before the id="app" element existed on the page.
So in your case you need:
<script src="{{ mix('/js/app-ihf.js') }}" defer></script>

How to set vue component when root of site is opened

In my laravel 5.6/vue.js 2.5.7 / vuetify": "^1.0.8" I need to set vue component when root of site is opened
I mean when I run url
http://local-artists-rating.com
see url reopened
http://local-artists-rating.com/#/
It has navbar, footer defined in my pages, but not any content I defined in resources/assets/js/components/appRoot.vue.
In my resources/assets/js/app.js:
require('./bootstrap');
window.Vue = require('vue');
import Vue from 'vue'
import VueRouter from 'vue-router';
window.Vue.use(VueRouter);
...
import AppRoot from './components/appRoot.vue';
...
const routes = [
{
path: '/',
components: {
...
appRoot: AppRoot,
...
}
...
{path: '/not-found/:invalid_url?', component: NotFound, name: 'notFound'},
{path: '/login', component: AppLogin, name: 'appLogin'},
{path: '/', component: AppRoot, name: 'appRoot'},
}
...
const router = new VueRouter( {
mode: 'hash', // default
routes
})
router.beforeEach((to, from, next) => {
if (!to.matched.length) {
next( '/not-found/'+encodeURIComponent(to.path) );
} else {
next();
}
})
...
new Vue({ router, i18n,
data:{
app_title: '',
},
mixins : [appMixin],
created() {
}, // created() {
mounted() {
}, // mounted(){
} ).$mount('#app') // new Vue({ router,
If I commented line :
path: '/',
at top of routes definitions, I got error in console:
app.js?dt=1529909735:73635 Uncaught Error: [vue-router] "path" is required in a route configuration.
at assert (app.js?dt=1529909735:73635)
at addRouteRecord (app.js?dt=1529909735:74771)
at app.js?dt=1529909735:74741
at Array.forEach (<anonymous>)
at createRouteMap (app.js?dt=1529909735:74740)
at createMatcher (app.js?dt=1529909735:74961)
at new VueRouter (app.js?dt=1529909735:76055)
at Object._typeof (app.js?dt=1529909735:4945)
at __webpack_require__ (app.js?dt=1529909735:20)
at Object.<anonymous> (app.js?dt=1529909735:50854)
In my resources/views/layouts/app.blade.php:
<!DOCTYPE html>
<html lang="{{ app()->getLocale() }}">
<head>
<?php $current_template= 'artists_rating_light' ?>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="Cache-Control" content="no-cache">
<!-- CSRF Token -->
<meta name="csrf-token" content="{{ csrf_token() }}">
<title id="app_title">{{ config('app.name', 'Laravel') }}</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/docsearch.js/2/docsearch.min.css">
<link href="https://use.fontawesome.com/releases/v5.0.8/css/all.css" rel="stylesheet">
</head>
<body>
<div id="app">
<backend-app-layout></backend-app-layout>
</div>
#include('layouts.footer')
<script src="{{ asset('js/app.js' ) }}{{ "?dt=".time() }}"></script>
</body>
</html>
Which is the right way ?
Thanks!

How do i integrate vue-router and laravel?

Currently i am using vue and laravel together.Vue for frontend and laravel for backend api.I am trying to use vue-router with laravel but couldnt make it work.
What i am trying to do is reach http://localhost/ec/public/#/login
app.js:
require('./bootstrap');
window.Vue = require('vue');
import Router from './routes.js'
Vue.component('example-component', require('./components/ExampleComponent.vue'));
Vue.component('login', require('./components/Login.vue'));
Vue.component('register', require('./components/Register.vue'));
const app = new Vue({
el: '#app',
router:Router
});
I have created a file in same dir app.js called routes.js:
import VueRouter from 'vue-router'
import Vue from 'vue'
import Login from './components/Login.vue'
Vue.use(VueRouter);
const router = new VueRouter({
routes:[
{
path:"/login",
component:Login
}
]
})
export default router
welcome.blade.php:
<!doctype html>
<html lang="{{ app()->getLocale() }}">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="csrf-token" content="{{ csrf_token() }}">
<title> site</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<!-- Fonts -->
<link href="https://fonts.googleapis.com/css?family=Raleway:100,600" rel="stylesheet" type="text/css">
</head>
<body>
<div id="app">
</div>
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
<script src="{{ asset('js/app.js') }}"></script>
</body>
</html>
If i ad to welcome.blade.php i get component not registered error
You need to call <router-view></router-view> within your welcome.blade.php
Update
I could say that the order of the import, try to import Vue 1st then import vue-router. Otherwise you can't skip the <router-view></router-view> because it is an element of vue-router itself.

Resources