Why can I only upload one file using Play and uploadify? - java

I wrote this simple Play-uploadify demo.
I want to an upload button that automatically upload an image each time its pressed.
For some reason, only the first time the button is pressed, I get an upload. After the button has been pressed once, further presses do not cause anything unless I "cancel" the previous uploads.
(I don't understand the meaning of canceling an upload with auto mode. Perhaps the problem is that my downloads never "complete" in some sense?)
Here is my action method:
public static void upload(File file, long userId){
System.out.println("Uploaded file name " + file.getName() +
" by user " + userId);
}
And the call to uploadify:
$(function() {
$("#uploader").uploadify({
uploader : '/public/libraries/uploadify/uploadify.swf',
script : '/Application/upload',
cancelImg : '/public/libraries/uploadify/cancel.png',
folder : '/uploads',
fileExt : '*.jpg;*.gif;*.png',
fileDesc : 'Image Files',
fileDataName: 'file',
scriptData: {userId: 123},
auto: true
});
});
Also, the upload never seems to complete - when I add an onComplete handler, it does't fire.

The problem was that I was not returning a HTTP 200 status code, because I didn't call any render method or return a value at the end of my action method.
Adding renderText("OK"); resolved my problem.
ok(); is a neater way of resolving it.

try to change it to
script : '/application/upload',
(notice the lowercase a in application... play always generates lowercase urls when you use the default route.)
as for only being able to upload one file at a time:
have you tested the upload in dev or production mode?
in dev mode, the amount of threads available for processing is one,
so it will block as soon as you want to upload a second file at the same moment

Related

How to use applescript to close upload dialog window from chromedriver instance?

I have a selenium test (selenide to be precise) where the scenario requires a file upload.
The element to which I'm uploading the file is a hidden input field which is located at the end of DOM;
<input type="file" style="height: 0; width: 0; visibility: hidden;" tabindex="-1" accept="*">
and appears only after clicking on the area where the file is supposed to be "drag&dropped" or loaded from the system;
<a class="browse" ref="fileBrowse" href="#">select files...</a>
that means I am unable to use any method I've known until now without the need to click the element first - e.g., sendKeys, uploadFile, uploadFromClassPath, etc. However, the moment I click the element, a dialog window appears. After loading the file, the window won't close and I have yet to find a robust solution to close that window.
Situation how the dialog window looks within the macOS and chrome setup
I am using macOS and chrome, which means I cannot use "autoIT", and I was not able to run "sikuliX" either to create a simple screenshot script.
I was able, however, to scramble up an applescript using Automator which worked fine provided we omit the web driver's instance existence. Meaning; if I run the script from the console, setting the website exactly as the automated test would find it - it works... Unfortunately, it does not work once the test instantiates and runs within the webdriver.
I have two questions I hope someone with more experience could answer:
1) How to make the applescript use the webdriver's instance and not the regular chrome window - should this be solved somehow, it's a pretty neat solution
2) Any other idea on how to close the upload dialog window?
The applescript
on run {input, parameters}
-- Click “Google Chrome” in the Dock.
delay 6.006100
set timeoutSeconds to 2.000000
set uiScript to "click UI Element \"Google Chrome\" of list 1 of application process \"Dock\""
my doWithTimeout( uiScript, timeoutSeconds )
return input
-- Click the ÒCancelÓ button.
delay 3.763318
set timeoutSeconds to 2.0
set uiScript to "click UI Element \"Cancel\" of sheet 1 of window \"PowerFLOW portal - Google Chrome\" of application process \"Chrome\""
my doWithTimeout(uiScript, timeoutSeconds)
return input
end run
on doWithTimeout(uiScript, timeoutSeconds)
set endDate to (current date) + timeoutSeconds
repeat
try
run script "tell application \"System Events\"
" & uiScript & "
end tell"
exit repeat
on error errorMessage
if ((current date) > endDate) then
error "Can not " & uiScript
end if
end try
end repeat
end doWithTimeout
the code used to run the script within the test
try {
new ProcessBuilder("/path/to/the/script").start();
} catch (IOException e) {
e.printStackTrace();
}
}
Besides trying to use the applescript, I've tried "java robot class" but I wasn't able to close the dialog window.
Using the snippet below, the uncommented part escapes the entire chrome window (the window goes "grey"/inactive) and not the dialog window, which honestly surprised me, as I have thought the dialog window was the main working window at that moment.
The part that is commented works, but as you can imagine, it is useless, should the test be run on any other machine as the coordinates are specific to my machine only.
try {
Robot robot = new Robot();
//robot.mouseMove(906, 526);
//robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
//robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
robot.keyPress(KeyEvent.VK_ESCAPE);
robot.keyRelease(KeyEvent.VK_ESCAPE);
} catch (AWTException e) {
e.printStackTrace();
}
The method itself looks just about like this
$$x("#ElementsCollection")
.findBy("text1")
.scrollIntoView(true)
.find(byXpath("#xpath")).val("text2")
.find(byXpath("#xpath") //this is the location of the <a> element mentioned above that needs to be clicked in order for <input type file> element to appear
.click();
$x("//input[#type=\"file\"]").sendKeys("/path/to/the/uploadedFile");
As I see, the original complexity on the way to achieve the goal is
the file is a hidden input field
and appears only after clicking on the area where the file is supposed to be "drag&dropped" or loaded from the system;
I.e. – the hidden file. Correct me if am wrong:)
But this should not be the problem, because the Selenium WebDriver's sendKeys command works with hidden elements of input tag with type=file. So just simple sendKeys should pass. The Selenide's uploadFromClassPath command is based on the original sendKeys - so it should pass too.
Here is a simple test that shows that uploading file does not depend on visibility of input element:
import org.junit.jupiter.api.Test;
import static com.codeborne.selenide.Condition.hidden;
import static com.codeborne.selenide.Condition.text;
import static com.codeborne.selenide.Selenide.*;
import static com.codeborne.selenide.Selenide.$;
public class TheInternetTest {
#Test
void fileUpload() {
// GIVEN
open("https://the-internet.herokuapp.com/upload");
executeJavaScript(
"document.getElementById('file-upload').style.display = 'none'"
);
$("#file-upload").shouldBe(hidden);
// WHEN
$("#file-upload").uploadFromClasspath("temp.txt");
$("#file-submit").click();
// THEN
$("#uploaded-files").shouldHave(text("temp.txt"));
}
}
Check the full working project with this code here: https://github.com/yashaka/selenide-file-upload-demo/blob/main/src/test/java/TheInternetTest.java
P.S.
The common best practice when writing Web UI Tests is "find the simple way to reach the goal instead of the best way in context of real user simulation". That's why we try to bypass all windows that are out of control for application under test. So my recommendation would be - forget apple script, and work with the input file directly through selenium webdriver.

