Error: Cannot find module 'libxmljs' - phantomjs

I am trying to parse xml using phantomjs for the following file, documentpreviewer1.js
var webPage = require('webpage');
var page = webPage.create();
var url = "http://xxx/sitemap.xml";
page.open(url, function(status){
if(status != 'success'){
console.log('Unable to access cfc');
}
else
{
var xml = page.content;
var libxmljs = require("libxmljs");
var xmlDoc = libxmljs.parseXml(xml);
var url1 = xmlDoc.get('//urlset/url[0]/loc');
console.log(url1);
}
});
when I run the above code, I get the following error
cmd sudo phantomjs documentpreivewer1.js
Error: Cannot find module 'libxmljs'
phantomjs://bootstrap.js:289
phantomjs://bootstrap.js:254 in require
documentpreivewer1.js:13
:/modules/webpage.js:281

libxmljs is a node.js module. Although phantomjs can be installed through npm (doesn't need to be) it is not a node.js module. It doesn't share any built-in module with node.js (fs seems the same, but is not equal to node.js fs).
You can use some node.js modules in phantomjs (See Use a node module from casperjs for a related question), but it doesn't seem like you could use libxmljs in phantomjs, because it depends on node-bindings which uses fs and path modules. You will have to change the implementation so that all dependencies can be expressed with phantomjs capabilities.
An alternative might be to use phantom-node or spookyjs for a casperjs node.js module.

Related

chrome:headless (MacOS) results with ' 1) AssertionError: expected 'about:blank' to include $target page'

I am using TestCafe in combination with gherkinTestcafe (steps) / cucumber.
I am also using environment variables so that i can run my tests on 2 different environments.
My code is as follows, although through debugging, i don't believe this is something strictly code related, as much as it is related to:
chrome:headless
environment
version of chrome / MacOS
import Enviorments from "../../../../../../AEM_Engine/Enviorment/Enviorments";
import { Helper } from "../../../../../TestActions/Test_specific/Career_helper";
import {AddAuthCredentialsHook} from "../../../../../TestActions/BasicAuth";
const {Before, Given, Then} = require('cucumber');
let publisher = new Publish();
let aemEnv = new Enviorments();
let helper = new Helper;
let careersPage = '/career';
Before('#basicAuth', async testController => {
const addAuthCredentialsHook = new AddAuthCredentialsHook('$someUserName', '$somePassword');
await testController.addRequestHooks(addAuthCredentialsHook);
});
Before('#disableCookie', async testController => {
await testController.addRequestHooks(publisher.mockCookieResponse);
});
Given('I am at Careers page', async testController => {
await publisher.Navigate(testController, aemEnv.frontEndURL + careersPage);
await publisher.verifyURL(testController, aemEnv.frontEndURL + careersPage);
});
.
.
.
When i wait for the script to run i have
1) AssertionError: expected 'about:blank' to include $expectedPage
As i mentioned, i don't believe the problem is in the code. Even if i remove the step for verifying the current URL location, the test fails on the next step after.
Tests pass on
Chrome (with UI shell)
Other browsers (firefox, safari), headless or with UI shell
Second (staging) environment
When Tests are run and TestCafe starts, i get the following info
Running tests in:
- HeadlessChrome 99.0.4844 / Mac OS X 10.15.7
Feature: Careers Page Available
(node:87344) Warning: Setting the NODE_TLS_REJECT_UNAUTHORIZED environment variable to '0' makes TLS connections and HTTPS requests insecure by disabling certificate verification.
I tried re-installing some packages, re-writing some of the steps, adding some flags to clear cache, change chrome port or similar, but nothing worked.
Any thoughts on what might be causing this and how to solve it?

Cannot import module from Cypress spec file

