When I run the test, the specified URL does not open, even though it is entered correctly and set in BaseUrl in cypress.config.js:
> module.exports = defineConfig({ e2e: {
> "projectId": "fi4fhz",
> "viewportHeight": 1080,
> "viewportWidth": 1920,
> specPattern: 'cypress/e2e/**/*.{js,jsx,ts,tsx}',
> baseUrl: 'https://pha.mm.int:6001/',
>
> setupNodeEvents(on, config) {
>
> }, },
In every test file I have this:
beforeEach(() => {
cy.runInWeb();
});
and in commands.js I have:
Cypress.Commands.add("runInWeb", () => { cy.visit(Cypress.e2e().projectUrl) });
and in cypress.config.js I have:
"projectUrl": "https://pha.mm.int:6001/"
but it's not functioning. Where is the problem?
The baseUrl value https://pha.mm.int:6001/ shows up in the browser address bar because Cypress uses it to configure set up the runner.
But the <iframe> containing the web page under test isn't changed until you perform
the first cy.visit('/').
This is to allow you to execute code before the page load occurs, like cy.intercept() and cy.fixture().
Yes you visit() but not in the right way, if you store your url in env variable you get it out like this:
Cypress.Commands.add("runInWeb", () => { cy.visit(Cypress.env('projectUrl')) });
and you store the default like this:
// cypress.config.js
const { defineConfig } = require("cypress");
module.exports = defineConfig({
e2e: {
setupNodeEvents(on, config) {
// implement node event listeners here
},
specPattern: 'cypress/e2e/**/*.cy.{js,jsx,ts,tsx}'
},
env: {
projectUrl: 'https://pha.mm.int:6001/',
},
})
or cypress.env.json
{
"projectUrl": "https://pha.mm.int:6001/"
}
Ensure that you have this beforeEach prior to running your it test blocks. You need to use cy.visit('/') before each of your tests.
beforeEach(() => {
//cy.session(id, setup); Use is if you want to stay logged into your application
cy.visit('/);
cy.wait(100);
});
If you're interested in using a session, visit the cypress docs here:
Based on the information in the question, I assume that you did not include a cy.visit() command. Without that command, Cypress does not know to open a webpage.
Related
I am performing playwright test automation using fixtures and have files as below. While running its working as expected so i know its not a playwright issue. My question is when i ctrl+click on loadAndLogin under test.step in TC_123.js with VS code, i am expecting it to navigate to the loadAndLogin method in LoadAndLogin.js. But this is not happening and how do i fix this?
// basePage.js
const base = require('#playwright/test');
const { LoadAndLogin } = require('../utilities/LoadAndLogin');
exports.test = base.test.extend({
loadAndLogin: async ({ page }, use) => {
await use(new LoadAndLogin(page));
},
});
exports.expect = base.expect;
// LoadAndLogin.js
const { test, expect } = require('#playwright/test');
const { LoginPage } = require('../pages/LoginPage');
exports.LoadAndLogin = class LoadAndLogin {
constructor(page) {
this.page = page;
this.loginPage = new LoginPage(page);
}
async loadAndLogin() {
// code to Login to the application
}
}
// TC_123.js
const { test } = require('../../fixtures/basePage');
test('TC_123', async function ({page, loadAndLogin}) {
await test.step('01_Load application and login', async function () {
await loadAndLogin.loadAndLogin();
});
});
I tried checking with playwright team in github and below was the response
https://github.com/microsoft/playwright/issues/20218
You need to either add // #ts-check and javascript type annotations and use type script to make the navigation work for fixtures. VSCode fails to infer all the types looking at the javascript code alone. Closing this issue as it is not a playwright defect. Also feel free to open a request for VS Code team.
i tried using //#ts-check and even created jsconfig.json but still i am not able to understand why it is not working
So, you know when you access a view with django rest api on the browser, you get an html page, and when you send something like an ajax request, you get the json? I'm trying to figure out how to mess with the proxy setting for vite, but I can't find a single decent documentation around it. I want to redirect '/' to 'http://localhost:8000/api', but there's really weird behavior going on.
If I have a route on localhost:8000/api, I can do:
//vite.config.js
export default defineConfig({
plugins: [vue()],
server: {
proxy: {
//Focus here
'/api': {
target: 'http://localhost:8000',
changeOrigin: true,
rewrite: (path) => { console.log(path); return path.replace('/^\/api/', '') }
}
}
}
})
//todo-component.vue
export default {
data() {
return {
todos: []
}
},
components: {
TodoElement
},
beforeCreate() {
//Focus here as well
this.axios.get('/api').then((response) => {
this.todos = response.data
})
.catch((e) => {
console.error(e)
})
}
}
This will return the json response as expected. However, if I try to make it so that '/' routes to 'localhost:8000/api/', like this:
export default defineConfig({
plugins: [vue()],
server: {
proxy: {
//change here
'/': {
target: 'http://localhost:8000/api',
changeOrigin: true,
rewrite: (path) => { console.log(path); return path.replace('/^\/api/', '') }
}
}
}
})
import TodoElement from "./todo-element.vue"
export default {
data() {
return {
todos: []
}
},
components: {
TodoElement
},
beforeCreate() {
//change here
this.axios.get('/').then((response) => {
this.todos = response.data
})
.catch((e) => {
console.error(e)
})
}
}
It just spews out the html version of the api view, but with no styling, with a bunch of errors
No idea what to do. If someone could explain how this proxy works, i'd really love it. I don't want to keep writing "api/", and it'd be really valuable if I can manage to understand how this works.
You are a bit confusing things and I will try to show you why.
If you redirect root path / to /api, every request sent to your app running at http://localhost:3000 will be forwarded to http://localhost:8000/api. It mean that you will not be able to serve anything from the running app, but you will get an answer from the configured endpoint (localhost:8000/api) for every request.
To understand easily what is going on, keep in mind that this vite config option (server.proxy) act like a reverse proxy. As example, I take the favicon.ico resource of your app.
With your current configuration, when from your browser you try to access your app, the /favicon.ico (and all other resources) is then loaded from http://localhost:8000/api/favicon.ico and not anymore from your app running at http://localhost:3000/favicon.ico.
This explain all the errors in the console. Again, for example, /static/rest_framework is loaded from http://localhost:8000/api/ and not http://localhost:3000/.
The documentation is quite clear, it's just a matter of understanding what a http-proxy is. To get more information you can head to https://github.com/http-party/node-http-proxy#core-concept
I am learning Cypress along with JavaScript. I am running into a problem that I am not certain how to search it into documentation. The site I started testing has the typical wait issues so I encountered a very good solution here.
Now my test is looking in this way
/// <reference types="Cypress" />
let appHasStarted
function spyOnAddEventListener (win) {
// win = window object in our application
const addListener = win.EventTarget.prototype.addEventListener
win.EventTarget.prototype.addEventListener = function (name) {
if (name === 'change') {
// web app added an event listener to the input box -
// that means the web application has started
appHasStarted = true
// restore the original event listener
win.EventTarget.prototype.addEventListener = addListener
}
return addListener.apply(this, arguments)
}
}
function waitForAppStart() {
// keeps rechecking "appHasStarted" variable
return new Cypress.Promise((resolve, reject) => {
const isReady = () => {
if (appHasStarted) {
return resolve()
}
setTimeout(isReady, 0)
}
isReady()
})
}
describe('Main test suite', () => {
beforeEach(() => {
cy.visit('http://mercadolibre.com.ar',{
onBeforeLoad: spyOnAddEventListener
}).then({ timeout: 10000 }, waitForAppStart)
})
it('search first scanner', () => {
cy.contains('nav-search-input').type("scanner bluetooth para auto")
})
})
The problem with this is, I should replicate spyOnAddEventListener, waitForAppStart and variable appHasStarted at the beginning of every source file but I want to avoid this. How could properly extend this functions as a part of the internal source project without replicating in every test source? I have tried to make a simple source JavaScript file at the root of the project but when I import it, Cypress clients give an unrelated plug error like this one:
It looks like you've added the code to /cypress/plugins/index.js, but that is for task extensions (code that requires NodeJS access).
The two functions can be added to a file, ideally in the /cypress/support folder
wait-for-app-utils.js
let appHasStarted
function spyOnAddEventListener (win) {
...
}
function waitForAppStart() {
...
}
module.exports = {
spyOnAddEventListener,
waitForAppStart
}
test
import {spyOnAddEventListener, waitForAppStart} from '../support/wait-for-app-utils.js'
describe('Main test suite', () => {
beforeEach(() => {
cy.visit('http://mercadolibre.com.ar', {
onBeforeLoad: spyOnAddEventListener
}).then({ timeout: 10000 }, waitForAppStart)
})
Another approach is to wrap it all up (including the visit) into a custom command. Now there's no need to export and import, the command will be available globally.
/cypress/support/commands.js
let appHasStarted
function spyOnAddEventListener (win) {
...
}
function waitForAppStart() {
...
}
Cypress.Commands.add('visitAndWait', (url) =>
cy.visit(url, { onBeforeLoad: spyOnAddEventListener })
.then({ timeout: 10000 }, waitForAppStart)
)
test
describe('Main test suite', () => {
beforeEach(() => {
cy.visitAndWait('http://mercadolibre.com.ar')
})
I am new to cypress when go to a url using a before hook it completes the first it statement, then it executes the before hook again and does the 2nd it statement, it should execute the before hook once execute the it statements and stop. However that is not what is happening and i need help please to see what i am doing wrong. My code is below:
import { expect, assert, should } from 'chai';
import LoginPage from '../page-objects/LoginPage.spec'
import BeHomePage from '../page-objects/BeHomePage.spec'
describe('create, edit, delete Survey', () => {
before(function() {
cy.visit(''); // see config json for base url
})
it('user can login to boardeffect', () => {
LoginPage.getLoginUserName().type(Cypress.env('username'));
LoginPage.getLoginUserPassword().type(Cypress.env('password'));
LoginPage.getSigninButton().click();
})
it('user can navigate to collaborate', () => {
BeHomePage.getAutoBeWorkroom().should('be.visible');
BeHomePage.getAutoBeWorkroom().click();
BeHomePage.getCollaborate().should('be.visible');
BeHomePage.getCollaborate().click();
cy.wait(10000)
})
})
{
"baseUrl": "https://automation-ozzie.boardeffect.com/login",
"defaultCommandTimeout": 15000,
"env": {
"username": "steveSystem",
"password": "Passw0rd"
}
}
class BeHomePage {
getAutoBeWorkroom() {
return cy.get(':nth-child(7) > a')
}
getCollaborate(){
return cy.get('.workroom-buttons > :nth-child(4) > a')
}
getNewSurvey(){
return cy.get('btn btn-success')
}
}
export default new BeHomePage();
As picture below shows all code in one (it) block passes as seen in picture however code in 2 it blocks fails as seen above.
enter image description here
The extra step you need is discussed in this section of the docs Cookies - Preserve Once.
Cypress auto-clears cookies between each it(), but if you add
it('user can login to boardeffect', () => {
LoginPage.getLoginUserName().type(Cypress.env('username'));
LoginPage.getLoginUserPassword().type(Cypress.env('password'));
LoginPage.getSigninButton().click();
// preserve the cookie set above for the next test
Cypress.Cookies.preserveOnce('_boardeffect_session');
})
it will keep that cookie value during subsequent it() sections.
Open the browser dev-tools, go to Application, Cookies, https://automation-ozzie.boardeffect.com and observe that without preserveOnce() the cookie value is cleared.
When I build my electron app with this plugin, all I get when installing the package is a blank, white, screen. I've configured the window to open dev tools in the built version, but when I look at the inspect menu, the only content on the page are the <html>, <head> and <body> tags, and there are no errors; the console is completely empty:
Elements:
Console:
I've looked just about everywhere online, but none of the solutions there worked.
I have tried changing the router mode from history to hash and also running vue invoke electron-builder, but they didn't help.
From what I can tell, this is failing:
win.loadURL('app://index.html')
because the path is incorrect. But I don't know if that's the case or if it's something else, since there are no errors reported.
Here's my background.js file:
'use strict'
import { app, protocol, BrowserWindow } from 'electron'
import { createProtocol } from 'vue-cli-plugin-electron-builder/lib'
import installExtension, { VUEJS_DEVTOOLS } from 'electron-devtools-installer'
const isDevelopment = process.env.NODE_ENV !== 'production'
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let win
// Scheme must be registered before the app is ready
protocol.registerSchemesAsPrivileged([
{ scheme: 'app', privileges: { secure: true, standard: true } }
])
function createWindow() {
// Create the browser window.
win = new BrowserWindow({
width: 1500,
height: 845,
webPreferences: {
// Use pluginOptions.nodeIntegration, leave this alone
// See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info
nodeIntegration: true,
enableRemoteModule: true
}
})
win.removeMenu()
win.webContents.openDevTools();
if (process.env.WEBPACK_DEV_SERVER_URL) {
// Load the url of the dev server if in development mode
win.loadURL(process.env.WEBPACK_DEV_SERVER_URL)
// if (!process.env.IS_TEST) win.webContents.openDevTools();
} else {
createProtocol('app')
// Load the index.html when not in development
win.loadURL('app://index.html')
}
win.once('ready-to-show', () => {
win.show();
})
win.on('closed', () => {
win = null
})
}
// Quit when all windows are closed.
app.on('window-all-closed', () => {
// On macOS it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (win === null) {
createWindow()
}
})
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', async () => {
if (isDevelopment && !process.env.IS_TEST) {
// Install Vue Devtools
try {
await installExtension(VUEJS_DEVTOOLS)
} catch (e) {
console.error('Vue Devtools failed to install:', e.toString())
}
}
createWindow()
})
// Exit cleanly on request from parent process in development mode.
if (isDevelopment) {
if (process.platform === 'win32') {
process.on('message', (data) => {
if (data === 'graceful-exit') {
app.quit()
}
})
} else {
process.on('SIGTERM', () => {
app.quit()
})
}
}
How can I fix this problem?
I found that solution is to change router mode from "history" to "hash". So in router config set:
mode: process.env.IS_ELECTRON ? 'hash' : 'history',
Problem solution source
So after more Googling, I stumbled upon this site which suggested to do this:
Replace your default win.loadURL() (which might look like this:
win.loadURL(formatUrl({
pathname: path.join(__dirname, 'index.html');,
protocol: 'file',
slashes: true
}))
or it could be different; it doesn't matter), with this:
win.loadURL(path.join(__dirname, 'index.html'));
Basically, the difference is that this just removes the formatUrl which seems to screw things up.
I replaced mine, which was:
win.loadURL("app://./index.html");
with this, and it works fine now.
Also make sure you don't delete createProtocol('app') if that is there too, (it was a few lines above win.loadUrl()), because you could break your app :).
if you are using vue-router, make sure to set it on "hash mode".
source: https://nklayman.github.io/vue-cli-plugin-electron-builder/guide/commonIssues.html