testing existing pages with mocha-phantomjs - phantomjs

I'm not quite getting how to use PhantomJS and Mocha together, specifically through mocha-phantomjs.
I've read some tutorials (the one at tutsplus is quite helpful) and am not seeing how I can test external pages using Phantom and Mocha. I'm sure I just need a nudge.
In the tutorial the author creates a tests.js file with some DOM setup/manipulation, as well as some mocha assertions. Then, he creates a separate HTML file that loads the tests.js file and uses mocha-phantomjs to fire up phantom and run the tests.
That's where I'm a little confused, how the mochaPhantomJS.run() method actually does things behind the scenes, whether it knows to search the js file for a describe block and run all tests within, that sort of thing. I don't need chapter and verse, but a high-level summary would be ideal.
Also, if I want to test an outside page, how can I best do that? In the tutorial all the DOM investigation and testing is done on the test page. If I want to test a different page, do I change or setup my assertions differently? Should I call the PhantomJS API from those tests and point to an external site?

Mocha will run tests that have been specified in javascript that has been included in the html page that is launched. If you look at the example html page on mocha-phantomjs it expects the test definitions using describe/it calls to be in the test/mycode.js file. If you put something like
These tests are only testing what is in the main file and associated javascript, there isn't anything special that mocha-phantomjs provides to test external html files. If you want to test your own html files I think you can head in a couple of directions, I came up with these:
first option: Create a way to load the parts of you app that you want to test into the main testing html file. How to do this depends a lot on your application setup. It is probably well-suited for a modular system. Just include the javascript from your application and test it. Not so good for full-page-html tests.
second option: Open new windows with the pages to test from the main testing html file (from within phantom that is). You can open a page using window.open() just like a normal browser. I created a proof of concept like this:
describe('hello web', function () {
it('world', function (done) {
var windowReference = window.open("fileundertest.html");
// windowReference.onload didn't work for me, so I resorted to this solution
var intervalId = window.setInterval(function () {
if (windowReference.document && windowReference.document.readyState === 'complete') {
window.clearInterval(intervalId);
expect(windowReference.document.title).to.equal("File Under Test");
done();
} else {
console.log('not ready yet');
}
}, 10);
});
}
)
This solution is relatively simple, but has the same drawbacks as any page-loading solution: you never know when the page is fully initialized and have to resort to some sort of timeout/wait system to wait for the page to get into the correct state. If you want to test a lot of separate html files these delays start to add up. Additionally waiting for 'onload' on the page that I opened wouldn't work so I created my own function based on setInterval and a (non-perfect) test on the document that was being loaded. I found out there are differences in behavior between loading an html page from the filesystem and loading the same page via a web-server.
third option: Create a mocha test that you run nodejs-style from the command line, and launch phantomjs with a specific page as part of your mocha tests. This is what I'd say you need if your system really depends on html pages that are quite different from each other.
I quickly tested the third option, here is my test based on the example I found on the phantom page (which is an alternative solution to phantomjs that is used by mocha-phantomjs -- I've used neither for more than brief experiments so I cannot recommend which one to use)
'use strict';
var chai = require('chai'),
phantom = require('phantom');
var expect = chai.expect;
describe('hello node', function () {
it('world', function (done) {
phantom.create(function (ph) {
ph.createPage(function (page) {
page.open("http://www.google.com", function (status) {
console.log("opened google? ", status);
page.evaluate(function () { return document.title; }, function (result) {
console.log('Page title is ' + result);
ph.exit();
expect(result).to.equal("Google");
done();
});
});
});
});
});
}
)
While it is possible to test this way I'd say that maybe the overhead of the communication between the code in the phantom-world and the testing code in the nodejs world isn't worth it. You can of course move a lot of general functionality to a couple of helper functions, but you are still stuck with having to call page.evaluate() to perform specific tests on the page. The same issues with timeouts/waits as above apply.
As an aside: do already know CasperJS? Maybe it can be helpful for your setup should you choose to build something on 'plain' phantomjs.

Related

Playwright upload file on non-input element

So I'm currently trying to automate uploading a profile photo on an Electron App using Playwright and I'm running into issues with 'filechooser' event.
await windowA.click('data-testid');
const [fileChooser] = await Promise.all([
windowA.waitForEvent('filechooser'),
// windowA.locator('text=Edit').click(),
windowA.waitForTimeout(3000),
windowA.locator(selector).click(),
]);
The element used to upload a photo isn't an input type so I'm using
await fileChooser.setFiles(
[filepath],
{ timeout: 1000 }
);
The issue is trying to get playwright to select an image from the input dialog box that pops up and it just won't select any files. I've also been trying to get playwright to select an image in my fixtures folder, which is in a relative path to the test, but haven't had success in either case.
The error that Playwright is displaying is
page.waitForEvent: Timeout while waiting for event "filechooser"
waiting for event "filechooser"
Any know what the issue is?
My slippers told me that if you are using the window.showOpenFilePicker() to get a file from the user, you won't get the filechooser event at all. This is because internally, the showOpenFilePicker is not triggering an event as it is still a WIP.
More infos can be found there but I don't think there is a workaround for now
https://githubmemory.com/repo/microsoft/playwright/issues/8850
Pupetter has actually the same issue: https://github.com/puppeteer/puppeteer/issues/5210`
One fix would be to not use the showOpenFilePicker() at all, but instead rely on the <input> element to gather the file. This is a bit more cumbersome for the dev but is more supported and should trigger the 'filechooser' event.
Another fix could be to add a function you can override when running in test move for it to not even need to open the file chooser. Something like
getFileFromPicker() => {
if(!isRunningInTest) {
// do the showOpenFilePicker logic as usual in the app and the user will need to choose a file from it
} else {
// provide synchronously a buffer to use as file content, and so do not even show the picker to the testing user.
}

how can i check if an element visible without stopping the program from running in cypress?

When I try to look for an element in the software I am working on and it is not found the automation stops.
What can I do so that if the element is not found the automation will continue to run?
There are multiple solutions out there for Cypress. As a quick solution, you can set a cookie value and decide to skip the particular test. add this code to your cypress/support/index.js
afterEach(function onAfterEach() {
if (this.currentTest.state === ‘failed’) {
cy.setCookie(‘shouldSkip’, ‘true’);
//set cookie to skip tests for further specs
Cypress.runner.stop();
//this will skip tests only for current spec
}
});
You can read more and see the full blog post here:
Skipping Cypress tests on first failure

PhantomJS process keeps running in background after calling program.kill()

I'm using phantomjs and webdriverio to fetch and render a webpage that's loaded by javascript, then save it to be parsed later by cheerio.
Here's the code for that:
import phantomjs from 'phantomjs-prebuilt'
const webdriverio = require('webdriverio')
const wdOpts = {
desiredCapabilities: {
browserName: 'phantomjs'
}
}
async parse (parseUrl) {
return phantomjs.run('--webdriver=4444').then(program => {
return webdriverio.remote(wdOpts)
.init()
.url(parseUrl)
.waitForExist('.main-ios', 100000)
.pause(5000)
.getHTML('html', true)
.then((html) => {
program.kill()
return html
})
})
}
Even though I call program.kill() I notice that the phantomjs in the list of processes, and it does use up quite a bit of RAM and CPU.
I'm wondering why the process doesn't terminate.
.close() just closes the window. There is a known bug, if it is the last window it stays open.
.quit() should do it, but there are issues associated with that as well.
PhantomJS bug report: https://github.com/detro/ghostdriver/issues/162
someone has a decent workaround posted at the bottom of that thread:
https://github.com/SeleniumHQ/selenium/issues/767#issuecomment-140367536
this fix shoots a SIGTERM to end it: (In python, but might be usefull)
# assume browser = webdriver.PhantomJS()
browser.service.process.send_signal(signal.SIGTERM)
browser.quit()
I like to just open a Docker container with my automation, and run it in there. Docker closes it up for me, however that is prolly out of scope for what you want to do.. i would recommend the above SIGTERM+quit method.
PhantomJS is a 2 component product. There is the Javascript which runs on the client (Whether web or other Script) side as part of your code. Then there is the part that runs as a server-side application (The command line call)
It has been my experience with PhantomJS that when an error is encountered, the PHantomJS server side "hangs" but is unresponsive. If you can update your call to this script to provide output logging, you may b able to see what the error is that PhantomJS application is encountering.
phantomjs /path/to/script/ > /path/to/log/file 2>&1
Hope this Helps! If you'd like me to clarify anything, or elaborate I'm happy to update my answer, just let me know in a comment, Thanks!

Nightwatch pipe all console messages to a file

I'm using nightwatch to run some QA tests on code I have little control over. The app consists of multiple windows being opened through the use of popups. Because it is difficult to know exactly when to try and grab the console within my tests, I'd like a way of piping all console messages from any window that is running within the context of selenium, to an output file so I can sift through it.
Right now I have this in my test
.getLog('browser', function (result) {
console.log(typeof result)
fs.writeFile("browser.log", JSON.stringify(result), function(err) {
if(err) {
return console.log(err);
}
console.log("Log Saved");
});
});
This may work for some cases, but sometimes the code I am hoping to catch happens on an unload event. In a situation like that, catching the error at the correct time proves challenging. I was hoping that nightwatch might expose some sort of event listener api where I could observe the browser.log file for example, and update the contents of the file automatically. Does such a feature exist? Is there a better way to do this?

NodeWebkit testing using grunt?

Right now i have grunt setup to watch for file changes and feed them to mocha, and mocha runs the tests. The problem is when modules include something like "nw.gui" the test case cannot find them. Is there any way to get around that, some way that i can include it?
//indexeddb.spec.js
var assert = require("assert");
var IndexedDB = require("../scripts/indexeddb");
db = new IndexedDB();
console.log(db);
describe('IndexedDB', function(){
describe('initialize', function(){
it('Should throw an error when the paramaters are null', function(){
expect(db.initialize()).to.throwError();
});
});
});
//indexeddb.js
module.exports = exports = function(){
var indexedDB = require("nw.gui").Window.get().window.indexedDB;
var _ = require("../bower_components/underscore/underscore.js")
this.initialize = function(databaseName,version,schema) {
}
}
Should i do this differently? I did think about running the tests in a gui window in webkit, but that would require that i include all the spec file's on the page and reload the page every time i wanted to run the test. With grunt and watch i was trying to get it to run the test for each file when i edited either the spec or the src file.
I will also need to test the html/js/backbone pages that i open in a webkit window.
Thanks for any insight.
Code example at https://github.com/varunvairavan/node-webkit-unit-testing
Found a way to run test's on node webkit, with a watch to reload the page on file changes.
I was going through this post https://github.com/visionmedia/mocha/issues/960 when i found a link to https://github.com/BenoitZugmeyer/chwitt/tree/5f9bc6c0b8c0328f1dc06a554e9fdd3a969c36ae/tests
The way it works is, create a new node webkit app in your test directory, it then includes all the files in that directory that end with .spec.js and runs the tests in them. It also does a page reload on file changes in the source/test folder.
I had my files in sub directories in the test folder so i used the walk function from node.js fs.readdir recursive directory search to find all the files ending with ".spec.js".