I am trying to use the #peculiar/x509 library to decode a CSR to use some of the information in my tests. The tests are using Cypress.
Here is an extract of my code:
import * as x509 from '#peculiar/x509';
const request = {
certificateSigningRequest: `-----BEGIN CERTIFICATE REQUEST-----
...
-----END CERTIFICATE REQUEST-----`,
};
describe('PKI', () => {
it('works', () => {
console.log(x509);
const stringPEM = request.certificateSigningRequest
.replace(/(-----(BEGIN|END) CERTIFICATE REQUEST-----|\n)/g, "");
const cert = new x509.X509Certificate(stringPEM);
console.log(cert.subject);
return;
// Stuff I want to test
});
});
When I try to log the x509 variable it returns an empty object.
And on the const cert = new x509.X509Certificate(stringPEM); line, I get an error:
x509.X509Certificate is not a constructor.
If I try to set up a simple project with a Typescript file to import the library and just log the x509 variable, it displays all the exports correctly.
I can't figure why it behaves like that with Cypress, so any help is appreciated.
EDIT: Diving a bit more into how Cypress works, I now understand that my assumption about the spec files running/controlled in a Node process was wrong. Spec files are running in the browser. So I would need to inject the browser version of the library in the spec file.
This can be done via the plugin API of Cypress, because it runs in the Cypress node process.
You can import a specific build, either x509.es.js or x509.cjs.js and your code works. The base #peculiar/x509 is for <script> inclusion.
One thing, the BEGIN and END tokens need to remain in the request for it to be recognized.
import * as x509 from '#peculiar/x509/build/x509.es.js'
// const x509 = require('#peculiar/x509/build/x509.cjs.js') // alternative
// hard left for multiline strings, otherwise request is not correctly formatted
const request = {
certificateSigningRequest: `-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----`,
};
// copied from #peculiar/x509 to verify format - not necessary for test
const isPem = (data) => {
return typeof data === "string"
&& /-{5}BEGIN [A-Z0-9 ]+-{5}([a-zA-Z0-9=+/\n\r]+)-{5}END [A-Z0-9 ]+-{5}/g.test(data);
}
console.log(isPem(request.certificateSigningRequest))
describe('PKI', () => {
it('works', () => {
console.log(x509);
const stringPEM = request.certificateSigningRequest // leave in BEGIN and END
const cert = new x509.X509Certificate(stringPEM);
console.log(cert.subject); // prints e.g. "CN=Test certificate, E=some#email.net"
return;
// Stuff I want to test
});
});
Possibly due to NodeJS version issue.
The X509Certificate was added recently in NodeJS version 15.6.0. Changelog here. So it requires that version. It might have worked on your simple project because of a newer NodeJS version.
And by default, Cypress is using its bundled NodeJS version, which since Cypress version 7.0.0 to 8.2.0, it's using bundled NodeJS version 14.16.0, as per the changelog here:
The bundled Node.js version was upgraded from 12.18.3 to 14.16.0.
So you can try changing/overriding the bundled NodeJS version in Cypress configuration to version 15.6.0, as per this configuration:
nodeVersion

Cordova FileTransfer Plugin error code 1 for image upload

I am trying to take a picture on my phonegap app and then use the FileTransfer plugin to upload it to my server. I am getting error code 1 but there is no other explanation - this is VERY frustrating. I have scoured every piece of documentation and blog known to man with no luck.
I am using a basic LAMP server and it continues to give me an http 500 code. I am 99.9% sure this error is specific to my server because I have tested this with a different web server of mine and the code works fine. Here is the response:
{"code":1,"source":"file:///storage/emulated/0/Android/data/io.cordova.xxappxx/cache/1477607161788.jpg","target":"https://server.com/php/uploadPhoto.php","http_status":500,"body":"\t","exception":"https://server.com/php/uploadPhoto.php"}
Below is my front-end js code:
function uploadPhoto(imageURI) {
var options = new FileUploadOptions();
options.fileKey="file";
options.fileName=imageURI.substr(imageURI.lastIndexOf('/')+1);
alert(options.fileName);
options.mimeType="image/jpeg";
var params = {};
params.value1 = sessionStorage.getItem("token");
options.params = params;
options.chunkedMode = false;
options.headers = {Connection: "close"};
var ft = new FileTransfer();
ft.upload(imageURI, "https://servername.com/php/uploadPhoto.php", function(result){
console.log(JSON.stringify(result));
}, function(error){
console.log(JSON.stringify(error));
}, options, true);
}
And here is my back-end PHP code that is being called (uploadPhoto.php):
<?php
session_start();
header('Access-Control-Allow-Origin : *');
$new_image_name = "$userId.jpg";
move_uploaded_file($_FILES["file"]["tmp_name"], "/var/img/".$new_image_name);
?>
This ended up being an issue of image size. I was working on this project for a university and their servers have lots of security installed - one of these security configurations had a very small file upload size limit which was blocking the uploads. I discovered this by scanning some of the log files in the /var/log/ directory.

