Quasar2 Vue3 Cypress Cannot read properties of undefined (reading 'deep') - cypress

I have the following component test:
import AutoGeneratedPage from '../../../src/components/AutoGenerate/AutoGenerate.vue'; // <= note the absence of `.vue` extension, here we are importing the JS/TS part of a Double File Component
describe('AutoGenerated Page tests', () => {
it('Auto generated page from JSON should contain all the UI Elements', () => {
cy.mount(AutoGeneratedPage);
cy.get('[data-test="toggle-setting-0"]').eq(false);
cy.get('[data-test="toggle-setting-0"]').focus().click();
cy.get('[data-test="toggle-setting-0"]').eq(true);
cy.get('[data-test="dropdown-setting-3"]').should('have.text', 'Option 1');
cy.get('[data-test="dropdown-setting-3"]').should('have.text', 'Option 2');
cy.get('[data-test="dropdown-setting-3"]').should('have.text', 'Option 3');
});
})
and bump into the following error when running the component test:
What do I miss? https://github.com/khteh/quasar

The first assertion needs changing:
cy.get('[data-test="toggle-setting-0"]').eq(false);
cy.get('[data-test="toggle-setting-0"]').focus().click();
cy.get('[data-test="toggle-setting-0"]').eq(true);
change to
cy.get('[data-test="toggle-setting-0"]').invoke('val').should('eq', false);
cy.get('[data-test="toggle-setting-0"]').focus().click();
cy.get('[data-test="toggle-setting-0"]').invoke('val').should('eq', true);
because .eq(number) is a Cypress command for taking the nth item in a group.
The error Cannot read properties of undefined (reading 'deep') is due to the deep rendering (i.e nested components) in the AutoGenerate.vue component.
If you comment out the child components, the test succeeds.
<div v-for="(field, index) in layoutObj.data" :key="index">
<span>{{field.name}}</span>
<!-- <toggle-setting
v-if="field.type === 'toggle'"
:name="field.name"
:fieldName="field.fieldName"
:description="field.description"
:data-test="`toggle-setting-${index}`"
/>
<pop-up-edit-setting
v-if="field.type === 'popUpEdit'"
:dataType="field.dataType"
:name="field.name"
:fieldName="field.fieldName"
:hint="field.hint"
:data-test="`popup-edit-setting-${index}`"
/>
<drop-down-setting
v-if="field.type === 'dropDown'"
:name="field.name"
:description="field.description"
:fieldName="field.fieldName"
:internalOptions="internalOptions"
:data-test="`dropdown-setting-${index}`"
/> -->
</div>
Of course, the child components are required, but I thought I'd post this in case it gives you clues.
In any case, the Cypress component test is configured correctly, this is the config I used.
const { defineConfig } = require("cypress");
const webpackConfig = require("./webpack.config");
module.exports = defineConfig({
e2e: {
...
},
component: {
devServer: {
framework: "vue",
bundler: "webpack",
webpackConfig,
},
specPattern: 'test/cypress/components/**/*.cy.{js,jsx,ts,tsx}',
indexHtmlFile: 'test/cypress/support/component-index.html',
},
});
Will add to this if I find out the problem with deep-nested components.

Remove mount() and all references to quasar UI stuff. mount() must only be used for Component Tests. Not E2E tests.

Related

How to stop cypress from closing browser after each test case (it)?

I have a cy.js file like this
/// <reference types="cypress" />
context("Dummy test cases", () => {
it("open Google", () => {
cy.visit("www.google.com");
});
it("search a keyword", () => {
cy.get(".gLFyf").type("cypress{enter}");
});
});
As you can see I've 2 test cases. 1 is to open a website and the other is to do other tasks.
But the problem is that after finishing the first 'it' (test case 1), the browser closes and then the next case fails because there is no active browser.
Can you help me how to stop cypress from closing the browser after the execution of each test case?
I found Cypress is quite opinionated about some things, one at the top of the list is "test isolation" which means one test must not influence another test.
Note each it() is a test.
To make your code work, you must turn off test isolation.
If the cypress.config.js file add the option
const { defineConfig } = require("cypress");
module.exports = defineConfig({
e2e: {
setupNodeEvents(on, config) {
// implement node event listeners here
},
testIsolation: false,
},
})
Same if you are using typescript.
This got added in the new Version Cypress 12.0.0, in their
Changelogs its at the feature section:
Added a new configuration option called testIsolation, which defaults to true.
As #Joylette already said, in your config file just use testIsolation: false to deactivate it. If you ever use an older version use testIsolation: off, they renamed it in the newest version.

Cypress: How to add functions to Mocha Context?

