protractor: test download file without knowing filename - selenium-webdriver

I followed this answer and it looks almost the thing I need.
The problem there is that he already knows the filename and I am doing e2e test for downloading a file, but the filename depends on the current time (even with milliseconds) so I don't really know the name (or it would be very difficult to get it).
I think I am missing something very simple here, but I was thinking of two ways:
Recreate filenames (with the same function that returns the name of this file) and start checking for existance of a file with that name, if it doesn't exist, then move to the next millisecond until I hit the right name.
Check the download folder for existance of "any" file, if I find one there then it should be the file I am downloading (for this case I don't know how to check an entire folder in protractor).
Hope you guys could help with these alternatives (I would like some help with point 2) or maybe give me a better one. Thanks

I ended up following #alecxe's suggestion and here is my answer:
var glob = require("glob");
browser.driver.wait(function () {
var filesArray = glob.sync(filePattern);
if (typeof filesArray !== 'undefined' && filesArray.length > 0) {
// this check is necessary because `glob.sync` can return
// an empty list, which will be considered as a valid output
// making the wait to end.
return filesArray;
}
}, timeout).then(function (filesArray) {
var filename = filesArray[0];
// now we have the filename and can do whatever we want
});

Just to add a little bit more background information to the #elRuLL's answer.
The main idea is based on 2 things:
browser.wait() fits the problem perfectly - it would execute a function continuously until it evaluates to true or a timeout is reached. And, the timeout mechanism is already built-in.
glob module provides a way to look for filenames matching a certain pattern (in the worst case, you can wait for the *.* - basically, any file to appear)

Related

How to check if a file was edited/modified by a user?

I'm having an issue in dart/flutter, I want to check if the user opens a file and modified/edited the file, and only if this happens I do something that is not important... for that purpose I used this chunk of code:
String dir = await bloc.buildFileDirectory(filePath);
File file = new File('$dir/filename');
DateTime date = await file.lastModified();
if(date.millisecondsSinceEpoch < someOtherFileTimeStamp)
do something
with the method lastModified() from File class in Dart, when the user open the file, it will consider a modification, and so it will trigger the if condition... is there any functional way to check for really modifications on the file? like editing some text inside the file, or change the name...something like that
Ty for your time
Yes, you can use the watcher library's FileWatcher.
Here's an example on how to use it:
final watcher = FileWatcher('main.dart');
final subscription = watcher.events.listen((event) {
switch (event.type) {
case ChangeType.ADD:
print('Added file');
break;
case ChangeType.MODIFY:
print('Modified');
break;
case ChangeType.REMOVE:
print('Removed');
}
});
If you need to determine whether the file changed since last time your program ran, then this will of course not work and you will have to use the timestamp as you're doing, or even hash the contents of the file and store it somewhere, so you can check later if the hash is still the same.

NancyFx will not display images

My last attempt: Don't even know what I'm doing anymore:
Get["/{any}/x.png"] = x => {
return Response.AsImage(Program.portal.ourRoot + "x.png");
};
Get["/{any}/{moreany}/x.png"] = x => {
return Response.AsImage(Program.portal.ourRoot + "x.png");
};
Get["/{any}/{moreany}/{extraany}/x.png"] = x => {
return Response.AsImage(Program.portal.ourRoot + "x.png");
};
What I currently have in my ConfigureConvetions (in the BootStrapper). I've tried a lot of permutations so far.
protected override void ConfigureConventions(NancyConventions conventions) {
//conventions.StaticContentsConventions.AddFile("x.png", ourRoot + "x.png");
conventions.StaticContentsConventions.Add(StaticContentConventionBuilder.AddFile("/portal/images/x.png", ourRoot + "x.png"));
conventions.StaticContentsConventions.Add(StaticContentConventionBuilder.AddDirectory("images", ourRoot, new string[] { "png" }));
conventions.StaticContentsConventions.Add(StaticContentConventionBuilder.AddDirectory("/portal/", ourRoot, new string[] { "png" }));
conventions.StaticContentsConventions.Add(StaticContentConventionBuilder.AddDirectory("/", ourRoot, new string[] { "png" }));
base.ConfigureConventions(conventions);
}
I have a CustomRootPathProvider that points to ourRoot (string, currently holds a direct C:\somepathstuffhere\ to a content directory).
I only need to serve a single image for my needs (at least, for now, things always tend to grow). I'm using the directory structure as variables, so I need to be able to serve this image from a very large amount of locations.
I have a copy of the image in my root folder, and in a directory called images (the "images" has had '/''s all over it, occasionally even through the middle). I am currently referencing the image with "/images/x.png", but I've tried from the root, just the name, and "images/x.png".
Thanks!
I will post back in the mean time if I figure it out (I'm assuming its something very simple.)
Solved: Worked Around? \ Non-Optimal
I changed my /images/x.png references to 'x.png', and then I dropped the extension reference to the following line.
conventions.StaticContentsConventions.Add(StaticContentConventionBuilder.AddDirectory("/", ourRoot));
Nancy started catching the 'x.png' image for the Root Page and the \Portal\ page. And then the 2nd Get /{any}/{moreany}/x.png started catching the rest of the 'x.png' requests (\Portal\Project).
I'm really not sure, why it started working all of a sudden. I've just been playing the permutation game.
The big non-optimal part, is every single directory's version of the image is treated as brand new. If anyone can solve this one for me, that'd be nice. If I figure out what to do to fix it myself, I will post back with my solution.
SOLVED
This solution won't interest anyone familiar with web programming. Its more of a new user pitfall situation. When I started setting up NancyFX I read the documentation fairly thoroughly (even if I didn't get it all on the first read). When I got to the web.config part, I first checked the Solution Explorer in VS and I didn't see one. So I just went into my project directory and created one (And there-in lies the problem). The one I made never applied settings to the project.
I figured it was a concept error, I just didn't know enough, to know where to look.\
Thx for the community's help! Hopefully my experience helps some other 1st time user out.

Delete avis and jpgs from a specified folder and older than x days

I want to use a script, that deletes AVIs and JPGs files from a specific folder. I want to filter them by date and extension. I have this script, which I think is really close to what I want, but it didn't deletes anything, it sends me an empty letter. (I know, I should comment out the trash parts, but it is for safety reasons so I will do it when my reports would look good)
function DeleteMyAVIs() {
var pageSize = 5000;
var files = null;
var token = null;
var i = null;
var SevenDaysBeforeNow = new Date().getTime()-3600*1000*24*7 ;
Logger.clear()
do {
var result = DocsList.getAllFilesForPaging(pageSize, token);
var files = DocsList.getFolder("motion").getFiles();
var token = result.getToken();
for(n=0;n<files.length;++n){
if(files[n].getName().toLowerCase().match('.avi')=='.avi' && files[n].getDateCreated().getTime() < SevenDaysBeforeNow){
//files[n].setTrashed(true)
Logger.log(files[n].getName()+' created on '+Utilities.formatDate(files[n].getDateCreated(), 'GMT','MMM-dd-yyyy'))
}
if(files[n].getName().toLowerCase().match('.mpg')=='.mpg' && files[n].getDateCreated().getTime() < SevenDaysBeforeNow){
//files[n].setTrashed(true)
Logger.log(files[n].getName()+' created on '+Utilities.formatDate(files[n].getDateCreated(), 'GMT','MMM-dd-yyyy'))
}
}
} while (files.length == pageSize);
MailApp.sendEmail('xy#gmail.com', 'Script AUTODELETE report', Logger.getLog());
}
You're not getting the files from the folder (it's fixed on the code below). Also, I recommend you get the folder by the id, which is a way more robust, because it allows you to rename the folder or move it inside others, and the code would still work.
Your match is also wrong (although it's not the reason it's not working), because the string will be converted into a regexp. And ".avi" would get any file with "avi" in it anywhere (aside from the very first 3 letters).
Lastly, DocsList token is not useful, because you cannot save it for a later execution, and we page not due to a Google Drive limitation, but Apps Script 6 minutes maximum execution time. In your case of deleting files, continuing the search is not really required since the files will not be there on the next search results anyway.
Lastly, when you're calling formatDate and passing GMT you're most likely going to shift the days by one, either one day before or after depending on where you are, unless you're really on GMT 0 hour and have no daylight saving shift (which I doubt). You should use your own real timezone or grab your script's default (like shown below).
function deleteMyAVIs() {
var pageSize = 500; //be careful with how much files you process at once, you're going to timeout
var sevenDaysAgo = Date.now()-1000*60*60*24*7;
var TZ = Session.getScriptTimeZone();
Logger.clear();
var result = DocsList.getFolderById('folder-id').getFilesForPaging(pageSize);
var files = result.getFiles();
//token = result.getToken(); //not useful and fortunately not important for your case
for( n=0;n<files.length;++n ) {
if(files[n].getName().toLowerCase().match('\\.(avi|mpg)$') && files[n].getDateCreated().getTime() < sevenDaysAgo){
//files[n].setTrashed(true)
Logger.log(files[n].getName()+' created on '+Utilities.formatDate(files[n].getDateCreated(), TZ,'MMM-dd-yyyy'))
}
}
MailApp.sendEmail('xy#gmail.com', 'Script AUTODELETE report', Logger.getLog());
}
By the way, if you ever require to continue a Drive search later on, you should use DriveApp instead of DocsList. Please see this other post where I show how to do it.

How to delete a File in Google Drive?

How do I write a Google Apps Script that deletes files?
This finds files:
var ExistingFiles = DocsList.find(fileName);
But DocsList.deleteFile does not exist to delete a file.
Is there a way to move those files to another Folder or to Trash?
The other workaround I would consider is to be able to override an existing file with the same name.
Currently when I want to create a file with a name already used in MyDrive then it creates a second file with the same name. I would like to keep 1 file (the new one is kept and the old one is lost).
There are 3 services available to delete a file.
DriveApp - Built-in to Apps Script
Advanced Drive Service - Built-in to Apps Script but must be enabled. Has more capability than DriveApp
Google Drive API - Not built-in to Apps Script, but can be used from Apps Script using the Drive REST API together with UrlFetchApp.fetch(url,options)
The DocsList service is now deprecated.
The Advanced Drive Service can be used to delete a file without sending it to the trash. Seriously consider the risk of not being able to retrieve the deleted file. The Advanced Drive Service has a remove method which removes a file without sending it to the trash folder. Advanced services have many of the same capabilities as the API's, without needing to make an HTTPS GET or POST request, and not needing an OAuth library.
function delteFile(myFileName) {
var allFiles, idToDLET, myFolder, rtrnFromDLET, thisFile;
myFolder = DriveApp.getFolderById('Put_The_Folder_ID_Here');
allFiles = myFolder.getFilesByName(myFileName);
while (allFiles.hasNext()) {//If there is another element in the iterator
thisFile = allFiles.next();
idToDLET = thisFile.getId();
//Logger.log('idToDLET: ' + idToDLET);
rtrnFromDLET = Drive.Files.remove(idToDLET);
};
};
This combines the DriveApp service and the Drive API to delete the file without sending it to the trash. The Drive API method .remove(id) needs the file ID. If the file ID is not available, but the file name is, then the file can first be looked up by name, and then get the file ID.
In order to use DriveAPI, you need to add it through the Resources, Advanced Google Services menu. Set the Drive API to ON. AND make sure that the Drive API is turned on in your Google Cloud Platform. If it's not turned on in BOTH places, it won't be available.
Now you may use the following if the file is as a spreadsheet, doc etc.:
DriveApp.getFileById(spreadsheet.getId()).setTrashed(true);
or if you already have the file instead of a spreadsheet, doc etc. you may use:
file.setTrashed(true);
This code uses the DocsList Class which is now deprecated.
try this :
function test(){
deleteDocByName('Name-of-the-file-to-delete')
}
function deleteDocByName(fileName){
var docs=DocsList.find(fileName)
for(n=0;n<docs.length;++n){
if(docs[n].getName() == fileName){
var ID = docs[n].getId()
DocsList.getFileById(ID).setTrashed(true)
}
}
}
since you can have many docs with the same name I used a for loop to get all the docs in the array of documents and delete them one by one if necessary.
I used a function with the filename as parameter to simplify its use in a script, use test function to try it.
Note : be aware that all files with this name will be trashed (and recoverable ;-)
About the last part of your question about keeping the most recent and deleting the old one, it would be doable (by reading the last accessed date & time) but I think it is a better idea to delete the old file before creating a new one with the same name... far more logical and safe !
Though the The service DocsList is now deprecated, as from the Class Folder references, the settrashed method is still valid:
https://developers.google.com/apps-script/reference/drive/folder#settrashedtrashed
So should work simply this:
ExistingFiles.settrashed(true);
Here is another way to do it without the need of Drive API. (based on Allan response).
function deleteFile(fileName, folderName) {
var myFolder, allFiles, file;
myFolder = DriveApp.getFoldersByName(folderName).next();
allFiles = myFolder.getFilesByName(fileName);
while (allFiles.hasNext()) {
file = allFiles.next();
file.getParents().next().removeFile(file);
}
}
Here is a slightly modified version using the above. This will backup said file to specified folder, also remove any old previous backups with the same name so there are no duplicates.
The idea is here to backup once per day, and will retain 1 month of backups in your backup folder of choice. Remember to set your trigger to daily in your Apps Script.
https://gist.github.com/fmarais/a962a8b54ce3f53f0ed57100112b453c
function archiveCopy() {
var file = DriveApp.getFileById("original_file_id_to_backup");
var destination = DriveApp.getFolderById("backup_folder_name");
var timeZone = Session.getScriptTimeZone();
var formattedDate = Utilities.formatDate(new Date(),timeZone,"dd"); // 1 month backup, one per day
var name = SpreadsheetApp.getActiveSpreadsheet().getName()+"_"+formattedDate;
// remove old backup
var allFiles = destination.getFilesByName(name);
while (allFiles.hasNext()) {
var thisFile = allFiles.next();
thisFile.setTrashed(true);
};
// make new backup
file.makeCopy(name,destination);
}

How to test file permissions using node.js?

How can I check to see the permissions (read/write/execute) that a running node.js process has on a given file?
I was hoping that the fs.Stats object had some information about permissions but I don't see any. Is there some built-in function that will allow me to do such checks? For example:
var filename = '/path/to/some/file';
if (fs.canRead(filename)) // OK...
if (fs.canWrite(filename)) // OK...
if (fs.canExecute(filename)) // OK...
Surely I don't have to attempt to open the file in each of those modes and handle an error as the negative affirmation, right? There's got to be a simpler way...
I am late, but, I was looking for same reasons as yours and learnt about this.
fs.access is the one you need. It is available from node v0.11.15.
function canWrite(path, callback) {
fs.access(path, fs.W_OK, function(err) {
callback(null, !err);
});
}
canWrite('/some/file/or/folder', function(err, isWritable) {
console.log(isWritable); // true or false
});
There is fs.accessSync(path[, mode]) nicely mentioned:
Synchronously tests a user's permissions for the file or directory specified by path. The mode argument is an optional integer that specifies the accessibility checks to be performed. Check File Access Constants for possible values of mode. It is possible to create a mask consisting of the bitwise OR of two or more values (e.g. fs.constants.W_OK | fs.constants.R_OK).
If any of the accessibility checks fail, an Error will be thrown. Otherwise, the method will return undefined.
Embeded example:
try {
fs.accessSync('etc/passwd', fs.constants.R_OK | fs.constants.W_OK);
console.log('can read/write');
} catch (err) {
console.error('no access!');
}
Checking readability is not so straightforward as languages like PHP make it look by abstracting it in a single library function. A file might be readable to everyone, or only to its group, or only to its owner; if it is not readble to everybody, you will need to check if you are actually a member of the group, or if you are the owner of the file. It is usually much easier and faster (not only to write the code, but also to execute the checks) to try to open the file and handle the error.
How about using a child process?
var cp = require('child_process');
cp.exec('ls -l', function(e, stdout, stderr) {
if(!e) {
console.log(stdout);
console.log(stderr);
// process the resulting string and check for permission
}
});
Not sure though if process and *child_process* share the same permissions.

Resources