I have below code which invokes a service to get some values, I knowingly shut down the backend part to check if error is being added. I noticed it makes the service call twice, can someone explain me why this is happening?
(async () => {
try {
this.countries = await this.testerSvc.getCountries().toPromise();
} catch (err) {
this.addError("Countries");
}
})();
Service code:
getCountries() {
return this.http.get<[]>(this.baseUrl + "countries");
}
On my app.module.ts I had added my component:
bootstrap: [AppComponent, MyComponent]
On my app.component.html, I had
<app-tester> </app-tester>
It was instantiating my component twice, I removed from the bootstrap and now it's instantiating only once. So service call is only once.
Related
I have an existing Express ApolloServer . I added subscription to that . I can see when I fire the subscription from Playground, the resolve method is called . But, the subscribe method is never called
const { PubSub, withFilter } = require ('apollo-server');
const pubsub = new PubSub();
const SOMETHING_CHANGED_TOPIC = 'something_changed';
const mySubscription = {
Subscription: {
somethingChanged: {
resolve: root => {
console.log('subscription server resolve', { root })
return root
},
subscribe: () => {
console.log('I AM HERE IN SUBSCRIPTION', pubsub.asyncIterator(SOMETHING_CHANGED_TOPIC))
return pubsub.asyncIterator(SOMETHING_CHANGED_TOPIC)
}
}
}
};
module.exports = { mySubscription}
I can see the console.log('subscription server resolve', { root }) getting printed although root is undefined. But the similar console.log('````') in subscribe is not executed .
You need to call pubsub.publish somewhere (usually in one of your resolvers) to trigger the subscription.
https://www.apollographql.com/docs/apollo-server/data/subscriptions/#subscriptions-example
I had a similar issue, there were a couple things I needed to achieve to accomplish this.
I had to remove my resolve() function to get it working. For some reason, having the resolve() function defined caused my subscription not to work.
I also had failed to follow the
https://www.apollographql.com/docs/react/data/subscriptions/#setting-up-the-transport. I was trying to request my subscription over the http link instead of over a ws link.
In general, a good test to see where the issue lies is to try to subscribe to your message using the GraphQL sandbox at http://localhost:4000/graphql (or wherever your sandbox is setup to run at when you start your server). If the sandbox subscribes successfully, the issue lies in your client code. If the sandbox fails to subscribe, the issue lies in your server code.
Please let me know if you are still having the issue and I will try to help.
I am not using redux-thunk. this keeps error-ing and I am not sure how to fix it. The examples I see online use redux-thunk which I am not using
my repo is here and the file I am trying to test is in tests\actions\...
My action that is being called in the test
import axios from "axios";
var CancelToken = axios.CancelToken;
let fetch_cancel;
export const FETCH_CATEGORIES = "fetch_categories";
export async function fetchCategories() {
fetch_cancel && fetch_cancel();
const request = await axios.get(
`https://d1i9eedhsgvpdh.cloudfront.net/production-plentific-static/api-cache/find-a-pro/api/v1/categories/all.json`,
{
cancelToken: new CancelToken(function executor(c) {
// An executor function receives a cancel function as a parameter
fetch_cancel = c;
})
}
);
return {
type: FETCH_CATEGORIES,
payload: request
};
}
The error message means that your actions must be plain objects. For example:
store.dispatch({
type: 'ADD_TODO',
text: 'Understand the middleware'
})
If you make an async request, you can't just return an object, because you need to wait for the request to finish. If you return too early, you return a Promise.
However, I cannot reproduce your error in your sandbox.
I am trying to cover redux-saga that gets data from RxDB with Jest tests.
export function* checkUnsavedData(action) {
const { tab } = action;
try {
const db = yield getDB().catch(e => {
throw new Error(e);
});
const currentUser = yield select(makeSelectCurrentUser());
const unsavedData = yield db[USER_COLLECTION].findOne(currentUser)
.exec()
.then(data => data && data.unsavedData)
.catch(e => {
throw new Error(e);
});
} catch (error) {
yield showError(error);
}
}
Everything is fine in live run. But testing the generator I get:
UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): Error: Error: RxError:
RxDatabase.create(): Adapter not added. Use RxDB.plugin(require('pouchdb-adapter-[adaptername]');
Given parameters: {
adapter:"idb"}
If anyone has done this, please, tell me how to test such cases with RxDB in redux-saga with Jest.
It looks like you did non add the adapter to RxDB. Can you paste the code where you create the database? This would help more in finding the error.
When running tests, you should not use the idb-adapter. Use the in-memory-adapter, it's faster and also you can be sure that you start on a clean state on each testrun.
Currently I am trying to write a test that will perform the following actions:
Load my Component
Wait for return from a service class (HTTP Call + Observable)
Check value returned.
Service class:
getMyInfo(): Observable<any[]> {
return this.httpClient.get(`${this.serviceurl}/all`) as Observable<any[]>;
}
Relevant component code:
ngOnInit() {
this.myService.getMyInfo().subscribe((data: any[]) => {
console.log('I was called')
this.myInfo = data;
})
}
In test class, using this method from Service will not work, the method is called, however the return is never applied in the class (Subscription).
Using a stub works, but this is not what I want, since I want to e2e.
const serviceStub = {
getMyInfo() {
return fakeAsyncResponse([{ id: 1,name: 'myname'}]);
}
};
it("should request names on component initiation.", inject([FrontendComponent, Service], async(component: FrontendComponent, service: Service) => {
let debugElement = fixture.debugElement;
let Service = debugElement.injector.get(Service);
let incrementSpy = spyOn(Service, 'getMyInfo').and.callThrough();
component.ngOnInit();
expect(incrementSpy).toHaveBeenCalled();
await fixture.whenStable();
fixture.detectChanges();
console.log(component.myInfo);
expect(component.myInfo.length).toEqual(1);
}));
To sum up, how can I handle real http calls and then process the expect assertion without stubbing the service classes?
I used app.authenticate on client.
It called the authentication hook in before create hook on server.
I imported from 'feathers-authentication-manage.hook' as verifyHooks.
Before create hook:
app.service('authentication').hooks({
before: {
create: [
authentication.hooks.authenticate(config.strategies),
async context => {
const { app, data } = context;
await app.service('users').find({
query: {
usernameUpperCase: data.username.toUpperCase(),
$limit: 1
}
})
.then(async (user) => {
await user.data.map(async data => {
if(!data.isVerified) {
await console.log('HELLO FROM ABOVE.');
//await v.validationError('Verify Email. A token link has been sent to your email.');
}
});
})
.catch(err => v.validationError(err));
},
verifyHooks.isVerified()
],
The 3 hooks in order were:
1. authentication
2. my hook
3. isVerified() email verify hook from feathers-authentication management
On client, the authenticate promise would be rejected when isVerified() hook activated even if was after the authentication hook.
If I removed the isVerified() hook, the authenticate promise would resolve.
How do I make my hook, the second hook, behave like isVerified() so the authenticate promise on client be rejected?
The first thing is that you are making your life harder by using async/await not as it is intended. The idea is to not having to write all those .then and .catch handlers.
The .catch handler is also probably where actual issue is. If a .catch (in your case v.validationError(err)) does not reject or throw an error, the promise will resolve successfully. Using async/await the right way and Promise.all to wait for the asynchronous validation steps and then re-throwing the validation error should do it:
app.service('authentication').hooks({
before: {
create: [
authentication.hooks.authenticate(config.strategies),
async context => {
const { app, data } = context;
const user = await app.service('users').find({
query: {
usernameUpperCase: data.username.toUpperCase(),
$limit: 1
}
});
try {
await Promise.all(user.data.map(async data => {
if(!data.isVerified) {
await console.log('HELLO FROM ABOVE.');
//await v.validationError('Verify Email. A token link has been sent to your email.');
}
});
} catch(err) {
throw v.validationError(err);
}
},