Bluebird promisifyAll doesn't work in a vanilla case - javascript

I'm trying to promisify a Pusher.js function and I am a bit confused why the last technique works and the first two don't, since the first two seem to be following the documentation example.
The errors I get are: triggerAsync not defined.
Sample
var Pusher = require('pusher');
var pusher = new Pusher(params);
Promise.promisifyAll(Pusher); //this doesn't work for some reason
var triggerAsync = Promise.promisify(pusher.trigger); //this also doesn't work
Promise.promisifyAll(Object.getPrototypeOf(pusher)); //this works

...since the first two seem to be following the documentation example.
So is the last! If we take a look at the documentation for Promise#promisifyAll over at bluebirdjs.com (at the bottom of the document) you will find this, which gives a short explanation for why you need to employ this behaviour:
In all of the above cases the library made its classes available in one way or another. If this is not the case, you can still promisify by creating a throwaway instance:
var ParanoidLib = require("...");
var throwAwayInstance = ParanoidLib.createInstance();
Promise.promisifyAll(Object.getPrototypeOf(throwAwayInstance));
// Like before, from this point on, all new instances + even the throwAwayInstance suddenly support promises
So although it doesn't give us a definitive answer for why we need to do this with Pusher, we can at least be sure that it is because it doesn't "[make] its classes available in one way or another". You can also rest assured that you aren't necessarily doing it wrong (you shouldn't use this method unless you have to).

Related

Use constants or no for expectations in tests?

For example, we have some big page that we testing, and for test we have big mock.
And one of our expectations - check value of product price.
It can be done like:
expect(price).toBe(20);
Or, we can use value directly from mock:
expect(price).toBe(orderMock.data.user.order.price);
Or define additional variable like:
const expectedPrice = orderMock.data.user.order.price;
expect(price).toBe(expectedPrice);
Which way will be preferrable?
I believe both ways are ok in your scenario, however I would declare const mostly when I have multiple attributes, in order to avoid repeat orderMock.data.user.order too many.
Sometimes you can use object destructuring as well, when you have more attributes:
const { price:expectedPrice, otherAttribute } = orderMock.data.user.order;
expect(price).toBe(expectedPrice);
expect(otherValue).toBe(otherAttribute);
Just keep in mind if you do something similar with methods you may lose your bind.
I appreciate second way a lot more, cause its re-useable and it's says about it self - variable names are like descriptions
PS: In my opinion you should use var instead of const cause many older browsers dont fully support const https://caniuse.com/?search=const
If im right const is full supported since ECMA 6

Rx.js fromEvent + flatMapLatest broken?

Well, the problem itself is kind of hard to describe briefly, so here's a live example to demonstrate. It seems like I'm misunderstanding something about how Rx.js works, otherwise the functionality here comes from a bug.
What I tried to do was a simple reactive rendering setup, where what you see on the screen, and what events happen are both described in terms of Observables. The problem is that, for some indiscernible reason, the events are dropped entirely when the code is written one way, yet work fine with code that should theoretically be equivalent.
So, let's start with the first case in the example code above:
var dom = makeBox('one');
var clicks = Rx.Observable.fromEvent(dom, 'click');
If you create a DOM fragment, then you can simply use fromEvent to get an Observable for whatever event it emits. So far, so good. You can click this box and see a bunch of lines written to the log.
Now, the next step would be to make the DOM reactive, to express how it changes over time.
var domStream = Rx.Observable.return(makeBox('two'));
var clicks = domStream.flatMapLatest(function(dom) {
return Rx.Observable.fromEvent(dom, 'click');
});
That would make it an Observable, using return here to produce the simplest, constant case. The events you're interested in would be the ones emitted by the latest version of the dom, and that's exactly what the flatMapLatest operator does. This variant still works.
Ultimately, the goal would be to generate the current DOM state based on some application state. That is, map it from one Observable to another. Let's go with the simplest version for now, have a single constant value as the state, and then map it to the same fixed output we used previously:
var updates = Rx.Observable.return(1);
var domStream = updates.map(function (update) {
return makeBox('three');
});
var clicks = domStream.flatMapLatest(function(dom) {
return Rx.Observable.fromEvent(dom, 'click');
});
This should not be any different from the previous version. However, this outputs no events, no matter what you do.
What exactly is going on here? Did I misunderstand some fundamental concept of Rx, or what? I've run into some issues with hot vs cold Observables, but that seems unrelated in this minimal case. So, I'm kind of out of ideas. Can anyone enlighten me?
Sorry to tell you but it is a Hot vs Cold issue.
It is a subtle issue, but the difference between
Rx.Observable.return(makeBox('two'))
and
Rx.Observable.return(1).map(function() {return makeBox('three'); })
Is that the first returns a constant every time you subscribe to it, that is,
a box that you created initially. The second returns a new box every time the Observable is subscribed to, this causes a problem since you actually subscribe to the domStream variable twice, you are creating two instances of Box three, one which has event handlers but isn't shown and one that does not and is shown.
The fix is that you either need to use approach 2 or you need to convert the third into a hot stream either by using:
domStream.replay(1).refCount()
Or by using
domStream.publish()
then after all subscriptions are completed:
domStream.connect()

How to develop a custom protractor locator?