Selenium Web driver gets blocked after getting a popup from another popup (IE driver)

I'm facing an issue when application I'm testing is opening a second level popup (I mean, a popup that rises another popup). I'm using Selenium for Java, version 2.42.2, with IE Driver.
My code currently manages all other flows and single pop ups windows, but when a second level popup appears my webdriver object gets irresponsive and just stuck in any method that try to get invoked. When this happens, I need to manually close the popup window and then driver method continues the execution of invoked method.
Maybe it worth mentioning, if I call the second popup from the main page (not from another popup) I am able to manage it without problems, so the problem seems to be related with the number of nested windows more than a specific problem for the page.
Take a look on below code:
String url = "/example.jsp"
int counter = 0;
boolean windowDetected = false;
// Waiting until page with given url gets detected
// It tries 10 times before it continues
while (counter++ < 10 && !windowDetected) {
waitForSeconds(1); // Just invokes Thread.sleep method,
System.out.println("before getting handlers, iteration " + counter + " of 10");
Set<String> handlers = driver.getWindowHandles();
System.out.println("after getting handlers, number of handlers: " + handlers.size());
for (String handler : handlers) {
try {
System.out.println("Moving to " + handler);
driver.switchTo().window(handler);
}
catch (NoSuchWindowException e) {
System.out.println("Window not found, it probably redirected to a different window");
break;
}
if (driver.getCurrentUrl().contains(url)) {
windowDetected = true;
waitForPageLoading(); // It just verify current page status to be completed
break;
}
}
}
I am able to position properly the driver in specific window with above code in other application pages, but when having the second level popup it just hangs on line Set handlers = driver.getWindowHandles(); that is the first method called on driver object after popup appeared. Similarly, if I had called another driver method like driver.getPageSource() the same would have happened in that method.
I am not able to change application structure (my scope is only for testing it), so doing changes in web application code is not an option for me now. I have read on different options like trying Robot class, but I think it will be difficult to implement with more complex pages and difficult to maintain.
Any idea of how can I solve this issue? Many thanks in advance.
Best regards,
Alberto.
After taking a look on IEDriverServer changelog, moving to a newer version of this driver solved the issue. Previous was 2.24.2, and now using 2.44. A slightly different behavior but that accomplishes what I wanted

mediaPlayer.setSpu() not working

Currently I am working on some code based on VLCJ to play video content, which is working pretty fine, but I am struggling hard making the setSpu() method work.
Just to mention, when it comes to load an external subtitle, in a file apart from the video file, it is working fine. The problem appears when I try to play subtitles contained in the media file. (e.g. subs contained into a MKV file).
I read carefully GitHub post "setSpu not working #278", and I think that maybe the problem is that I am not invoking the setSpu() method correctly.
To make it simple, I am trying to make it works on the example "uk.co.caprica.vlcj.test.basic.TestPlayer".
On TestPlayer.java class, I loaded all native vlc required libs and configured the mediaPath, and mediaPlayer, so if I execute the class, the media player is built properly, and the video starts playing.
Now, to try make the subtitle work, I reused the button "subTitlesButton" on "PlayerControlsPanel.java". First of all, as the spu to be set is the ID of the TrackDescription, I added the following code, and executed to get the spuDescriptions list:
subTitlesButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println(mediaPlayer.getSpuDescriptions());
}
});
When the Sub-titles button is pressed, the following output is get:
spuDescriptions=[TrackDescription[id=-1,description=Deshabilitar], TrackDescription[id=3,description=Pista 1 - [Español]], TrackDescription[id=4,description=Pista 2 - [Inglés]], TrackDescription[id=5,description=Pista 3 - [Español]]]
So, to keep it simple, I just tried to add the following code and execute it:
subTitlesButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println(mediaPlayer.getSpuDescriptions());
mediaPlayer.setSpu(3); // TrackDescription[id=3,description=Track 1 - [Spanish]]
}
});
The expected resault would be the subtitle "Track 1 - [Spanish]" with ID=3 to appear on screen, but nothing happens. The video goes on and is being played properly, but the sub-title is not shown.
All the other buttons, work fine when you pressed them, you get the expected result (pause, stop, play, fastforward, rewind, and so on)... so I dont get the point on why media.setSpu() is not working there.
Would be much appreciated some help :)
Thanks in advance.
EDITED The exact problem was that all subtitles contained in the media file (video.mkv) were UTF8 text encoded. I tried to re-mount the video.mkv file with mkvmerge, but this program allways converts SRT files to UTF8 text format.
WORKAROUND convert the SRT files to ASS subtitles format. If the video.mkv contains .ASS subtitles format, the subtitles are always loaded properly by VLC and also by vlcj libs.
Thanks a lot in advance for all the help provided.
If this question can be distilled down to how to use external SPU files with non-ASCII characters, you can try this:
Suppose you have some filename for your external SPU file, the filename containing non-ASCII characters, let's call this spuFileName...
Try:
String asciiFileName = new File(spuFileName)
.toURI()
.toASCIIString();
Or:
String asciiFileName = new File(spuFileName)
.toURI()
.toASCIIString()
.replaceFirst("file:/", "file:///");
Then use asciiFileName instead when you specify the SPU file for vlcj.
If I remember correctly, LibVLC requires ASCII strings on its API. This problem can also show itself if you try and play a video with a filename that contains non-ASCII characters (vlcj detects this and handles it automatically).
But I'm not sure if this really is your problem as given the partial log you posted it looks like VLC has indeed detected the SPU tracks correctly.
On the other hand, if this suggestion does actually work, vlcj could be changed to handle this case (an external SPU file) automatically.
When actually selecting SPU for display, whether the SPU are in a separate file or contained within the video itself, the only thing that matters is the id of the SPU track. vlcj passes this id directly to the LibVLC API method. The fact that the track description strings are not being encoded directly does not matter.
In earlier versions of VLC, this id was actually the index of the SPU track - so 0, 1, 2, 3 and so on.
With the current version of VLC (this was changed around February 2013, I think this means VLC 2.1+) this was fixed to use the actual SPU track identifiers.
So depending on your version of VLC, if the track identifiers are not working for you try just passing an index instead.

How to wait for user decision when downloading file

I want to continue with this question: How to download whole file from website. I find out that downloading a file is an automatic process and it doesn't wait for user decision cancel/save. So for example user writes url to download file and wait 1 minute. The file automatically starts downloading (I am using firefox) probably to the memory of the browser and when file is download then it continues processing code where I have logger "file successfully download" but there is still pop up window with decision cancel/save. So my question how I can wait for this decision and react on this.
Let's presume that you have an object that performs a download. You can make it implement Runnable and then make it run as a separate thread.
You can have a method called setDestination(String), and a method called cancel().
Cancel would be something like that:
public synchronized void cancel() {
this.cancelled = True;
}
And in the part where you actually perform the download you'd have a
if (this.cancelled) {
//remove downloaded data
return; //Exit from the download function
}
for the setDestination you would need to do something similar, store the download to a tempfile and at the end move it to the file indicated by destination.

How can I tell if a JEditorPane/TextPane document or page has finished loading?

I'm trying to load a URL into a JEditorPane or JTextPane but the URL is a dynamically generated PHP page. I then want to process the output from the PHP page in my Java application. The PHP page will always output at least one String that I can use to check that it's generated correctly.
If I try and process the page straight after setting the page using
JEditorPane.setPage(URL);
if( outputTracker.getText().contains("desktop_process") )
it returns a blank HTML page, even if I specify a text/plain content type for the JEditorPane:
System.out.println(outputTracker.getText() );
I assume this is because the PHP page hasn't finished loading as the method below will return the correct output every time.
At the moment I'm setting the page and then starting a Swing Timer and checking every 200ms if the page contains the correctly generated String:
private void getPageBtnActionPerformed(java.awt.event.ActionEvent evt) {
outputTracker.setPage("URL_GOES_HERE?variables=x&y=a");
check_response_timer.start();
}
ActionListener checkAction = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
if( outputTracker.getText().contains("desktop_process") ) {
System.out.println("Checking results...");
check_response_timer.stop();
process_response();
} else {
num_checks++;
System.out.println("Checking results...");
if( num_checks == 10 ) {
check_response_timer.stop();
checkLater = true;
responseLbl.setText("Connection timeout. Please click reconnect to check again.");
num_checks = 0;
}
}
}
};
private Timer check_response_timer = new Timer(200,checkAction);
This works fine.
At current server loads and the current complexity of the PHP pages being loaded the loop stops after the first iteration but it just seems a little inefficient and I don't want to have to keep checking if the page is going to take several seconds to load during heavy server loads or on more complex PHP pages.
I'm wondering if there's a better way to check that the page has finished loading.
I was wondering if I could use the JEditorPane.read(inputStream) method or set the page in a Swing Background Worker thread and then process the output of the PHP page when the worker's done() is called.
And is there a better way of loading the PHP output, reading it straight into a string from the dynamically generated output without the use of an editor pane as the editorpane isn't visible anyway?
Hope this is clear enough.
Thanks.
You can add a PropertyChangeListener to the editor pane:
editorPane.addPropertyChangeListener("page", ...);
However, this will only tell you when the main page is loaded. It won't tell you when images or other related files have finised loading.

Categories

Resources