-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
selenium support #650
Comments
@KhodeN This directive did work in Selenium if you revert to 3.1 I actually had a ton of Protractor tests that use this directive. On Friday, they suddenly started failing. After spending dozens of man hours, our team finally found this in Intellij's local history: Someone must have added an unrelated bower dependency to our project, which changed the logic on which version of this directive got checked out. It appears that somewhere between 3.1 & 3.2, Selenium support was broken. In the end I fix it by changing from:
to this:
I guess on Friday "something" happened which caused Bower to decide to give us 3.2 instead of 3.1 as it was doing. (If anyone has suggestions to "lock" bower's versions like you do with Composer, please PM me!) I also typed up a stack overflow post that I never actually submitted, while I was debugging. I still have the tab open & I'll paste it here in case it helps anyone debug: We had a Protractor test that uses
Today we noticed that this test began failing. We have reverted our code & all dependencies (composer, bower, npm) back to where we knew it was working. The tests still fail. This lead us to believe the issue was a regression in Chrome, webdriver, selenium or Protractor itself. One by one we reverted each of these & the tests still fail. In order to debug, I've setup a page called Here is what I see when I select a file manually: Here is what I see when Protractor selects the file (used to work): As you can see, it appears the value of the input was set. I can also bind to it via jquery & confirm the
I'm then observing the console errors in my test like this:
I see this output to my terminal when running the tests, which seems to indicate the ##test-spec.js##: var path = require('path');
describe('test', function() {
// wait for angular
beforeEach(function() {
browser.ignoreSynchronization = false;
});
it('test', function() {
browser.get('/test.html');
var fileToUpload = 'fixtures/slide1.png';
var absolutePath = path.resolve(__dirname, fileToUpload);
$('input[type="file"]').sendKeys(absolutePath);
browser.actions().sendKeys(protractor.Key.ENTER).perform();
expect(element(by.css('#myLog')).getText()).toEqual('changed');
browser.manage().logs().get('browser').then(function(browserLog) {
console.log('\n log: ' + require('util').inspect(browserLog));
});
browser.pause();
});
}); ##test.html##: <!DOCTYPE html>
<html lang="en">
<head>
<script src="https://code.jquery.com/jquery-1.11.2.js"></script>
<script src="/vendor/angular/angular.js"></script>
<script src="/vendor/ng-file-upload/angular-file-upload-all.js"></script>
</head>
<body ng-app="fileUpload" ng-controller="MyCtrl">
<pre>{{files|json}}</pre>
<input type="file" ng-file-select ng-model="files" name="file" accept="image/*" required>
<button ng-click="uploadPic(picFile)">Submit</button>
<div id="myLog"></div>
<script>
jQuery(document).on('ready', function() {
jQuery('input[type="file"]').on('change', function () {
console.error('yay!');
});
});
var app = angular.module('fileUpload', [ 'ngFileUpload' ]);
var version = '3.2.4';
app.controller('MyCtrl', [ '$scope', '$http', '$timeout', '$compile', '$upload', function($scope, $http, $timeout, $compile, $upload) {
$scope.changeAngularVersion = function() {
window.location.hash = $scope.angularVersion;
window.location.reload(true);
};
$scope.angularVersion = window.location.hash.length > 1 ? (window.location.hash.indexOf('/') === 1 ?
window.location.hash.substring(2): window.location.hash.substring(1)) : '1.2.20';
$scope.$watch('files', function(files) {
if(undefined !== files) {
$scope.upload(files);
}
});
$scope.upload = function (files) {
jQuery('#myLog').html('changed');
if (files && files.length) {
for (var i = 0; i < files.length; i++) {
var file = files[i];
$upload.upload({
url: 'upload/url',
fields: {'username': $scope.username},
file: file
}).progress(function (evt) {
var progressPercentage = parseInt(100.0 * evt.loaded / evt.total);
console.log('progress: ' + progressPercentage + '% ' + evt.config.file.name);
}).success(function (data, status, headers, config) {
console.log('file ' + config.file.name + 'uploaded. Response: ' + data);
});
}
}
};
} ]);
</script>
</body>
</html> You should be able to copy & paste this & run Protractor. If you give v3.1 of the directive, tests are green & pass. If you put v3.2 of the upload directive, you get no side effects from the "change" event & tests fail. |
I take my hat off to you) Big thx. |
3.1.2 has bug - do not work correctly with accept="{{ ctrl.accept }}" attribute (with dynamic value). Rollback to 3.0.7. |
From version 3.2.x a new file input element will be created and clicked on when you click on the file upload element. So the change event is firing on the newly created element. |
Yes, I read source. But this behavior is not compatible with Protractor or webdriver (selenium). How can I write e2e test for your control? |
I'd also imagine that breaks other things besides just Protractor. Probably older & mobile browsers, screen readers, maybe other libraries that expect events to work, etc... Could it be made to "forward" events from one element to the other, to fix the issue(s)? Also I'm not sure why a hidden element affects anything? Protractor will not interact with any hidden elements. Protractor is sending keys to the visible element, the same way a user would. It should be firing the same events on the same elements whether it is Protractor or a human user. I even used jquery to filter for all file inputs in the source & only found 1 element. So I doubt that this explains things @danialfarid are you sure its not something more complex? If that were the case I would have gotten an error from Protractor stating that it refuses to click a hidden element. I would have then changed my selectors to simply match the visible newly created element. But this was not the issue I experienced. I also use Protractor to tests lots of directives that transclude and/or replace, replacing DOM elements doesn't cause this issue from my experience. |
Do you get the same result for input type file element and div? |
When you click on the ng-file-select element, if it is file input, it would replace it with a new file input element and would click on the new element. If it is a div or button element it would insert a file input element before that element and click on it and then remove it once you select the file and change event is fired. |
Yes. But when user clicks on P.S. My English is terrible, I know this) |
In Selenium we're not to click on the file input. You "send keys" to the file input, which bypasses the file selection dialog altogether. Selenium is sending keys to the element that is visible that matched my selector. Even if the element is replaced, Selenium is interacting with the same replacement element that the real user is. So it would make sense to me that the issue is with "sending keys" to an input rather than clicking it. Its not likely that the issue is Selenium interacting with the wrong element. Its worth elaborating and explaining that Selenium is not using keyboard shortcuts to navigate to the file dialog either. From what I understand, its a special way Selenium modifies the state of the file input, bypassing certain events like click or key down. They actually say to blur (loose focus) to trigger the upload.... For example - I'm sending the "enter" key instead of doing a blur in my example, which works in the old version. I've reverted the verison of this dependency in my project to a working state & don't have time to debug much further on the newer version. |
Since version 3.3.0 the underlying input file element will not be removed after the change event. That might fix the selenium problem, could you verify? |
OK, today or tomorrow I'd check |
No
|
@danialfarid do I read you correctly at Apr 14, that you suggest we:
I have trouble implementing 2 and 4. -Pete |
Please follow this thread: #710 (comment) |
since version 5.0.0 you can set |
thx |
Since version 7 there won't be a new element created on each click so that would make the e2e testing easier. |
This thread went to a lot of discussions and I am finding it difficult to summarize! So can someone please help me understand what the problem was altogether? And also, how the solution was achieved? I am testing a similar AngularJS custom directive using Sahi web driver. The approach was very similar to that of Selenium where in Sahi proxy would 'inject' the file to be uploaded into the Http request against the file input element and can be submitted as usual. But the same is not working in my case only when I was testing an AngularJS file upload component. |
My workaround was to find the hidden file-upload input and inject javascript to unhide it before using Selenium Webdriver .type() function to enter the upload filename to the field. I am unsure about any other working solutions. |
Need ability to select file without open dialog (for selenium tests).
Usually, selenium send keys (file path) to
<input type="file">
, then submits form.How can I do this with
ng-file-upload
?input
elements not exists until click :-(.The text was updated successfully, but these errors were encountered: