Is there a way to keep 'select' options open for screenshots? - testing

I'm trying to take screenshots of a site and need to keep a 'select' menu-open so that I can capture its contents. It always closes before taking the screenshot.
I've tried taking a screenshot after clicking on the menu
test('SelectOptionsScreenshot', async t => {
await faveDogs.load(t)
await t
.click(faveDogs.dogSelect)
.takeScreenshot()
I've tried it by telling it to look for 'options' with no specific text
test('SelectOptionsScreenshot', async t => {
await faveDogs.load(t)
await t
.click(faveDogs.dogSelect)
.click(faveDogs.dogSelect.find('option')
.takeScreenshot()
I've tried having it hover over an option
test('SelectOptionsScreenshot', async t => {
await faveDogs.load(t)
await t
.click(faveDogs.dogSelect)
.hover(faveDogs.dogSelect.find('option').withText('German Shepherd')
.takeScreenshot()

It looks like you faced an issue in the current product version. I've reproduced this behavior and we are going to look into it in the context of this thread created based on your information: https://github.com/DevExpress/testcafe/issues/4101.

Related

(uncaught exception)TypeError: $(...).datepicker is not a function

it('Access URL', () => {
cy.visit('URL')
cy.wait(5000)
cy.get('.login-btn').click()
})
URL is working but login click is not working.
(uncaught exception)TypeError: $(...).datepicker is not a function --- is displayed
Trying to access url and trying to click the Login link in the website.
If it takes the page more then 5 seconds to load cypress would never find the button in your code. If you can give the button an id it would be able to find it, but if you can't you can try to add a long timeout to the button and when the button appear on the page it will click it, for example.
`cy.get('.login-btn', { timeout: 30000 }).click()`
By the looks of your comment, you have an uncaught exception in your application. That’s an indication you or a dev needs to fix something in the app. Cypress is just trying to tell you.
If you want to ignore the error, you can add this to your test
it('Access URL', () => {
cy.once('uncaught:exception', () => false);
cy.visit('URL')
cy.wait(5000)
cy.get('.login-btn').click()
})
If you want to ignore uncaught exceptions in ALL tests you can add this to your support file. (I do NOT recommend this, I recommend fixing your application to find out why it’s throwing an exception in the first place)
// support/index.js
Cypress.on('uncaught:exception', () => false);

TestCafe and Yopmail

simple question
In end2end testing I want to check a few options, inner texts and links on yopmail in one of incoming mails. The problem occurred after .click on button "Check Inbox" with 404 result.
I looks like yopmail is successfully preventing automated testing.
Am I right, or there is a secret way to do it? and if answer is no, maybe you have some idea how to accomplish test where temporary mails have to be inspected
I'm not familiar with yopmail, but if all you care about is the contents of the email message, perhaps you could forward emails to a provider that doesn't block automation, such as protonmail, and check the contents there? Protonmail doesn't block me from checking/sending emails.
Secret Way :) (works in chrome only, fails in firefox):
You go into the inbox directly by appending it to the URL.
import { Selector } from 'testcafe'
fixture`yopMail`
.page`http://www.yopmail.com?emailme1997#yopmail.com`
.before(async t => {
})
.beforeEach(async t => {
await t.setTestSpeed(0.3)
await t.maximizeWindow()
})
test("hello", async t => {
const chkMail = Selector('.slientext')
await t.wait(3000)
await t.click(chkMail);
await t.wait(5000)
});

Jest + puppeteer best architecture practices

I just entered the world of testing with puppeteer and jest, and I was wondering what the best practice was in terms of folder architecture and logic.
I've never done testing before and I think I'm getting a little lost in the different principles and concepts and how it all fits together.
I learned to do my tests based on the page-object model, so I have classes for each of my pages, but also for each of my modules ( or components ). For example, in my application, the header or the login modal are components.
Then I have a test file per page or per component.
(for example the landingPage.tests.js file, which uses the model of the LandingPage class in the LandingPage.js file)
Here is a concrete example:
I have different login cases and I'd like to test them all. For example I want to test to connect with a "normal" user, for which the process is simply login then password. Then I need to test with a user who has activated 2FA, or with a user from a company that uses SSO.
I first thought about putting my different tests in authentication.tests.js, in different describe blocks, thinking it would open a new tab each time, but it doesn't... I use puppeteer in incognito mode to make sure each tab is an isolated session.
So my questions are:
Where is the best place to do these test suites?
Am I supposed to have test files that "describe" the pages ( for example, the button must be present, such text must be here etc) and also have "scenario type" test file ( a set of contextual actions to a user, like for my different login cases) ?
Here is authentication.tests.js, in which I would like to tests all my different ways of logging in :
import HeaderComponent from "../../../pages/components/HeaderComponent";
import AuthenticationComponent from "../../../pages/components/AuthenticationComponent";
import LandingPage from "../../../pages/landing/LandingPage";
import {
JEST_TIMEOUT,
CREDENTIALS
} from "../../../config";
describe('Component:Authentication', () => {
let headerComponent;
let authenticationComponent;
let landingPage;
beforeAll(async () => {
jest.setTimeout(JEST_TIMEOUT);
headerComponent = new HeaderComponent;
authenticationComponent = new AuthenticationComponent;
landingPage = new LandingPage;
});
describe('Normal login ', () => {
it('should click on login and open modal', async () => {
await landingPage.visit();
await headerComponent.isVisible();
await headerComponent.clickOnLogin();
await authenticationComponent.isVisible();
});
it('should type a normal user email adress and validate', async () => {
await authenticationComponent.typeUsername(CREDENTIALS.normal.username);
await authenticationComponent.clickNext();
});
it('should type the correct password and validate', async () => {
await authenticationComponent.typePassword(CREDENTIALS.normal.password);
await authenticationComponent.clickNext();
});
it('should be logged in', async () => {
await waitForText(page, 'body', 'Success !');
});
});
describe('SSO login ', () => {
// todo ...
});
});
Thank you and sorry if it sounds confusing, like I said I'm trying to figure out how it all fits together.
Regarding the folder structure, Jest will find any files according to the match config, basically anything called *.spec.js or *.test.js. Looks like you know that already.
What that means is the folder structure is completely up to you. Some people like to have the tests for components in the same folders as the components themselves. Personally I prefer to have all the tests in one folder as it makes the project look cleaner.
The other benefit of having all the tests in one folder is that you can then start to distinguish between the types of tests. Component tests check that pure components render and operate as expected. You don't need Puppeteer for this, use snapshots if you're in a React app. Puppeteer is good for integration tests that navigate through so-called 'happy paths', login, signup, add to cart etc., using a headless Chromium browser.
To answer the specific problem you have been having with Jest / Puppeteer on a new page for each test:
//keep a reference to the browser
let browser
//keep a reference to the page
let page
// open puppeteer before all tests
beforeAll(async () => {
browser = await puppeteer.launch()
})
// close puppeteer after all tests
afterAll(async () => {
await browser.close()
})
// Get a new page for each test so that we start fresh.
beforeEach(async () => {
page = await browser.newPage()
})
// Remember to close pages after each test.
afterEach(async () => {
await page.close()
})
describe('Counter', () => {
// "it" blocks go here.
})
Hope that helps a bit.

Cypress - log response data from an request after a click()

Although I know this may not be considered as a best practice, but what I want to achieve is to silently delete a record from a database after the same was created throughout UI. In htat way I want to keep our test environment clear as much as possible and reduce the noise of test data.
After my tests create a new record by clicking over the UI, I wait for POST request to finish and then I would like to extract the id from the response (so I can reuse it to silently delete that record by calling the cy.request('DELETE', '/id')).
Here's a sample test I have put on as a showcase. I'm wondering why nothing is logged in this example.
it('GET cypress and log', () => {
cy.server()
.route('**/repos/cypress-io/cypress*')
.as('getSiteInfo');
cy.visit('https://www.cypress.io/dashboard');
cy.get('img[alt="Cypress.io"]')
.click()
.wait('#getSiteInfo')
.then((response) => {
cy.log(response.body)
})
})
As far as I can see from here https://docs.cypress.io/api/commands/wait.html#Alias this should be fine.
your code contains two problems.
First:
The click triggers a new page to be loaded but cypress does not wait until the PageLoad event is raised (because you do not use visit). On my PC the Request takes about 5 seconds until it is triggered after the click. So you should use wait(..., { timeout: 10000 }).
Second:
wait() yields the XHR object, not the response. So your code within then is not correct. Also the body is passed as object. So you should use JSON.stringify() to see the result in the command log.
This code works:
describe("asda", () => {
it('GET cypress and log', () => {
cy.server()
.route('**/repos/cypress-io/cypress*')
.as('getSiteInfo');
cy.visit('https://www.cypress.io/dashboard');
cy
.get('img[alt="Cypress.io"]')
.click()
.wait('#getSiteInfo', { timeout: 20000 })
.then((xhr) => {
cy.log(JSON.stringify(xhr.response.body))
})
})
})
Instead of route and server method, try intercept directly

Detox: Testing a React-Native spinner with a stop button

Was wondering if anyone has had a similar issue.
In the app I'm working with, we have a spinner showing downloading content with a stop button in the middle. When the user taps the spinner/stop button, the download is meant to cancel. For reference the spinner/stop button looks like this on iOS:
I'm trying to write an e2e test for this functionality using Detox. It doesn't work using automatic synchronisation as the animation (and the download) keeps the thread running. I've tried using device.disableSynchronization() but I haven't had any success.
Here's my e2e test for reference:
it('should start and then cancel a download from the <My Learning> screen', async() => {
// setup
await device.reloadReactNative()
await expect(element(by.id('feed_screen'))).toBeVisible()
await element(by.id('LearningPlan_Tab')).tap()
await expect(element(by.id('learning-plan-screen'))).toBeVisible()
// Tap the download icon, it will turn into a spinner
await element(by.id('offline_download_c2a')).atIndex(1).tap()
// Alert box appears with Cancel/Download options
await expect(element(by.label('Download')).atIndex(1)).toBeVisible()
await element(by.label('Download')).atIndex(1).tap()
// Ideally this would work, but it doesn't (the above alert box doesn't dismiss properly)
await device.disableSynchronization()
await waitFor(element(by.id('download_spinner_c2a')).atIndex(0)).toBeVisible().withTimeout(5000)
await element(by.id('download_spinner_c2a')).atIndex(0).tap()
await device.enableSynchronization()
await element(by.label('Cancel download')).tap()
await expect(element(by.id('offline_download_c2a')).atIndex(1)).toBeVisible()
})
When this test runs the app still seems to wait for the download to finish. Does anyone know any suggestions on the best way to test this, or if it's even possible?
I've found a way to make it work, though it seems quite flaky:
it('should start and then cancel a download from the <My Learning> screen', async () => {
//...
await device.disableSynchronization()
// This timeout seems to help
await waitFor(element(by.id('download_spinner_c2a')).atIndex(0)).toBeVisible().withTimeout(10000)
await element(by.id('download_spinner_c2a')).atIndex(0).tap()
await device.enableSynchronization()
await element(by.label('Cancel download')).tap()
await expect(element(by.id('offline_download_c2a')).atIndex(1)).toBeVisible()
})