Rx.js observable subscribe - button click not caught - rxjs

I'm trying a very basic example with Rx.js observable-subscribe. Here is my code:
HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"></meter>
<title></title>
</head>
<body>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.4.0/Rx.js"></script>
<script src="https://code.jquery.com/jquery-3.4.0.min.js" integrity="sha256-BJeo0qm959uMBGb65z40ejJYGSgR7REI4+CW1fNKwOg=" crossorigin="anonymous"></script>
<script src="index.js"></script>
<button id='testButton'>Click</button>
</body>
</html>
JS
var button = $('#testButton');
var btn$ = Rx.Observable.fromEvent(button, 'click');
btn$.subscribe(function(e){
console.log(e);
});
But there is nothing in the console when I click the button. Did I miss something?

fromEvent requires the first argument to be DOM element. $ probably refers to jQuery which returns a jQuery object.
So you should pull the native element from button before passing it to fromEvent:
var button = $('#testButton');
var btn$ = Rx.Observable.fromEvent(button[0], 'click'); // or .get(0) instead of [0]
Live demo: https://stackblitz.com/edit/rxjs-lpvsng?file=index.ts

I wrapped my JS code to jquery '$( document ).ready()' handler and it started working:
$( document ).ready(function() {
var button = $('#testButton');
var btn$ = Rx.Observable.fromEvent(button, 'click');
btn$.subscribe(function(e){
console.log(e);
});
});

Related

Jasmine Test Cases for click and toggle events

Struggling on writing the testcases on click,toggle,slideUp,fade events.
How do I write jasmine test cases to check if div is clicked or not and the slideUp and down and toggle events. Is there a provision in jasmine to test them.
Have listed my code having click test case for reference.
SpecRunner.html file
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Jasmine Spec Runner v2.3.4</title>
<link rel="shortcut icon" type="image/png" href="lib_jasmine/jasmine- 2.3.4/jasmine_favicon.png">
<link rel="stylesheet" href="lib_jasmine/jasmine-2.3.4/jasmine.css">
<script src="scripts/jquery.js"></script>
<script src="lib_jasmine/jasmine-2.3.4/jasmine.js"></script>
<script src="lib_jasmine/jasmine-2.3.4/jasmine-html.js"></script>
<script src="lib_jasmine/jasmine-2.3.4/boot.js"></script>
<script src="lib_jasmine/jasmine-2.3.4/jasmine-jquery.js"></script>
<!-- include source files here... -->
<script type="text/javascript" src="js/eigMain.js"></script>
<script type="text/javascript" src="js/sinon.js"></script>
<!-- include spec files here... -->
<script type="text/javascript" src="js/specEig.js"></script>
</head>
<body>
</body>
</html>
js file for reference
$('#screenPane').click(function(e){
$('#Panel,.FixedHeader').toggleClass('fullscreen');
$('#eIcon').toggle();
$('#cIcon').toggle();
$(".Col").toggle();
$('html, body').animate({scrollTop: $('#total-results').offset().top}, 800);
$('#nav_up').fadeIn('slow');
$('#nav_down').hide();
});
Spec.js file having click event test case on it. It gives me ERROR : Expected event [object Object] to have been triggered on [object Object]. Also, toggle test case fails to execute.
it ("should invoke the screenPane click event.", function() {
spyOnEvent($('#screenPane'), 'click');
$('#screenPane').click();
expect('click').toHaveBeenTriggeredOn($('#screenPane'));
});
Please help
While most tags accept or react to a click event, detecting it may prove difficult on the various platforms and browsers. You would probably be better checking to see if the CSS classes that toggle() deals with have been swapped in response to the click. For checking anything that is going to get moved around, simply check the starting X/Y coordinates and then compare them to the ones when the animation is finished and just check to see if they are different (so as to not create a brittle situation with strictly defined values.)
//Checking coordinates
it ("should invoke the screenPane click event.", function() {
var coords = $('screenPane').offset();
$('#screenPane').click();
var newCoords = $('screenPane').offset();
expect(newCoords).not.toEqual(coords);
});
//Checking classes
it ("should invoke the screenPane click event.", function() {
var classes = $('screenPane').val('class');
$('#screenPane').click();
var newClasses = $('screenPane').val('class');
expect(classes).not.toEqual(newClasses);
});

Responsive Picture Element still working even after being removed from DOM in Chrome Browser