Selenium/PhantomJS Can't Find Javascript in Webjars

I am running a simple log in test using PhantomJS 1.9.8 and Selenium 2.42.2. Everything is setup with maven and I am using embedded Jetty 8.1.14.v20131031.
Before starting jetty I also add all the webjars to org.eclipse.jetty.webapp.WebAppContext#setExtraClasspath
My login.jsp is using webjars to reference jquery.
<script src="webjars/jquery/1.10.2/jquery.js"></script>
When I run my test I get the following error:
Session [81d93a00-9101-11e5-bc34-79a9cbd8ffe4] - page.onError - msg: ReferenceError: Can't find variable: $
If I change the login.jsp to the full URL the test passes.
<script src="https://code.jquery.com/jquery-1.10.2.js"></script>
Is it PhantomJS that is having a problem reading from the webjars or is it Jetty not serving them?
The key was to iterate over the webjars and add each as a classpath resource.
//Ensure that webjars are visible as they are packaged in META-INF/resources
ResourcePatternResolver patternResolver = new PathMatchingResourcePatternResolver();
Resource[] webjarResources = patternResolver.getResources("classpath*:/META-INF/resources");
String[] resources = new String[webjarResources.length + 1];
for(int i = 0; i < webjarResources.length; i++) {
Resource webjarResource = webjarResources[i];
resources[i] = webjarResource.getURI().toString();
}
//Try to find the webapp source regardless of the current working directory
URL resource = this.getClass().getClassLoader().getResource("app.properties");
String resourcePath = resource.getPath();
String root = resourcePath.substring(0, resourcePath.lastIndexOf("myapp"));
String path = root + "myapp/src/main/webapp";
File webAppDir = new File(path);
resources[resources.length - 1] = webAppDir.getAbsolutePath();
webapp.setBaseResource(new ResourceCollection(resources));

Opening local html file with SlimerJS

I have a script that works in PhantomJS but I'm trying to switch to SlimerJS. I keep getting an error when trying to open a local file:
var webPage = require('webpage');
var system = require('system');
var page = webPage.create();
page.viewportSize = { width: 2048, height: 1536 };
console.log('Processing',system.args[1]);
page.open(
'simple.html',
function start(status) {
setTimeout(function(){
page.render(system.args[2], {format: 'png'});
phantom.exit();
},1000);
}
);
simple.html is a file located in the same directory as the script. The resulting PNG says "Address Not Found", "simple.html could not be found. Please check the name and try again."
I've also tried:
full OS path, eg /User/blah/blah/simple.html
file URI file:///Users/blah/blah/simple.html
These yield a similar result.
I'd rather not have the script publicly available for a variety of reasons. Is it possible to launch a local file with SlimerJS?
I don't think its possible. Reading the docs it specifies a url.
I got around this by running a http server
python -m SimpleHTTPServer
Then accessing it through localhost.
page.open('http://localhost:8000/simple.html',...)
A file URI does work. Something like file:///Users/name/project/file.html.

Categories