JScript: Dynamically load JavaScript libraries - javascript

I am currently writing a JavaScript script for the Microsoft JScript Runtime Environment. It's not in a browser, but rather going to be run more like a SysAdmin would use VBScript. I've written a lot of code, and while some of it is specific for what needs to be accomplished, a majority of it is supporting framework for the script to do what it needs to do. I'd like to use this sum of code in other future scripting adventures, but as to my current knowledge, I would have to copy and paste these mini-libraries over and over again, and well, that's just an update nightmare for one and two, it's inefficient. I know it's possible to dynamically load JS when I have a window or document, I know it's possible to require() JS files in Node.js, but is this possible in the raw JScript Runtime for MS?

Look into the Windows Script File (*.wsf) format. One of its features is to allow for includes like you're describing. An example taken from the linked documentation:
<job id="IncludeExample">
<script language="JScript" src="FSO.JS"/>
<script language="VBScript">
' Get the free space for drive C.
s = GetFreeSpace("c:")
WScript.Echo s
</script>
</job>
where "FSO.JS" contains the JScript library.

Assuming your talking about the WSH, you can load a file and eval the contents, which is much the same as including it.
var incfso=new ActiveXObject("Scripting.FileSystemObject");
include = function(x) {
eval(incfso.OpenTextFile(x,1).ReadAll());
}
source: http://www.mailsend-online.com/blog/wsh-javascript-includes.html
I couldn't find a global object like "window" for jscript, but you can sort of create one.
var host = this;
var test = "hello-world";
var messagebox = new ActiveXObject("wscript.shell");
if (host.test) {
messagebox.Popup("host.test exists, value = " + host.test);
} else {
messagebox.Popup("host.test does not exist.");
}
I think "host" should now effectively be the global object. (the example works for me anyway)

Related

Javascript Nashorn scripting mode: how to write to file

I'm writing a shell script to be run with jjs -scripting under Java 8. However, a key requirement is that I need to be able to write to a number of files. (So I can't just print() to stdout and redirect.)
There's handily readFully to read a file, but I don't see any writeFully, which seems odd to me.
I thought probably I could just $EXEC an echo command, but I can't get that to work:
jjs> x='some string'
some string
jjs> $EXEC("echo '"+x+"' >test.out");
some string >test.out
So my next thought is that I have to load up and call the appropriate Java classes, but that seems like it's over-complicating a simple function. What am I missing?
The best I could figure out was to do it via the Java FileWriter class. For example, I had an array of links I needed written to a file:
var FileWriter=Java.type("java.io.FileWriter");
var olinkfile = caldir+"/"+year+"_links.html";
var fw = new FileWriter(olinkfile);
fw.write(links.join("\n"));
fw.write("\n");
fw.close(); // forgetting to close it results in a truncated file
Although it would have been nice for JJS to provide a function to do this directly from JavaScript without having to instantiate the FileWriter class manually, this really isn't too much code. And once you've done it once it seems almost obvious.

How to read and write to a file (Javascript) in ui automation?