Can anyone explain why the responsive picture image is still firing using Chrome Canary 42.0.2302.2 after it has been removed (works as expected in IE11 and FF 35.0.1 - in Chrome 40.0.2214.111 m it is broken, but interestingly, it also downloaded both images straight away!).
To test, open the test page with Chrome Dev Tools open on the Network tab. Take note of the image that has been displayed. Tap anywhere on the page to empty the content. Now resize the page and note that the other images are downloaded despite the picture element being removed from the page.
<!DOCTYPE html>
<html>
<head>
<title>Test Picture Element</title>
<meta charset="utf-8">
</head>
<body>
<picture>
<source srcset="http://placehold.it/768/f00/fff" media="(max-width: 768px)">
<source srcset="http://placehold.it/992/0f0/fff" media="(max-width: 992px)">
<img srcset="http://placehold.it/1200/00f/fff">
</picture>
</body>
<script src="https://code.jquery.com/jquery-2.1.3.min.js"></script>
<script type="text/javascript">
$(function(){
$('body').on('click', function() {
$('body').empty();
});
});
</script>
</html>
JSFiddle for your convenience: http://jsfiddle.net/5qwLus59/4/
Because Mutations aren't set up correctly in Chrome. It's similar to how people sometimes write their JS code.
For example:
$('.nav').each(function(){
var $nav = $(this);
var sizeNav = function(){
//some code
};
$(window).on('resize', sizeNav);
});
In fact they should do something like this:
$('.nav').each(function(){
var $nav = $(this);
var sizeNav = function(){
//some code
};
$(window).on('resize', sizeNav);
$nav.on('remove', function(){
//destroy code
$(window).off('resize', sizeNav);
});
});
This is a serious issue, please report this!:
https://code.google.com/p/chromium/issues

How to inject dependencies in jasmine test for an angular item

Here is the test spec file:
describe('Test main controller', function(){
it('Should initialize value to Loading', function(){
$scope = {}
ctrl = new mainNavController($scope)
expect($scope.wksp_name).toBe('Loading')
})
})
Here is the controller file
function mainNavController($scope) {
$scope.wksp_name = 'Loading...'
$scope.$on('broadCastWkspNameEvent', function (e, args) {
$scope.wksp_name = args
})
}
mainNavController.$inject=['$scope']
But my test fails saying Object #<Object> has no method '$on'
I am using the basic setup of jasmine.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>Jasmine Spec Runner</title>
<link rel="shortcut icon" type="image/png" href="testlib/jasmine-1.2.0/jasmine_favicon.png">
<link rel="stylesheet" type="text/css" href="testlib/jasmine-1.2.0/jasmine.css">
<script type="text/javascript" src="testlib/jasmine-1.2.0/jasmine.js"></script>
<script type="text/javascript" src="testlib/jasmine-1.2.0/jasmine-html.js"></script>
<!-- include source files here... -->
<script type="text/javascript" src="/static_files/js/test-specs/main-nav-spec.js"></script>
<!-- include spec files here... -->
<script type="text/javascript" src="/static_files/js/common/jquery/latest.js"></script>
<script type="text/javascript" src="/static_files/js/common/angular/angular-1.0.1.min.js"></script>
<script type="text/javascript" src="/static_files/js/common/angular/angular-resource-1.0.1.min.js"></script>
<script type="text/javascript" src="/static_files/js/section/main-nav-controller.js"></script>
<script type="text/javascript">
(function() {
var jasmineEnv = jasmine.getEnv();
jasmineEnv.updateInterval = 1000;
var htmlReporter = new jasmine.HtmlReporter();
jasmineEnv.addReporter(htmlReporter);
jasmineEnv.specFilter = function(spec) {
return htmlReporter.specFilter(spec);
};
var currentWindowOnload = window.onload;
window.onload = function() {
if (currentWindowOnload) {
currentWindowOnload();
}
execJasmine();
};
function execJasmine() {
jasmineEnv.execute();
}
})();
</script>
</head>
<body>
</body>
</html>
What is it that I am doing wrong? I am not able to understand how this thing is supposed to work :)
The main problem with your test code is that it tries to create a controller's instance "by hand" using the new operator. When doing so AngularJS has no chance to inject dependencies. What you should be doing is to allow AngularJS inject dependencies:
var $scope, ctrl;
//you need to inject dependencies first
beforeEach(inject(function($rootScope) {
$scope = $rootScope.$new();
}));
it('Should initialize value to Loading', inject(function($controller) {
ctrl = $controller('MainNavController', {
$scope: $scope
});
expect($scope.wksp_name).toBe('Loading...');
}));
Here is the link to a complete jsFiddle: http://jsfiddle.net/pkozlowski_opensource/7a7KR/3/
There are 2 things worth noting in the above example:
You can use the inject() method from the ngMock module to inject dependencies: https://docs.angularjs.org/api/ngMock/function/angular.mock.inject
To create a controller instance (that supports dependency injection) you would use the $controller service: http://docs.angularjs.org/api/ng.$controller
As the last remark: I would advise naming controllers starting with an uppercase letter - this way we won't confuse them with variable names.
Great answer by #pkozlowski.opensource. To elaborate a bit more... Sometimes it could be also handy to assert that $scope.$on was really called by your controller. In this case you can spy on $scope.$on as pointed out below:
beforeEach(inject(function($rootScope) {
$scope = $rootScope.$new();
spyOn($scope, '$on').andCallThrough();
}));
And then you can assert that $on was called with your event name and some function as arguments:
it('Should bind to "broadCastWkspNameEvent"', inject(function($controller) {
ctrl = $controller('MainNavController', {
$scope: $scope
});
expect($scope.$on).toHaveBeenCalledWith('broadCastWkspNameEvent', jasmine.any(Function));
}));
I agree with pkozowski's response, but to answer your question more directly, you need to stub out '$on'
Your example would pass if your $scope looked like:
$scope = {
$on: function() {}
}

