TestCafe: Testing a Page Opening a PDF in a New Tab - pdf

Part of the web application I am testing is to click a button, which normally opens a PDF in a new tab. This enables the user to go forward in the application. The PDF can be ignored.
Currently, my strategy is to click the button and then navigate back using ClientFunction. TestCafe successfully opens the PDF when the button is clicked, but it is opened in the same tab and the test is then stuck. Navigating back changes the URL, but the PDF is still displayed.
const goBack = ClientFunction(() => window.history.back())
await this.t.click(this.button)
await this.t.wait(10000)
await goBack()
Is TestCafe currently able to bypass this issue, as I don't need to actually do anything with the PDF?

TestCafe allows testing html pages, but not PDF files. So, you can check the generated link to the PDF file as a string without actually following this link. For example:
const overrideWindowOpen = ClientFunction(() => {
window.open = function (url) {
window.__lastWindowOpenUrl = url;
};
});
const getResultUrl = ClientFunction(() => window.__lastWindowOpenUrl);
await overrideWindowOpen();
await t
.click(this.button)
.expect(getResultUrl()).eql('http://example.com/path/to/PDF/93023813-0984-1');
See also: Multiple Browser Windows

Related

How to enter Immersive Reader on Microsoft Edge through Selenium?

On a high level, does anyone know how to enter the Immersive Reader mode on Microsoft Edge when it is available for a given webpage through Selenium?
My aim is to load up a page, enter Immersive Reader, and save the page's source code to disk. I'm firing up Edge through Docker and I'm pragmatically connecting to it via a Node.js script.
I've tried driver.actions().sendKeys(KEY.F9), but that doesn't work since I'm targeting the browser and not a DOM element.
Many thanks for all your help.
New
Just run
driver.get('read://' + url)
and the site is loaded in immersive reader mode if available.
Old
To interact with the UI you have to use pyautogui (pip install pyautogui) and then run this code while the browser window is on focus/active:
import pyautogui
pyautogui.press('F9')
It is also useful for example to save a pdf by interacting with the popup window appearing when pressing CTRL+S.
Here's a bit of code for anyone else who might stumble across this:
Credits to #sound wave for helping me get there!
const { Builder } = require('selenium-webdriver');
const fs = require('fs');
(async () => {
const driver = await new Builder().forBrowser('MicrosoftEdge').usingServer('http://localhost:4444').build();
await driver.get('read://https://www.bbc.co.uk/news/entertainment-arts-64302120'); // this URL needs to be Immersive Reader supported
await driver.switchTo().frame(0);
const pagesource = await driver.getPageSource();
fs.writeFile('test.html', pagesource, err => {
if (err) {
console.log(err);
}
});
const title = (await driver.getTitle()).trim();
console.log(title);
await driver.quit();
})().catch((e) => console.error(e));

webdriverio - download pdfs in chrome

I am new to using webdriverio, and attempting to automatically download a pdf file. The file opens in the browser and I cannot figure out how to download it - ideally to a folder specified on my local machine. I see some old forum posts which possibly suggest using chromedriver, however, due to minimal code snippets provided, I cannot understand if it's the correct approach though. Here is what I have this far (although the last two lines do not work):
const LoginPage = require('../pageobjects/login.page');
describe('Payroll Download Application', () => {
it('Login Fail Page', async () => {
await LoginPage.open();
await LoginPage.login();
await $("a[href='PayCycleReports']").click()
await $('a=Payroll Summary').click()
const handles = await browser.getWindowHandles()
await browser.switchToWindow(handles[1])
const elem = await $("#viewer").shadow$("#toolbar").shadow$("#downloads").shadow$("#downloads").shadow$("#download")
await elem.click()
});
});
Any help to figure it out would be greatly appreciated. Thanks :)
This can be done with browser.execute.
It will be necessary to select the element through JS and add the 'download' attribute to it. If you click on an element with the 'download' attribute, the pdf will not open but will be downloaded.
Example:
await browser.execute(function(){
document
.querySelector("#node-32 > div > div > div > ul:nth-child(4) > li:nth-child(1) > a")
.setAttribute("download", "download")
},
);
If you need a different selector (not CSS) you can use getElementById , getElementsByName, getElementsByTagName, getElementsByClassName, getElementByXPathand others.

Get list of Chrome Windows (OS-Level)