I want to identify few properties during my run and form a json object which I would like to write to a ".json"file and save it on the disk.
var target = UIATarget.localTarget();
var properties = new Object();
var jsonObjectToRecord = {"properties":properties}
jsonObjectToRecord.properties.name = "My App"
UIALogger.logMessage("Pretty Print TEST Log"+jsonObjectToRecord.properties.name);
var str = JSON.stringify(jsonObjectToRecord)
UIALogger.logMessage(str);
// -- CODE TO WRITE THIS JSON TO A FILE AND SAVE ON THE DISK --
I tried :
// Sample code to see if it is possible to write data
// onto some file from my automation script
function WriteToFile()
{
set fso = CreateObject("Scripting.FileSystemObject");
set s = fso.CreateTextFile("/Volumes/DEV/test.txt", True);
s.writeline("HI");
s.writeline("Bye");
s.writeline("-----------------------------");
s.Close();
}
AND
function WriteFile()
{
// Create an instance of StreamWriter to write text to a file.
sw = new StreamWriter("TestFile.txt");
// Add some text to the file.
sw.Write("This is the ");
sw.WriteLine("header for the file.");
sw.WriteLine("-------------------");
// Arbitrary objects can also be written to the file.
sw.Write("The date is: ");
sw.WriteLine(DateTime.Now);
sw.Close();
}
But still unable to read and write data to file from ui automation instruments
Possible Workaround ??
To redirect to the stdout if we can execute a terminal command from my ui automation script. So can we execute a terminal command from the script ?
Haven't Tried :
1. Assuming we can include the library that have those methods and give it a try .
Your assumptions are good, But the XCode UI Automation script is not a full JavaScript.
I don't think you can simply program a normal browser based JavaScript in the XCode UI Automation script.
set fso = CreateObject("Scripting.FileSystemObject");
Is not a JavaScript, it is VBScript which will only work in Microsoft Platforms and testing tools like QTP.
Scripting.FileSystemObject
Is an ActiveX object which only exists in Microsoft Windows
Only few JavaScript functions like basic Math, Array,...etc..Are provided by the Apple JavaScript library, so you are limited to use only the classes provided here https://developer.apple.com/library/ios/documentation/DeveloperTools/Reference/UIAutomationRef/
If you want to do more scripting then Try Selenium IOS Driver http://ios-driver.github.io/ios-driver/
Hey so this is something that I was looking into for a project but never fully got around to implementing so this answer will be more of a guide of what to do than step by step copy and paste.
First you're going to need to create a bash script that writes to a file. This can be as simple as
!/bin/bash
echo $1 >> ${filename.json}
Then you call this from inside your Xcode Instruments UIAutomation tool with
var target = UIATarget.localTarget();
var host = target.host();
var result = host.performTaskWithPathArgumentsTimeout("your/script/path", ["Object description in JSON format"], 5);
Then after your automation ends you can load up the file path on your computer to look at the results.
EDIT: This will enable to write to a file line by line but the actual JSON formatting will be up to you. Looking at some examples I don't think it would be difficult to implement but obviously you'll need to give it some thought at first.

Flash and External Javascript [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
calling a Flash ExternalInterface with JavaScript
I have a flash file with AS code. I want to run Javascript that will run a function the AS. For example: In the AS I have a function called "loadXML". The object that holds the SWF file called "pawel" (The ID of the object). How can I run a Javascript code that will run on "pawel" the function "loadXML"? I'm using Flash 6 with AS 3.
You should use ExternalInterface.addCallback() method. See http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/external/ExternalInterface.html#addCallback() for details.
I suggest you check this http://www.redcodelabs.com/2012/04/calling-actionscript-method-from-javascript/ it has running sample and as3/js code.
I believe the goal here is to send the swf (which has compiled an external .as file) the location of an xml file somewhere on the server so the swf can compile, parse, and create something.
I've done this many times, using flash variables, which may be useful to you as well. When embedding the .swf in your webpage you can send it flash variables via js or html, or dynamically with php. Once i have my fla working perfectly with hardcoded variables (like the xml) i then add the flash variable code to the head and make a few minor adjustments to the fla – which usually breaks the fla from running "properly" within flash (because it's now dependent upon these external variables)
anyways, here's how i do my flash vars (there's other ways, worth a good google search)
import flash.net.*;
var flashVars:Object = new Object();
flashVars = this.loaderInfo.parameters;
var xmlVal;
for (var item:String in flashVars)
{
switch (item)
{
case "xmlLocation" :
xmlVal = String(flashVars[item]);
break;
}
}
Here's the javascript which sends the values:
<script type="text/javascript">
//flashObj
var flashvars = {};
flashvars.xmlLocation = "http://google.com/myXML.xml";
var params = {wmode:"transparent"};
var attributes = {};
swfobject.embedSWF("images/banner.swf", "yourSliderId", "175", "300", "9.0.0", false, flashvars, params, attributes);
</script>
this is using SWFObject (an open API flash embedding js library) to handle the swf embed. I prefer it because if you look at the code above you can read it and understand it, the default way is really hard to read, edit and understand.
If you simply need XML and then you're done, this will work for you. If you still need to say hit the 'next' or 'previous' button using javascript, refer to this web site article, i believe this may help you out further:
http://arrixlive.wordpress.com/2005/03/25/javascript-in-love-with-flash-control-swf-from-javascript/

Is there a way to AutoFormat (Javascript) code in TestComplete?