How to embed Firebug Lite in my QWebView widget?

I've started to embed some QWebView widgets to my desktop application (PyQt).
I use JQuery and CSS to enhance appearance and usability.
It would be comfortable to debug my html code with a web inspector.
How can I embed Firebug Lite in my QWebView widgets?
E.g. I tried the following code and it doesn't work:
html1 = """
<html debug="true">
<head>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.6.1.js"></script>
<script type="text/javascript" src="https://getfirebug.com/firebug-lite.js#startOpened=true"></script>
<script type="text/javascript">
$(document).ready(function() {
$("body").css("background", "#f00");
console.log("in here");
});
</script>
</head>
<body><h1>Hello!</h1></body>
</html>
"""
html2 = """
<html debug="true">
<head>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.6.1.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$("body").css("background", "#f00");
var firebugLite = document.createElement("script");
firebugLite.src = "https://getfirebug.com/firebug-lite.js";
firebugLite.id = "firebug_lite";
firebugLite.textContent = "{ startOpened: true }";
document.getElementsByTagName("head")[0].appendChild(firebugLite);
console.log("in here");
});
</script>
</head>
<body><h1>Hello!</h1></body>
</html>
"""
if __name__ == '__main__':
app = QApplication(sys.argv)
view = QWebView()
frame = view.page().mainFrame()
frame.setHtml(html2)
view.show()
app.exec_()
html1 and html2 have the same effect: body turns into red but Firebug doesn't show up.
P.S. my actual html code can't be debug with an external client browser,
because it uses QT resources and application window objects.
I've added this JavaScript to my WebKit-based projects, maybe this helps for QWebView as well?
var firebugLite = document.createElement("script");
firebugLite.src = "https://getfirebug.com/firebug-lite.js";
firebugLite.id = "firebug_lite";
firebugLite.textContent = "{ startOpened: true }";
document.getElementsByTagName("head")[0].appendChild(firebugLite);

Trouble with jQuery Ajax timing

I have a very simple javascript class that does an ajax call to a web service of mine via jquery. It returns the data successfully, but I am unable to retrieve it via a variable I set the data to. I don't think it is a matter of the ajax call being asynchronous or not because I have set up event handlers for all the ajax events, but some of them do not fire. I have no idea what is wrong. Here is the complete code:
Javascript:
function testClass(){
this.returnData = "";
this.FireAjax = function(){
$.getJSON("http://localhost/mywebapp/webservices/service.asmx/Initialize?userID=12&jsoncallback=?",
function(data){
this.returnData = data.d;
alert(data.d);
}
);
}
}
HTML page:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
<script type="text/javascript" src="http://localhost/mywebapp/js/jquery-1.3.2.min.js"></script>
<script type="text/javascript" src="testClass.js"></script>
<script type="text/javascript">
$(document).ready(function(){
var obj = new testClass();
$("#debug").ajaxError(function(event, request, settings){
$(this).append("<b>Ajax Error!</b><br />"); //this does not fire
});
$("#debug").ajaxSend(function(evt, request, settings){
$(this).append("<b>Ajax Send!</b><br />"); //this does not fire!?
});
$("#debug").ajaxStop(function(){
$(this).append("<b>Ajax Stopped</b><br />"); //this fires
});
$("#debug").ajaxComplete(function(event,request, settings){
$(this).append("<b>Ajax Completed!</b><br />"); //this fires
$(this).append("<h2>" + obj.returnData + "</h2>"); //this returns an empty string!!!!!!
});
$("#debug").ajaxSuccess(function(evt, request, settings){
$(this).append("<b>Ajax Successful!</b><br />"); //this fires
});
$("#debug").ajaxStart(function(){
$(this).append("<b>Ajax Started!</b><br />"); //this fires
});
obj.FireAjax();
});
</script>
</head>
<body>
<div id="debug">
</div>
</body>
</html>
Additional Info:
If I remove the complete event in my html page and place the call to obj.returnData in my stop event (thinking that perhaps my html complete event overwrites my testClass complete function), i get the same results.
Your problem is here:
this.returnData = data.d;
this inside the anonymous function refers to the jQuery Options object, not the instance of your object.
Try this:
function testClass(){
this.returnData = "";
var that = this;
this.FireAjax = function(){
$.getJSON("http://localhost/mywebapp/webservices/service.asmx/Initialize?userID=12&jsoncallback=?",
function(data){
that.returnData = data.d;
alert(data.d);
}
);
}
}

Resources