I thought initially that I could retrieve Chrome Windows by using:
browser.getWindowHandles()
Problem with that is that it doesn't actually get Chrome "Window" but Tabs. Is there anyway in Selenium to have a concept of real "visual" Chrome window? I want to know if a Tab is from a specific Window and how many tabs in a Window specifically. The doc is misleading especially with getAllWindowHandles which implies that it's about Window.
I'm basically looking for a solution to get "OS Window" and their tabs. I've switched from Selenium to WebdriverIO maybe thinking it's possible but I can't find in the docs.
Thanks guys for the help!
https://stackoverflow.com/a/34655248/6793637
Windows and Tabs are similar , it depends on the browser setting whether the new link should be open in a tab or window.
if you open a new window or tab both will be detected in selenium/wdio . Note that the tab or window count is for the window that was opened by the selenium session and not the entire windows opened in your system
eg
it('should login with valid credentials', async () => {
await LoginPage.open();
// opens new tab
await browser.execute((a) => { window.open(a) }, 'http://the-internet.herokuapp.com/login')
await expect((await browser.getWindowHandles()).length).toBe(2);
//opens new window
await browser.execute((a) => { window.open(a, 'target', 'features') }, 'http://the-internet.herokuapp.com/login')
await expect((await browser.getWindowHandles()).length).toBe(3);
await browser.pause(5000);
});

Does TestCafe support multiple tab testing

I have a scenario where clicking on a button opens a new tab but when I try with testCafe it opens in a new window instead of new tab.Why is this ? Doesn’t testCafe support new tab scenarios?
I think using multiple tabs is not really necessary. Usually people try to test that a link opens up in a new tab, but why?
<a class="c-cookie-bar__text-link" target="_blank" href="/private-data-info">More information</a>
You know that a link with target="_blank" will open up in a new tab. This is nothing that would be programmed by your team, this is how a browser works. Just every imaginable browser behaves the same if it encounters this attribute in a link. It's been tested, you don't need to retest it on your website.
However, you still might need to test that the target content loads or that the link looks the way you want. That's ok, but you don't need multiple tabs for that. The following scenarios make sense:
check that the link has the target="_blank" attribute:
test
('Check Target Attr', async t => {
await t
.expect(Selector('.c-cookie-bar__text-link').withAttribute('target', '_blank').exists)
.ok();
});
check that the href attr is what it should be:
test
('Check Href Attr', async t => {
await t
.expect(Selector('.c-cookie-bar__text-link').getAttribute('href'))
.eql('/private-data-info');
});
check that the content loads in the same tab:
import getBaseUrl from '../Helpers/baseUrl';
import { Selector } from 'testcafe';
const baseUrl = getBaseUrl();
fixture `Link Handling`
.page(baseUrl);
test
('Go To Resource', async t => {
const resource = await Selector('.c-cookie-bar__text-link')
.getAttribute('href');
await t
.navigateTo(baseUrl + resource);
// possibly some other assertions follow
});
check the http status code (I use axios here, but it's not all visible in my example):
import getBaseUrl from '../Helpers/baseUrl';
import { Selector } from 'testcafe';
import request from '../Helpers/networkRequest';
const baseUrl = getBaseUrl();
fixture `Link Handling`
.page(baseUrl);
test
('Check Status Code', async t => {
const resource = await Selector('.c-cookie-bar__text-link')
.getAttribute('href');
const networkReq = await request({
method: 'GET',
url: baseUrl + resource
});
await t
.expect(networkReq.status).eql(200);
});
If you actually ignore all this and just click the link in TestCafe:
await t
.click(Selector('.c-cookie-bar__text-link'));
it will be opened in a new window like so:

How do I deal with a page loading in a secondary browser tab when I run Protractor tests headless (Chrome)?

When this code clicks a “Print”-icon, a PDF-file will be generated and displayed in a new browser-tab. I want to switch to this tab, wait until the PDF has finished loading there, check a part of the URL and then close that secondary tab.
it( "should open document as PDF-file in new browser-tab", async () => {
const mUrl = "TherapyReportForm/Export";
await mTherapyReportView.btnPrintform.click();
await browser.getAllWindowHandles().then(async (handles) => {
//if there is a secondary browser-tab open...
if (handles.length > 1) {
//...click on it
await browser.driver.switchTo().window(handles[1]);
}
});
//confirm that the url of the secondary tab matches the print-url pattern
await browser.sleep( 18000 );
expect( await browser.getCurrentUrl() ).toContain( mUrl );
await browser.getAllWindowHandles().then( async (handles) => {
//if there are multiple browser-tabs open
if (handles.length > 1) {
//close the secondary and move back to first
await browser.driver.close();
await browser.driver.switchTo().window( handles[0] );
}
} );
} );
The test above works reliably, unless I run it in chromes headless-mode, then the test-run breaks at line
expect(await browser.getCurrentUrl()).toContain(mUrl);
console output
The console output proves that it switches to the secondary tab, but apparently never tries to load the url. Since it fails to close this secondary tab the entire suite will break at that point.
What am I doing wrong?
Here is a thing... downloading functionality is not available in headless chrome. That's for sure. What I'm going to talk about below, I'm a little bit uncertain if that's the case
There is no such thing as 'open' pdf file in browser. The reason is that behind scene the browser actually downloads it (maybe temporarily). This is why you'll never be able to do that in headless
But that's rather a shot in the dark