So similar to ALt-Shift-F in Netbeans, is there a to do this right in the ide in TestComplete? Not sure if this is possible or if anyone can think of a workaround to autoFormat without leaving the TestComplete window.
I'm trying to get the below solution to work with http://jsbeautifier.org/ for javascript / Jscript code in TestComplete.
Thanks
Great question!
There is no built-in function for that. So, we should not expect any solution to be 100% convenient - it is just not a simple task to modify the current script editor contents (if at all possible). So, whatever you do, it will still be some kind of compromise.
In general, the task is three-fold:
Get the current unit code.
Format the code.
Put the code back to the unit.
According to my understanding, items 1 and 3 can be accomplished only by creating a TestComplete plug-in - accessing editors for project nodes is not an easy thing.
UPDATE: silly me! There is a way to access the script editor code - I've updated the below part.
What will help us avoid switching to a different app, are the Script Extensions:
We create a custom Checkpoint in the form of a Script Extension, and install it to TestComplete. As a result, we get a button on the toolbar that we can click to invoke our code.
In the design time action, we call some code that reads the editor contents, then uses external code formatting functionality, and replaces the editor contents with the formatted code.
It would extremely interesting to see the implementations other TestComplete users can suggest! As a start, I am posting a solution that includes using an external web site to format VBScript code (http://www.vbindent.com/). I know that the starter of the post is probably using JScript, but I have not found a JScript formatter yet.
My solution is a simple Script Extension. I can't post a file here, so I will post the code of the two Script Extension files:
Description file:
<!-- Description.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<ScriptExtensionGroup>
<Category Name="Checkpoints">
<ScriptExtension Name="VBScript Code Indent" Author="SmartBear Software" Version="0.1" HomePage="smartbear.com">
<Script Name="VBIndent.js">
<DesignTimeAction Name="Indent Current VBScript Unit" Routine="DesignTimeExecute"/>
</Script>
<Description>
Indents VBScript code in the currently active unit.
</Description>
</ScriptExtension>
</Category>
</ScriptExtensionGroup>
Code file:
// VBIndent.js
function DesignTimeExecute()
{
if (CodeEditor.IsEditorActive)
{
var newCode = IndentVBSCode_Through_VBIndent(CodeEditor.Text);
if (null == newCode)
return;
CodeEditor.Text = newCode;
}
}
function IndentVBSCode_Through_VBIndent(codeToIndent)
{
var URL_VBIndent = "http://www.vbindent.com/?indent";
var httpObj = Sys.OleObject("MSXML2.XMLHTTP");
httpObj.open("POST", URL_VBIndent, false);
httpObj.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
httpObj.send("thecode=" + escape(codeToIndent));
var responseText = httpObj.responseText;
// Extract the indented code from the response
var rx = /<textarea name=\"thecode\".*?>((.*\n)*?)<\/textarea>/;
matches = rx.exec(responseText);
if (null == matches)
{
return null;
}
codeIndented = matches[1];
return codeIndented;
}
After you create these files, and put them to something like "\Bin\Extensions\ScriptExtensions\VBIndent", and click "File | Install Script Extensions | Reload", you will see a new "Indent Current VBScript Unit" item in the custom checkpoints drop-down button on the Tools toolbar. Clicking the element will format the VBScript code in the currently active editor.
So, this is to give a clear idea of what a solution can look like. Better suggestions are welcome! Share your thoughts!
FYI
I've done. Based on your posts.
JSFormat.tcx
https://drive.google.com/uc?export=download&id=0B1x_73bHRc2Jcm8wbTJ2dUpZQTQ
To install the extension copy attached file JSFormat.tcx to C:\Program Files (x86)\SmartBear\TestComplete 10\Bin\Extensions\ScriptExtensions
To use view next image:
https://drive.google.com/uc?export=download&id=0B1x_73bHRc2Jc3RuLXFpTnlCSnc
Regards

Mozilla (Firefox, Thunderbird) Extension: How to get extension id (from install.rdf)?

If you are developing an extension for one of the mozilla applications (e.g. Firefox, Thunderbird, etc.) you define a extension id in the install.rdf.
If for some reason you need to know the extension id e.g. to retrieve the extension dir in local file system (1) or if you want to send it to a webservice (useage statistic) etc. it would be nice to get it from the install.rdf in favour to have it hardcoded in your javascript code.
But how to access the extension id from within my extension?
1) example code:
var extId = "myspecialthunderbirdextid#mydomain.com";
var filename = "install.rdf";
var file = extManager.getInstallLocation(extId).getItemFile(extId, filename);
var fullPathToFile = file.path;
I'm fairly sure the 'hard-coded ID' should never change throughout the lifetime of an extension. That's the entire purpose of the ID: it's unique to that extension, permanently. Just store it as a constant and use that constant in your libraries. There's nothing wrong with that.
What IS bad practice is using the install.rdf, which exists for the sole purpose of... well, installing. Once the extension is developed, the install.rdf file's state is irrelevant and could well be inconsistent.
"An Install Manifest is the file an Add-on Manager-enabled XUL application uses to determine information about an add-on as it is being installed" [1]
To give it an analogy, it's like accessing the memory of a deleted object from an overflow. That object still exists in memory but it's not logically longer relevant and using its data is a really, really bad idea.
[1] https://developer.mozilla.org/en/install_manifests
Like lwburk, I don't think its available through Mozilla's API's, but I have an idea which works, but it seems like a complex hack. The basic steps are:
Set up a custom resource url to point to your extension's base directory
Read the file and parse it into XML
Pull the id out using XPath
Add the following line to your chrome.manifest file
resource packagename-base-dir chrome/../
Then we can grab and parse the file with the following code:
function myId(){
var req = new XMLHttpRequest();
// synchronous request
req.open('GET', "resource://packagename-base-dir/install.rdf", false);
req.send(null);
if( req.status !== 0){
throw("file not found");
}
var data = req.responseText;
// this is so that we can query xpath with namespaces
var nsResolver = function(prefix){
var ns = {
"rdf" : "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
"em" : "http://www.mozilla.org/2004/em-rdf#"
};
return ns[prefix] || null;
};
var parser = CCIN("#mozilla.org/xmlextras/domparser;1", Ci.nsIDOMParser);
var doc = parser.parseFromString(data, "text/xml");
// you might have to change this xpath expression a bit to fit your setup
var myExtId = doc.evaluate("//em:targetApplication//em:id", doc, nsResolver,
Ci.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE, null);
return myExtId.singleNodeValue.textContent;
}
I chose to use a XMLHttpRequest(as opposed to simply reading from a file) to retrieve the contents since in Firefox 4, extensions aren't necessarily unzipped. However, XMLHttpRequest will still work if the extension remains packed (haven't tested this, but have read about it).
Please note that resource URL's are shared by all installed extensions, so if packagename-base-dir isn't unique, you'll run into problems. You might be able to leverage Programmatically adding aliases to solve this problem.
This question prompted me to join StackOverflow tonight, and I'm looking forward participating more... I'll be seeing you guys around!
As Firefox now just uses Chrome's WebExtension API, you can use #serg's answer at How to get my extension's id from JavaScript?:
You can get it like this (no extra permissions required) in two
different ways:
Using runtime api: var myid = chrome.runtime.id;
Using i18n api: var myid = chrome.i18n.getMessage("##extension_id");
I can't prove a negative, but I've done some research and I don't think this is possible. Evidence:
This question, which shows that
the nsIExtensionManager interface
expects you to retrieve extension
information by ID
The full nsIExtensionManager interface
description, which shows no
method that helps
The interface does allow you to retrieve a full list of installed extensions, so it's possible to retrieve information about your extension using something other than the ID. See this code, for example:
var em = Cc['#mozilla.org/extensions/manager;1']
.getService(Ci.nsIExtensionManager);
const nsIUpdateItem = Ci.nsIUpdateItem;
var extension_type = nsIUpdateItem.TYPE_EXTENSION;
items = em.getItemList(extension_type, {});
items.forEach(function(item, index, array) {
alert(item.name + " / " + item.id + " version: " + item.version);
});
But you'd still be relying on hardcoded properties, of which the ID is the only one guaranteed to be unique.
Take a look on this add-on, maybe its author could help you, or yourself can figure out:
[Extension Manager] Extended is very
simple to use. After installing, just
open the extension manager by going to
Tools and the clicking Extensions. You
will now see next to each extension
the id of that extension.
(Not compatible yet with Firefox 4.0)
https://addons.mozilla.org/firefox/addon/2195

Categories

Resources