Adding a method to Bluebird promise - promise

I have promisified Mongoose. I have some methods that extent Mongoose Query that now would need to be added to Bluebird. I don't mind extending Mongoose but do not want to take the same approach for this more gobal library. Looking through the docs I see some potentials but I am not sure.
I would like to come as close/clean as the following:
Model.findAsync().toCustom();
toCustom is basically a form of toJSON which 1) execs the query and 2) custom outputs the results/create custom errors etc... pretty straighforward.
What is the cleanest way to achieve something like the above? I would like to avoid doing this each time:
Model.findAsync().then(function(docs) {
return toCustom(docs);
}, function(err) {
return toCustom(err);
});
You get the idea...

Bluebird actually supports your use case directly. If you need to publish a library that extends bluebird in your own custom way you can get a fresh copy of bluebird by doing:
var Promise = require("bluebird/js/main/promise")();
Promise.promisifyAll(require("mongoose")); // promisify with a local copy
Promise.prototype.toCustom = function(){
return this.then(toCustom, toCustom); // assuming this isn't just `.finally`
};
You might also want to export it somehow. This feature is designed for library authors and for getting an isolated copy of bluebird. See the for library authors section in the wiki.

Related

Using `createMockClient` for testing non react code?

I have mixed application that uses Apollo for both React and non-react code.
However, I can’t find documentation or code examples around testing non-react code with the apollo client,not using MockedProvider. I did, however, notice that apollo exports a mock client from the testing directory.
import { createMockClient } from '#apollo/client/testing';
I haven’t found any documentation about this API and am wondering if it’s intended to be used publicly and, if not, what the supported approach is for this.
The reason I need this is simple: When using Next.js’ SSR and/or SSG features data fetching and actual data rendering are split into separate functions.
So the fetching code is not using React, but Node.js to fetch data.
Therefore I use apolloClient.query to fetch the data I need.
When trying to wrap a react component around that fetching code in a test an wrap MockedProvider around that the apolloClient’s query method always returns undefined for mocked queries - so it seems this only works for the useQuery hook?
Do you have any idea how to mock the client in non-react code?
Thank you for your support in advance. If you need any further information from me feel free to ask.
Regards,
Horstcredible
I was in a similar position where I wanted to use a MockedProvider and mock the client class, rather than use useQuery as documented here: https://www.apollographql.com/docs/react/development-testing/testing/
Though it doesn't seem to be documented, createMockClient from '#apollo/client/testing' can be passed the same mocks as MockedProvider to mock without useQuery. These examples assume you have a MockedProvider:
export const mockGetAssetById = async (id: Number): Promise<any> => {
const client = createMockClient(mocks, GetAsset)
const data = await client.query({
query: GetAsset,
variables: id,
})
return data
}
Accomplishes the same as:
const { data } = useQuery(
GetAsset,
{ variables: { id } }
)

Cypress command vs JS function

The Cypress documentation suggests that commands are the right way to reuse fragments of code, e.g.
Cypress.Commands.add("logout", () => {
cy.get("[data-cy=profile-picture]").click();
cy.contains("Logout").click();
});
cy.logout();
For simple cases like this, why would I use a command over a plain JS function (and all the nice IDE assistance that comes with it). What are the drawbacks of rewriting the above snippet as
export function logout(){
cy.get("[data-cy=profile-picture]").click();
cy.contains("Logout").click();
}
// and now somewhere in a test
logout();
Based on my experience with Cypress (one year project and several hundred test cases), I can say that a plan JS function is great for grouping cy commands.
From my point of view, a custom cy command may be really useful only if it is incorporated into the chain processing (utilizes the subject parameter or returns a Chainable to be used further in the chain). Otherwise, a plain JS function is preferable due to it simplicity and full IDE support (unless you're using an additional plugin).
If you for any reason need to do something inside the cypress loop, you can always wrap you code by cy.then() in a plain JS function:
function myFunction() {
cy.then(() => {
console.log(("I'm inside the Cypress event loop"))
})
}
Commands are for behavior that is needed across all tests. For example, cy.setup or cy.login. Otherwise, use functions.
See official docs: https://docs.cypress.io/api/cypress-api/custom-commands#1-Don-t-make-everything-a-custom-command

How can you mix Parse.Promise with other forms of Promise, e.g. Bluebird / ES6 native Promises?

I want to run some of my Parse Cloud Code on Heroku (Node) to kick start the migration process out of Parse's hosted Cloud Code.
One of the differences between the two environments is the fact that Parse SDK you use is different too. On node, I found that if you do a
var Parse require('parse/node').Parse;
... then Parse.Cloud.httpRequest is actually missing.
I was looking for Node alternatives for performing http requests and found request. But... it doesn't really fit in well with Parse Promises:
parsePromise1()
.then(parsePromise2) // okay
.then(requestPromise) // CUSTOM HTTP REQUEST!
.done(parsePromise3) // this Parse promise always succeeds, and occurs even before the request is fully completed.
I was wondering if anybody had found better ways of converting out of Parse Promises? Thanks.
You can use the request-promise package that wraps request with promises support or a library like bluebird that exposes a method that converts callback APIs to promises.
I recommend that you migrate from Parse promises which are suboptimal to ES2015 native promises (or, more powerful alternatives like bluebird). With those you could:
Promise.resolve(someParsePromise).then(() => // convert
return someParsePromiseFn()// return some Parse promise, that works
}).then(res => {
// more async work ...
});
And avoid .done altogether.
Its not ideal at all, but you can use this kind of wrapper from native Bluebird to native promises:
const Promise = require('bluebird')
function handle () {
return new Promise((resolve, reject) => {
handleWithNativePromise(...arguments)
.then(resolve)
.catch(reject)
})
}

