This question already has an answer here:
PhantomJS not returning results
(1 answer)
Closed 6 years ago.
I have running
localhost === http://localhost:8000/app/templates/
and I would like to open it with PhantomJS so all procedures looks exactly like in real browser -> and in result i can see all the information that i normally see in browser console.
I couldn't find any information how to do it properly.
Untill now i have tried this pattern
var webPage = require('webpage');
var page = webPage.create();
page.open('http://localhost:8000/app/templates/
', function(status) {
});
but still I cannot see any console.logs which are used in js files which should be loaded together with get call to my localhost
To see the console log, register the onConsoleMessage callback:
var webPage = require('webpage');
var page = webPage.create();
page.onConsoleMessage = function(msg, lineNum, sourceId) {
console.log('CONSOLE: ' + msg + ' (from line #' + lineNum + ' in "' + sourceId + '")');
};
http://phantomjs.org/api/webpage/handler/on-console-message.html
Related
I have written a web-crawler to test a pre-release website for errors and issues (i.e. missing content type, timeouts, exceptions, redirects).
This morning a colleague asked me to include a check if there was any javascript error on the page...
A pure javascript solution is unlikely -- i.e. detect all JS errors, using JS
What I appear to want to be able to do is capture the javascript console text, ideally via CoreWebView2
If the page logs each exception into an array,
Errors=[]
window.onerror = function (msg, url, line) {
Errors.push("Caught[via window.onerror]: '" + msg + "' from " + url + ":" + line);
return true;
};
Then you can just query the Errors and see both the count and the nature of the errors.
You can also push errors from try catch
This question already has an answer here:
Google app script only updates document's changes after finishing running. Can I force it to refresh before?
(1 answer)
Closed 2 years ago.
I have created a script that is triggered after button click on android app.
The script I've written gets a Google Docs Template and creates a copy of it to edit it afterwards.
After being edited i want to send an email to the email that will be inserted in the app.
The email should include the body, the subject and the file attached as pdf.
I've achieved to send the email with the pdf in it but it sends the copy of the Template without being edited.
Any suggestions to solve this problem?
Here's my code:
//Make a copy of the template file
var templateID = DriveApp.getFileById('My Template ID').makeCopy().getId();
//Rename The copied file
DriveApp.getFileById(templateID).setName(codigOperari + " - " + numero + " - " + operari + " - " + cliente + " - " + data);
//Get the document body as a variable
var doc = DocumentApp.openById(templateID);
var body = doc.getBody();
//Edit the copy of the template
body.replaceText('<<C>>', codigOperari);
body.replaceText('<<NUMPARTE>>', numero);
body.replaceText('<<FECHA>>', data);
body.replaceText('<<CLIENTE>>', cliente);
body.replaceText('<<CORREO>>', e.parameter.ETEmail);
body.replaceText('<<ORDENTRABAJO>>', e.parameter.ETMotiu);
body.replaceText('<<OPERARIO>>', operari);
//A lot of data more
//Message to be sent
var message = {
to: e.parameter.ETEmail,
subject: "Subject",
body: "This is a Test",
name: "Name",
attachments: [DocumentApp.getActiveDocument().getAs(MimeType.PDF)
.setName(codigOperari + " - " + numero + " - " + operari + " - " + cliente + " - " + data)]
}
//Send Email
MailApp.sendEmail(message);
I wrote you a comment as well, but I believe your issue is that you're sending the ActiveDocument and not the document that was edited.
DocumentApp.getActiveDocument() will only ever return the document the script is "anchored" to. If you open up a Google Doc or Spreadsheet, go to the Tools menu, and click Script Editor, you will be given an Apps Script file that is bound to your Google Doc. You can access the document directly in this Apps Script ONLY with DocumentApp.getActiveDocument(). Trying to edit this Google Doc from anywhere else will require the DocumentApp.openById() method.
My guess is that once you ran var body = DocumentApp.openById(templateID) you thought that you actually opened the document and activated it, which lead you to think that all you had to do was attach the "active document". This is wrong though, as you will only ever be attaching the source document. I'm assuming this is the template.
You already have the solution though. The document you're trying to send is stored in the doc variable. var doc = DocumentApp.openById() gives you a variable that points to that spreadsheet indefinitely. You can access this document through this variable at any point (you do so right afterwards with the var body = doc.getBody() statement.
Let me know if this fixed it!
I noticed that for a simple script like:
var url = "http://stackoverflow.com";
var page = require('webpage').create();
page.onConsoleMessage = function(msg) {
console.log('Page title is ' + msg);
};
page.onLoadFinished = function(status) {
console.log('Status: ' + status);
};
page.open(url, function(status) {
page.evaluate(function() {
console.log(document.title);
});
phantom.exit();
});
calling phantom.exit() will not exit immediately, rather it will wait 2 seconds before doing so. I'm using version 2.1.1.
Do you know where this delay comes from and how I can make phantom exit immediately? Thank you!
Look like "open issue":
https://github.com/ariya/phantomjs/issues/14033
I did try your code with the last version and I get the same behaviour.
You can use phantomjs#1.9.X as "jmullo" commented in the issue thread.
Like other browser, phantomjs is just headless. so it's exit() method will do many things, and it may cost couple of seconds.
I have the following code as a Google Apps Script (deployed as a web app) and have inserted it into my Google Enterprise page as a Google Apps Script Gadget. The UI (panel) loads properly with the label, textBox and button, but when I enter in text and click the button, I get the following error:
Error encountered: The resource you requested could not be located.
Here is my script:
function doGet(e) {
// create all UI elements
var myApp = UiApp.createApplication();
var panel = myApp.createVerticalPanel();
var label = myApp.createLabel('Please enter the name of your new site:');
var textBox = myApp.createTextBox().setName('txtSiteName');
var button = myApp.createButton('Create Site');
var btnHandler = myApp.createServerHandler('createNewSite');
button.addClickHandler(btnHandler);
btnHandler.addCallbackElement(panel);
// add all UI elements to the panel
panel.add(label);
panel.add(textBox);
panel.add(button);
// add the panel to the app
myApp.add(panel);
// return the app to the browser to be displayed
return myApp;
}
// button server handler
function createNewSite(e) {
var domain = SitesApp.getActiveSite().getUrl();
var siteName = e.parameter.txtSiteName;
var newSite = SitesApp.createSite(domain, siteName, 'script_center_demo', "this is just a test page");
return app.close();
}
Also, what is the difference between createSite() and createWebPage()?
EDIT: Ok, so using the same doGet() function above, my createNewSite() function could look like this?
function createNewSite(e) {
var domain = 'my-domain.com';
var siteName = e.parameter.txtSiteName;
var newPage = SitesApp.createSite(domain, siteName, 'script_center_demo', "this is just a test page");
var pageName = 'script_center_demo';
var html = '<div><p>This project aims to....</p></div>';
var site = SitesApp.getSite(domain, site);
site.createWebPage('Script Center Demo', pageName, html);
return app.close();
}
Look at this line:
var domain = SitesApp.getActiveSite().getUrl();
You're need to obtain a domain, e.g. example.com, but this line will yield a URI containing google's domain, and a resource path (that contains your domain). Example:
https://sites.google.com/a/example.com/mySite/
^^^^^^^^^^^
When you attempt to create a new site, it cannot be found as a domain. You need to strip the result of getUrl() down to just the domain name.
If you're the Domain administrator, you can use this instead:
var domain = UserManager.getDomain();
Ordinary domain users don't have access to the UserManager Service, so they would need to parse the site URL to extract their domain. I suggest using parseUri by Steven Levithan to handle the task:
var uri = parseUri(SitesApp.getActiveSite().getUrl());
var domain = parseUri(uri.path.slice(3)).host;
The .slice(3) operation is intended to remove /a/ from the path property of the parsed Site URI. This works on my accounts in multiple domains today - ymmv.
After that, we treat the remaining path as a URI and invoke parseUri() again, extracting the host property, which should be our domain.
Also, what is the difference between createSite() and createWebPage()?
You create an instance of a Site, using the Sites service method SiteApp.createSite. Not much to look at, a Site object is a container, a skeleton - you use the Site.createWebPage() method to create Web Pages that will be contained in the Site, and visible to users, mainly via web browsers.
Edit - Debugging Results
Debugging WebApps is tricky. Get familiar with "View - Execution Transcript", since it will show a trace of execution for your createNewSite() handler function when it's invoked. Using that technique, here's what I found, part 1:
We can't call SitesApp.getActiveSite().getUrl() in the handler, because when it's invoked there is no active site. You're already using the simple work-around of hard-coding the domain.
When trying to get a handle on the new site, you have var site = SitesApp.getSite(domain, site);. This is where your latest "resource error" message was coming from. The site parameter is left-over from insertion of the function - it needs to be a string, matching the site name used in createSite().
You're returning app.close(), but have no app defined in the function.
With those problems fixed, here's problems, part 2:
The dialog lets users enter a site name, but there are restrictions on those that need to be followed to make createSite succeed. The simplest rule is that the site name must be lower case. Why not let users enter the site title, and derive the name from that?
What if the site already exists? That's not handled. Same thing for the page creation, later on.
There's no feedback to the user. The example below has very rudimentary status updates in it, which are appended to the UI.
updated code
function createNewSite(e) {
var app = UiApp.getActiveApplication();
var domain = 'mitel.com';
var siteTitle = e.parameter.txtSiteName;
var siteName = siteTitle.toLowerCase();
var result = 'Results: ';
var site = SitesApp.getSite(domain, siteName); // Check if site already exists
if (site)
result += 'Site "' + siteName + '" exists, ';
else {
// Doesn't exist, so create it
site = SitesApp.createSite(domain, siteName, siteTitle, "this is just a test page");
result += 'Site "' + siteName + '" created with title "' + siteTitle + '", ';
}
var pageName = 'script_center_demo';
var html = '<div><p>This project aims to....</p></div>';
var page = site.getChildByName(pageName); // Check if page already exists
if (page)
result += 'Page "' + pageName + '" exists, ';
else {
// Doesn't exist, so create it
page = site.createWebPage('Script Center Demo', pageName, html);
result += 'Page "' + pageName + '" created, ';
}
result += 'Done.';
// Add result text to UI
var uiResult = app.createLabel(result, true);
app.add(uiResult);
return app.close();
}
I am quite new to Phantomjs and am starting to getting to know how to use it. However all of the semi advanced tutorials does not cover the thing i want to use Phantomjs for.
Now my question is how would i check if a Javascript is active on the site and if it is working correcly (i.e not throwing erros in the console).
I hope someone is able to point me in the right direction or know how to do this.
you can interact with the open page using the webpage.evaluate method:
var page = require('webpage').create();
page.open('http://m.bing.com', function(status) {
var title = page.evaluate(function(s) {
//what you do here is done in the context of the page
//this console.log will appear in the virtual page console
console.log("test")
//here they are just returning the page title (tag passed as argument)
return document.querySelector(s).innerText;
//you are not required to return anything
}, 'title');
console.log(title);
phantom.exit(); //closes phantom, free memory!
});
in order to see the virtual page console, you have to add a onConsoleMessage callback:
page.onConsoleMessage = function(msg, lineNum, sourceId) {
console.log('CONSOLE: ' + msg + ' (from line #' + lineNum + ' in "' + sourceId + '")');
};
EDIT: by default javascript is executed.