I have an angular-application where I put custom html-attributes ("data-testid='saveButton'") for identification on e.g. buttons, inputs etc.
Protractor has no built-in locator for this: the xpath-way does not work as this will always search from the document root (to overcome this limitation I would have to do quite a lot of string-magic to build the xpath-string, so I discarded this variant).
So I wanted to write my own locator, and consulted the official Protractor Documentation.
The documentation leaves me with an important question:
What methods are available on the parent-element-object? In their example they use using.querySelectorAll('button'); but how do they know they can use this?
I searched for 'querySelectorAll' in the protractor-documentation to see if it is maybe a method of ElementFinder or WebElement, but I didn't find it.
Also I found no way to debug the locator (only stop the protractor-test by browser.pause()), so I can't look at runtime to see what I can do with the given parent-element.
So does anybody know how I can get information about what methods the parent-element has?
The parent-element, which is essentially the context of the selector is a DOM element that gets handled by the browser - it can use whatever DOM function there is, in this case Element.querySelectorAll. As the addLocator's example says about the function you pass to it:
This function will be serialized as a string and will execute in the browser.
Also, keep in mind that there is a way to provide context to the xpath selectors thus avoiding the search from root:
var context = element(by.css('.some-parent-element-class'));
var divDirectDescendants = context.element(by.xpath('div'));
var divAllDescendants = context.element(by.xpath('.//div'));
With CSS these would be:
var divDirectDescendants = element(by.css('.some-parent-element-class > div'));
var divAllDescendants = element(by.css('.some-parent-element-class div'));
Also, there's a way to achieve what you want with a CSS selector (which is what querySelectorAll is, after all):
var everyElementWithMyAttr = element.all(by.css('[data-testid="saveButton"]'));

Strange javascript behaviour - error unless 'classes' are defined in correct order

I have a very strange problem with javascript and easel js.
I am using the easel.js library and am already fairly far into the construction of a project using it.
I am attempting to have a 'class' (I know they aren't technically classes in javascript but I will use this terminology for lack of a better word) inherit the Shape class from easel js, and then have another class inherit that. So it would be something like this:
easeljs.Shape --> MenuButton --> BuildingButton
The code I am using looks like this:
BuildingButton.prototype = Object.create(MenuButton.prototype);
BuildingButton.prototype.constructor = BuildingButton;
function BuildingButton(){
MenuButton.call(this);
}
MenuButton.prototype = Object.create(createjs.Shape.prototype);
MenuButton.prototype.constructor = MenuButton;
function MenuButton(){
createjs.Shape.call(this);
}
The problem is that I get the following error with this code:
Uncaught TypeError: undefined is not a function
easeljs-0.7.1.combined.js:8439
(line 8439 is pointing to the initialize() function in the Shape() constructor).
now here's the strange thing. If I change the order of the definitions so that the sub class is defined second and not first, it works fine!
MenuButton.prototype = Object.create(createjs.Shape.prototype);
MenuButton.prototype.constructor = MenuButton;
function MenuButton(){
createjs.Shape.call(this);
}
BuildingButton.prototype = Object.create(MenuButton.prototype);
BuildingButton.prototype.constructor = BuildingButton;
function BuildingButton(){
MenuButton.call(this);
}
This is very confusing as I can't seem to figure out why on earth this is happening. I could just make sure I define them in the correct order and leave it be, but I have all my 'classes' in different source files which are then strung together by grunt, which does so alphabetically.
Also, I feel like I may have a big gap in my knowledge of javascript (or maybe easel.js I'm not sure what exactly is causing this behaviour).
Thanks in advance for your help and I hope the question makes sense!
MenuButton.prototype = Object.create(createjs.Shape.prototype);
…
BuildingButton.prototype = Object.create(MenuButton.prototype);
These two statements have a clear dependency and need to be executed in the correct order (for the function declarations the order is irrelevant if placed in the same scope/file, but if in different files they need to be loaded in the correct order obviously).
I have all my 'classes' in different source files which are then strung together by grunt, which does so alphabetically
That's not a good idea. You should use some build tool/script that allows the declaration of dependencies.
Read this to clear things out: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Inheritance_and_the_prototype_chain
In first example you try to inherit from nothing, since MenuButton.prototype is not yet defined. To make it work just add MenuButton.prototype = new createjs.Shape.prototype(instead of Object.create() wich shouldn't be used anymore) to instantiate it first before you can you use it. Your first code is like you are willing to eat a banana before having one.

Dojo marginBox return different value

Anyone can guide me what's the difference between
this.marginBox
and
dojo.marginBox(this.node)
I'm confusing with this two where they return different value.
What are the two values you're getting back? (I haven't used dojo for a while, but I seem to remember one of them including padding and the other not?)
Dojo only provides a dojo.marginBox() method — I am not aware of Dojo providing any kind of prototype or mixin that enables a this.marginBox method. In other words, only dojo.marginBox(this.node) is correct.
It would have helped if you provided examples of what those methods are returning for you.
I would expect:
var example = this.marginBox;
to return undefined in most circumstances. However if you have tried to assign to this.marginBox like this:
// Don't do this - marginBox is not a DOM property!
this.marginBox = 10;
then future calls to this.marginBox would return 10... it might look like it is doing something, but it's got nothing to do with Dojo or CSS and will just return what you put in... not very useful!
I would be very careful in using dojo.marginBox, I was browsing around an issue about it and I found the following:
https://bugs.dojotoolkit.org/ticket/12492
unfortunately the dojo team won't fix the problem because the method dojo.marginBox(..) will not work for hidden nodes, quoting the ticket "the behavior is undefined when called on hidden nodes".
What I did I checked the node's clientWidth / Height.

Categories

Resources