I am trying add functions to this (which is a Mocha Context) in tests, so I can do e.g.
describe('my spec', () => {
it('should work', function () {
this.sayHelloWorld();
})
})
In an empty folder I call
yarn add cypress
yarn cypress open
so that default config files are created. It also creates a sample test in cypress/e2e/spec.cy.js.
I can run the sample test without problem. But if I add
import { Context } from "mocha";
to cypress/support/e2e.js I get
Error: Webpack Compilation Error
./cypress/support/e2e.js
Module not found: Error: Can't resolve 'mocha' in '...\support'
resolve 'mocha' in '...\support'
Parsed request is a module
So I installed Mocha, the same version which is in devDependencies of Cypress (see package.json):
yarn add mocha#3.5.3
My package.json now looks like this:
{
"dependencies": {
"cypress": "^10.4.0",
"mocha": "3.5.3"
}
}
Now that import line passes. But this fails:
import { Context } from "mocha";
Context.prototype.sayHelloWorld = () => console.log("hello world");
Error:
> Cannot read properties of undefined (reading 'prototype')
Why is that? In comparison adding something to String.prototype works.
Also in comparison: Again in an empty folder:
yarn add mocha#3.5.3
And in test/test.js:
const { Context } = require("mocha");
it("should work", function () {
Context.prototype.sayHelloWorld = () => console.log("hello world");
this.sayHelloWorld();
});
Now yarn mocha works (says hello world).
What is going on in Cypress? Possibly a bug?
Solution:
no import { Context } from "mocha";
add functions like that:
Mocha.Context.prototype.sayHelloWorld = function () {
cy.log('hello world');
};

Cypress shadow-root inside of shadow-root

How do I find the element that is inside of shadow-root which is inside of other shadow-root? I'm new to this and tried .shadow() function.
You don't have to use .shadow() every time. Go to cypress.json file and add the following includeShadowDom: true.
Now with this added all your get, find commands will automatically traverse through the shadow dom and reach the element.
cy.get('some-element').should('be.visible')
If you're using Cypress v10, then the configuration is in the file cypress.config.js and the format for setting global shadow enabling is
const { defineConfig } = require("cypress");
module.exports = defineConfig({
e2e: {
...
},
...
includeShadowDom: true
})
Or use test-specific configuration
it('tests some shadow dom elements', {includeShadowDom: true}, () => {
...
})

Cypress asynchronous execution returns 4 same assertion

I have a question.
I am using Cypress for my automation and I started using async and await for my tests.
I am using POM design pattern.
My question:
If I execute the following test:
test.spec.ts class (test class)
import { login_po } from "../pom/1.Chiquito/login_po";
const pom = new login_po()
describe("Put some name here.", async() => {
it('TestCase1', async () => {
await pom.navigateTo();
});
});
My POM class.
export class login_po {
navigateTo() {
cy
.visit(`https://chiquito-qa.omnifitrgsites.co.uk/`)
.url()
.should('be.equal', 'https://chiquito-qa.omnifitrgsites.co.uk/').then(() => this.verifyAfterLogin());
}
verifyAfterLogin() {
cy.get('.header__logo-img');
}
}
When I execute the test - Cypress makes 4 (same) assertions.
If I remove 'async' - 'await' from the test class - Cypress makes 1 assertion.
import { login_po } from "../pom/1.Chiquito/login_po";
const pom = new login_po()
describe("Put some name here.", () => {
it('TestCase1', () => {
pom.navigateTo();
});
});
Why this is happening?
Cypress commands are not promises, and their interaction with async/await will not happen as you expect. Additionally, while POM is feasible and reasonable to do within Cypress, it is recommended that you use App Actions instead of a POM.

Cypress - New test file not showing in cypress UI

Creating a new test file in Cypress folder integration is not showing in the Cypress UI.
In this print-screen I have created a new file called: NewTest.spec.js (in green). It is not showing in Cypress.
It used to work
In case you have a testFiles list defined inside the cypress.json file, Cypress will not include all of spec files found within the integration folder and will instead use that list to populate the suite.
So, check cypress.json and add the new spec file to the appropriate place in the order.
"testFiles": [
"FirstTest.spec.js",
"NewTest.spec.js",
"ThirdTest.spec.js"
]
In the latest version of Cypress, make sure your file is named [filename].cy.js
This is for cypress 10 and above - You can also specify the spec pattern in cypress.config.js as below, for all of the files to show up.
No need to name the files as [filename].cy.js for these to show up.
const { defineConfig } = require("cypress");
module.exports = defineConfig({
e2e: {
specPattern: "cypress/e2e/**/*.*",
setupNodeEvents(on, config) {
// implement node event listeners here
},
},
});
In cypress.config.ts you need to define your pattern with specPattern:
Like this:
import { defineConfig } from "cypress";
export default defineConfig({
e2e: {
specPattern: 'cypress/integration/*.cy.ts', // write your pattern here
setupNodeEvents(on, config) {
// implement node event listeners here
},
},
});

Resources