Is it possible to write these Protractor expectations using no continuations?

Using protractor and jasmine(wd) we want to check that a table on the web page contains expected values. We get fetch the table from the page using a CSS selector:
var table = element(by.css('table#forderungenTable')).all(by.tagName('tr'));
We then set our expectations:
table.then(function(forderungen){
...
forderungen[2].all(by.tagName('td')).then(function(columns){
expect(columns[1].getText()).toEqual('1');
expect(columns[5].getText()).toEqual('CHF 277.00');
});
});
Is it possible to change this code so that we don't have to pass functions to then, in the same way that using jasminewd means that we don't have to do this? See this page, which states:
Protractor uses jasminewd, which wraps around jasmine's expect so that you can write:
expect(el.getText()).toBe('Hello, World!')
Instead of:
el.getText().then(function(text) {
expect(text).toBe('Hello, World!');
});
I know that I could write my own functions in a way similar to which jasminewd does it, but I want know if there is a better way to construct such expectations using constructs already available in protractor or jasminewd.
You can actually call getText() on an ElementArrayFinder:
var texts = element(by.css('table#forderungenTable')).all(by.tagName('tr')).get(2).all(by.tagName('td'));
expect(texts).toEqual(["text1", "text2", "text3"]);

How can I pass a local variable from function to event listener function in JavaScript?

Good day!
I began writing my own basic JavaScript library for personal use and distribution a few days ago, but I am having trouble with one of the methods, specifically bind().
Within the method itself, this refers to the library, the object.
I went to Google and found function.call(), but it didn't work out the way I planned it--it just executed the function.
If you take a look at another method, each(), you'll see that it uses call() to pass values.
I also tried the following:
f.arguments[0]=this;
My console throws an error, saying it cannot read '0' of "undefined".
I would like to be able to pass this (referencing the library--NOT THE WINDOW) to use it in the event listener.
You can see it starting at line 195 of the JavaScript of this JSFiddle.
Here it is as well:
bind:function(e,f){
if(e.indexOf("on")==0){
e=e.replace("on","");
}
if(typeof f==='function'){
/*Right now, 'this' refers to the library
How can I pass the library to the upcoming eventListener?
*/
//f=f(this); doesn't work
//f.call(this); //doesn't work
//this.target refers to the HTMLElement Object itself, which we are adding the eventListener to
//the outcome I'm looking for is something like this:
/*$('h3').which(0).bind(function({
this.css("color:red");
});*/
//(which() defines which H3 element we're dealing with
//bind is to add an event listener
this.target.addEventListener(e,f,false)
}
return this;
},
Thank you so much for your help, contributors!
If, as per your comments, you don't want to use .bind(), rather than directly passing f to addEventListener() you could pass another function that in turn calls f with .call() or .apply():
if(typeof f==='function'){
var _this = this;
this.target.addEventListener(e,function(event){
f.call(_this, event);
},false)
}
Doing it this way also lets your library do any extra event admin, e.g., pre-processing on the event object to normalise properties that are different for different browsers.
So in this particular case you actually want to call JavaScript's built in bind method that all functions have.
f = f.bind(this);
f will be a new function with it's this argument set to whatever you passed into it.
Replace f=f(this); with f.apply(this);
Look at underscore code, here:
https://github.com/jashkenas/underscore/blob/master/underscore.js#L596

Resources