I am trying to dynamically set the Chrome download path in conf.js for Protractor. Our webservice exports a file and I am writing a test that needs to know where the download file is going to be in order to verify it. Right now, I am hard setting the browser's download path. The problem is that other members of my team and the build machines will also be running this test and there is no single download path I could choose that would work on every dev and build machine. After doing some reading, I thought the best solution would be get the user data directory from the getCapabilities() function inside the onPrepare function, and then set that as the download directory, like so:
onPrepare: function () {
var jasmineReporters = require('jasmine-reporters');
jasmine.getEnv().addReporter(new jasmineReporters.JUnitXmlReporter( {
savePath: 'reports', consolidateAll: true } ));
var cap = browser.getCapabilities();
// Set prefsDict using cap.caps_.userDataDir
},
capabilities: {
'chromeOptions': {
'prefs': prefsDict
}
}
This would allow the code to be dynamic, but getCapabilities returns a promise, so the code above is not going to work because conf.js will finish constructing the config object before the promise resolves. Using a then function on getCapabilities doesn't help because I can't construct the capabilities section of my config object in the then function. I can't call getCapabilities outside of the onPrepare function because conf.js itself doesn't have context for it. Setting a network path is also not feasible for the team's setup.
Has anyone else tackled something like this? Is there any other way to programmatically set the download path for Chrome?
This probably doesn't solve the issue in the way you'd like, but you could run
protractor conf.js --capabilities.chromeOptions.prefs 'path/to/user/folder'
if the user is savvy enough to know, find, or store that information.
Edit:
You might be able to use .execute() to force the browser.getCapabilities(); to fulfill before moving to the next statement.
Normally called by protractor.promise.controlFlow().execute( myPromise )
However, I think execute() also returns a promise, so you might be back to square one with this idea.
Related
I am writing a VSCode extension and I need a way to know when a project gets a new dependency to trigger some action. For that, I decided to watch package.json file using 'fs.watchFile'. But the problem is that fs sees the change only after saving the file and it takes a second or two. Moreover, if a user adds a new dependency manually to package.json there is no change event until the user saves it. I wonder if VSCode has some internal API that will do it better than fs.
VSCode has a nice utility for that vscode.workspace.createFileSystemWatcher. It's better than fs implementation because it is also triggered when the file is 'dirty' before it is saved. Possible implementation is:
const watcher = vscode.workspace.createFileSystemWatcher(
packageJsonPath, // absolute path to package.json
true, // ignore create events
false, // don't ignore change events
true, // ignore delete events
);
watcher.onDidChange(() => {
// trigger some action
})
// when not needed
if (watcher) {
watcher.dispose();
}
We can accesss the remote files via SMB protocol
Finder Menu > Go > Connect to server.
ex: smb:///cifsshare/master.tif"
But when we push the command, we only end up to opening the enclosing directory and not to the tif file. Now if i need to open the master.tif file i need to double click and open it. But for the connection i entered address of the file.
Iam trying to achieve same functionality with safari extension.
NSWorkspace.
if let url = URL(string: path) {
if NSWorkspace.shared.open(url) {
print("Url is opened")
}
}
Result: Same :(
When tried with Process()
//1
let toolPath = "/usr/bin/open"
let arguments = [pathUrl.absoluteString]
//2
let task = Process()
task.launchPath = toolPath
task.arguments = arguments
task.launch()
task.waitUntilExit()
Result: Not Working :(
Is it even possible in macos?
Any clue how to achieve this, is highly appreciated.
You can do this as a two step process:
Mount the SMB share to a local mount point
Open the file within that mount mount.
Unmount the SMB share when you're done with it.
I couldn't find a way to do #1 in a predictable manner. I.e., if something was already mounted at /Volumes/cifsshare, then opening smb:///cifsshare would automatically mount it to a new folder (/Volumes/cifsshare (1), if I recall correctly), without giving you feedback as to where exactly it ended up.
At a glance, it looks like the APIs that Finder uses to mount SMB reside within private frameworks, so there doesn't to be a nice easy API like SMB.mount(smbURL, to: mountPoint).
You can try using the Process API to call mount_smbfs (which is just a wrapper around mount -t smbfs). You can use it to mount your SMB share to a mount point of your own choosing, like /Volumes/MyAppSMBShare or whatever.
From there, you can open the file as normal:
NSWorkspace.shared.open(URL(fileURLFromPath: "/Volumes/MyAppSMBShare/master.tif))
So i wanted to get into Test Driven Development and decided to use Jasmine on my project.
The thing is, i can't load fixtures.
The 2 solutions commonly proposed are :
Run chrome with --allow-file-access-from-files
Serve the file from you local server
So i used the first solution, but no result.
Then i set up the routes of my webserver so that localhost/fixture/my_fixture would return the content of my_fixture.html.
So when i manually access localhost/fixture/my_fixture, the content of the fixture is displayed on screen. But in my jasmine spec file, when i use :
jasmine.getFixtures().fixturesPath = 'http://localhost/fixture'
loadFixtures('quizz_fixture')
I get the following errors :
Error: Fixture could not be loaded: http://localhost/fixture/quizz_fixture
(status: error, message: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'http://localhost/fixture/quizz_fixture?_=1455854875950'.)
When i use the URL given in the error, my browser displays the content of the fixture without errors.
Therefore, i don't understand the reason for this error. Does anyone have an insight?
Edit:
Web server : Apache
Browser : Chrome
OS : Windows 7
Edit 2
The issue comes from jasmine-jquery, on line 139 below, where the fail function is called. I can't figure out what's happening as the URL that supposedly can't be loaded actually loads just fine in my browser :
jasmine.Fixtures.prototype.loadFixtureIntoCache_ = function (relativeUrl) {
var self = this
, url = this.makeFixtureUrl_(relativeUrl)
, htmlText = ''
, request = $.ajax({
async: false, // must be synchronous to guarantee that no tests are run before fixture is loaded
cache: false,
url: url,
dataType: 'html',
success: function (data, status, $xhr) {
htmlText = $xhr.responseText
}
}).fail(function ($xhr, status, err) {
throw new Error('Fixture could not be loaded: ' + url + ' (status: ' + status + ', message: ' + err.message + ')')
})
The result is :
Failed to load 'http://localhost/fixture/quizz_fixture.html?_=1456886216017'
Which works when called in the browser. I just don't get it.
Thanks.
It's really hard to answer without knowing at least a little about the nature of your server, or what the fixture looks like. Is the server just a simple file server like node-http-server, or is this pointing to your app? Is it serving the fixture correctly? Does your fixture have a mistake in it? I can't tell any of that from here.
What I would say though is that if you are just beginning TDD you should probably avoid fixtures entirely. One of the biggest challenges to somebody new to TDD is writing small enough tests, and Jasmine fixtures make it easy to write really big tests.
Instead I would recommend manually adding the bare minimum of DOM you need to the page and removing that in an after hook. jasmine-fixture is a tool that essentially does this. This'll force you to consider how much of the DOM you actually need to write a test, and will make the DOM changes you are making visible in the tests itself.
So i found a very unsatisfying solution, but a solution nonetheless.
To summarize
Using chrome, i tried to load jasmine fixture from a local file, which wouldn't work with chrome (this is something known, disabled for security reasons).
I tried using the chrome flag --allow-file-access-from-files but it didn't work. So i gave up on using a fixture from a local file.
I understood that the fixture file had to be served from my web server, which i did. But it didn't work either, because of some Ajax error related to the caching of fixtures. I tried updating my version of jquery (which was a bit old) but it didn't work. In the end, I wasn't able to understand what the issue was.
I downloaded firefox and tried executing the jasmine specRunner with the configuration of point 3 above (fixture served by web server) but again, it didn't work.
Using firefox, I reverted to the method in point 1, which is using a local fixture file, and it did work. I hate that solution, but i need to go forward, so that will do.
Conclusion
If stuck with that kind of issue, save yourself some time and use firefox which will allow the use of a local fixture file.
In the command line you can write:
start chrome --allow-file-access-from-files "path_to_test/SpecRunner.html"
That solved to me... hope can help some more people.
I am fumbling around with the free Chrome Dev Editor on my Chromebook. I am trying to use the fileSystem to read and write .txt files. It is all very wrapped up, not at all like in C. I can no more tell if I am even allowed to do something, let alone where the proper place is to find out how.
I think the files I can see using the Files thingy are in the sandbox that I am allowed to play in (meaning, folders that are accessible by the app?) The root is called Downloads. Sure enough, if I use all the dot calls and callback arguments for the read, as in the examples at developer.chrome.com/apps/filesystem, it works. But I have to have a prompt
every time for both reads and writes.
A little more Googling came up with this trick: (I think it was here in stackoverflow, in fact) a chrome.runtime call, getPackagedDirectoryEntry, that seems to give me a handle to the folder of my app. Great! That's all I need to not have to go through the prompting. For the readfile, anyway.
But then trying to apply the same trick to the writefile did not work. In fact, it did nothing discernible. No errors, no complaints. Nothing. Even though the write file with prompting works fine (so presumably I have the permissions and Blob construction right.) What to do?
Here is my code:
function test(){
// Samsung 303C Chromebook - Chrome Dev Editor - /Downloads/Daily/main.js
// prompted write
chrome.fileSystem.chooseEntry({type:'saveFile'},function(a){
a.createWriter(function(b){
b.write(new Blob(["Programming fun"],{type:'text/plain'}));
},function(e){trace.innerText = 'error is ' + e;});
});
// unprompted read
chrome.runtime.getPackageDirectoryEntry(function(a){
a.getFile('text.txt',{},function(b){
b.file(function(c){
var d = new FileReader();
d.onloadend = function(){trace.innerText = this.result;};
d.readAsText(c);
});
});
});
// unprompted write - why not?
chrome.runtime.getPackageDirectoryEntry(function(a){
a.getFile('new.txt',{create:true},function(b){
b.createWriter(function(c){
c.write(new Blob(["Miss Manners fan"],{type:'text/plain'}));
},function(e){trace.innerText = 'error is ' + e;});
});
});
}
To be fair, Filesystem API is a big mess of callbacks and it's not unreasonable to get drowned in it.
It's not currently documented, but chrome.runtime.getPackageDirectoryEntry returns a read-only DirectoryEntry, and there is no way to make it writable (it's specifically blacklisted).
You probably don't see an error, because it fails at the getFile stage, for which you don't have an error handler.
Unfortunately, for a Chrome App the only option to write out to a real filesystem is to prompt the user. However, you can retain the entry and ask only once.
If you don't need to write out to the real filesystem but need only internal storage, HTML Filesystem API can help you (yes, it's marked as abandoned, but Chrome maintains it since chrome.fileSystem is built on it).
Extensions additionally have access to chrome.downloads API that enables writing to (but not reading) the Downloads folder.
P.S. What you see in Files app is your "real" local filesystem in ChromeOS + mounted cloud filesystems (e.g. Google Drive)
You can use the basic web Filesystem API. First, add the "unlimitedStorage" permission. Then, copy the packaged files to the sandboxed filesystem, like this:
chrome.runtime.getPackageDirectoryEntry(function(package) {
package.getMetadata(function(metadata) {
webkitRequestFileSystem(PERSISTENT, metadata.size, function(filesystem) {
package.copyTo(filesystem.root)
})
})
})
I'm trying to setup my own nodejs server, but I'm having a problem. I can't figure out how to see changes to my application without restarting it. Is there a way to edit the application and see changes live with node.js?
Nodules is a module loader for Node that handles auto-reloading of modules without restarting the server (since that is what you were asking about):
http://github.com/kriszyp/nodules
Nodules does intelligent dependency tracking so the appropriate module factories are re-executed to preserve correct references when modules are reloaded without requiring a full restart.
Check out Node-Supervisor. You can give it a collection of files to watch for changes, and it restarts your server if any of them change. It also restarts it if it crashes for some other reason.
"Hot-swapping" code is not enabled in NodeJS because it is so easy to accidentally end up with memory leaks or multiple copies of objects that aren't being garbage collected. Node is about making your programs accidentally fast, not accidentally leaky.
EDIT, 7 years after the fact: Disclaimer, I wrote node-supervisor, but had handed the project off to another maintainer before writing this answer.
if you would like to reload a module without restarting the node process, you can do this by the help of the watchFile function in fs module and cache clearing feature of require:
Lets say you loaded a module with a simple require:
var my_module = require('./my_module');
In order to watch that file and reload when updated add the following to a convenient place in your code.
fs.watchFile(require.resolve('./my_module'), function () {
console.log("Module changed, reloading...");
delete require.cache[require.resolve('./my_module')]
my_module = require('./my_module');
});
If your module is required in multiple files this operation will not affect other assignments, so keeping module in a global variable and using it where it is needed from global rather than requiring several times is an option. So the code above will be like this:
global.my_module = require ('./my_module');
//..
fs.watchFile(require.resolve('./my_module'), function () {
console.log("Module changed, reloading...");
delete require.cache[require.resolve('./my_module')]
global.my_module = require('./my_module');
});
Use this:
https://github.com/remy/nodemon
Just run your app like this: nodemon yourApp.js
There should be some emphasis on what's happening, instead of just shotgunning modules at the OP. Also, we don't know that the files he is editing are all JS modules or that they are all using the "require" call. Take the following scenarios with a grain of salt, they are only meant to describe what is happening so you know how to work with it.
Your code has already been loaded and the server is running with it
SOLUTION You need to have a way to tell the server what code has changed so that it can reload it. You could have an endpoint set up to receive a signal, a command on the command line or a request through tcp/http that will tell it what file changed and the endpoint will reload it.
//using Express
var fs = require('fs');
app.get('reload/:file', function (req, res) {
fs.readfile(req.params.file, function (err, buffer) {
//do stuff...
});
});
Your code may have "require" calls in it which loads and caches modules
SOLUTION since these modules are cached by require, following the previous solution, you would need a line in your endpoint to delete that reference
var moduleName = req.params.file;
delete require.cache[moduleName];
require('./' + moduleName);
There's a lot of caveats to get into behind all of this, but hopefully you have a better idea of what's happening and why.
What's “Live Coding”?
In essence, it's a way to alter the program while it runs, without
restarting it. The goal, however, is to end up with a program that
works properly when we (re)start it. To be useful, it helps to have an
editor that can be customized to send code to the server.
Take a look: http://lisperator.net/blog/livenode-live-code-your-nodejs-application/
You can also use the tool PM2. Which is a advanced production process tool for node js.
http://pm2.keymetrics.io/
I think node-inspector is your best bet.
Similar to how you can Live Edit Client side JS code in Chrome Dev tools, this utilizes the Chrome (Blink) Dev Tools Interface to provide live code editing.
https://github.com/node-inspector/node-inspector/wiki/LiveEdit
A simple direct solution with reference to all answers available here:
Node documentation says that fs.watch is more efficient than fs.watchFile & it can watch an entire folder.
(I just started using this, so not really sure whether there are any drawbacks)
fs.watch("lib", (event_type, file_name) => {
console.log("Deleting Require cache for " + file_name);
delete require.cache[ require.resolve("./lib/" + file_name)];
});