Mocking REST calls in Svelte - rest

Hi I've been using Svelte for some weeks not and really enjoy it.
I was trying to set up unit tests according to https://testing-library.com/docs/svelte-testing-library/intro/
and that went also well. What that guide does not include however, is how I should mock my REST calls. I have tried following without success:
jest-mock-fetch
jest-fetch-mock
jest-mock-promise
msw server (this does not respond anything, maybe it works only for React applications?)
Has anyone successfully mocked the REST calls in a Svelte app, if so could you post a minimal fiddle to show me what libs to use and how it looks like. Thank you.

Instead of mocking the request functions you can mock at the network layer with the msw library. This has the added benefit of not being tied to fetch, so you could replace with axios if need be.
It would look something like this:
import {rest} from 'msw'
import {setupServer} from 'msw/node'
const server = setupServer(
rest.get('/my-api', (req, res, ctx) => {
return res(ctx.json({greeting: 'hello there'}))
}),
)
beforeAll(() => server.listen())
afterEach(() => server.resetHandlers())
afterAll(() => server.close())
test('does what I want it to', async () => {
// the actual test...
})
You can have a look at the react examples in the testing library. Although it's specifically for react, the msw use can be used the same in svelte testing.

Related

Flutter testing, passing an actual HTTP client, instead of a mocked one

I have developed a package in flutter, and wanted to test it, which makes a network call.
As we know that all network request while testing will return 404, and such HTTP reqeust needs to be mocked.
However its also possible to use the orginal HTTP clients instead of mocking or getting 404.
https://github.com/flutter/flutter/issues/19086#issuecomment-402639134
How do we do that ?
I have tried this :
main(){
TestWidgetsFlutterBinding.ensureInitialized();
HttpOverrides.runZoned(() {
test("Case1: Make HTTP request to an actual server", ()async{
let a = MyPackage.makesAHTTPRequest();
expect(a,"hello world");
});
}, createHttpClient: (SecurityContext c) => new HttpClient(context: c));
}
My URL is working all fine.
But it keeps giving me 404.
How do one use real HTTP client, if needed that way?
Ok so if any one is facing a similar issue like me use this hack.
You will need to modify your class, in a way that we can inject HTTP clients into it at run time. We will need to modify our test case as such.
import 'package:http/http.dart'; //client is from this pack
Client httpclinet = Client();
var a = MyPackage.makesAHTTPRequest(httpclient);
remove that Httpoverride.runzoned cod, you can pass Client object from http package directly.
Some test case will fail, due to fake asynchronous effect, but you can use timeouts to manage those.
You will also need to remove any such statements:
TestWidgetsFlutterBinding.ensureInitialized();
In my case I added this line as I was loading files from assets, using packages notation, I referenced them locally and removed above ensureInitalized line as well. [Actually I passed flag to use local notation during testing and package notation otherwise]

Get body request parameters using express in V2 Dialogflow

I'm migrating my Google Action from v1 => v2 using an express app, and in the past, I've been able to get url params & initialize my action map like this:
// INITIALIZE EXPRESS APPLICATION & ENDPOINTS
app.use(bodyParser.json({strict: false}));
// POST [TYPE] [PLATFORM] [PUBLISHER] PARAMS => PASS TO FULFILLMENT
app.post('/:platform/:type/:publisher', function(req, res) {
debugRequest(req);
console.log(`SENDING TO ${TYPE} => ${PLATFORM} => ${PUBLISHER} FULFILLMENT`);
fulfillment.fulfillment(req, res);
});
```
With v2, instead of using a .post route with express, I just need to use .use e.g. express().use(bodyParser.json(), app). However, I don't understand how to get the body params (req/res) using this method [still kind of a node newbie] from body parser.
I need the full URL path (type, platform, publisher) from the request in order to fulfill some app logic later on, within various intents.
If someone has a more built out express / v2 Dialogflow example, that'd be very helpful. I have all this working with v1, but times are a changing!
You should be able to get this data now with the new Framework Metadata feature added in 2.2.0. See this GitHub comment for more details.
An object containing framework metadata is now present as the 2nd parameter in the middleware function.
Now you can do something like:
app.middleware((conv, framework) => {
if (framework.express) {
conv.expressParams = framework.express.request.expressParams;
}
});
app.intent('some intent', conv => {
conv.ask(`Params sent was ${JSON.stringify(conv.expressParams)}`);
});
From a similar question in this GitHub issue:
You can retrieve the raw JSON data from conv.request for the core Actions on Google data and conv.body for the entire JSON body.

How to render react on server-side with an api?

Just to make it clear, I'm using the MongoDB, Express, React and Node stack.
I'm trying to learn react.js right now. I got the basics right and I am able to code a simple react app with a router. I've also tried server-side rendering a simple react app and it also works perfectly. However, I'm kind of stuck now that I want to make a full app with a rest api and server-side rendering.
1) I don't know how I should go about separating the api and the react code in the server file. Would starting off by listing the api calls and then do the server-side rendering work?
Like so:
app.get('/api/whatever', function(req, res) {
//get whatever
});
app.get('*', function(req, res) {
//math routes and renderToString React
});
2) Also, the reason I couldn't even test the above, is that when I try to run the server with nodemon it throws an error because it doesn't understand the react code, how should I go about this? Should I somehow configure nodemon to read es6 or ignore it or configure webpack to run the express server ?
3) The final question that could clear this whole story quite easily. I've tried finding an answer but got many conflicting ones instead. Are the google crawlers capable of crawling a React app? I'm learning server-side rendering for SEO, is that all really necessary?
Sorry for the long question, looking forward to reading your answers.
I do it the same way you do in your code example in the project I'm currently working on – I match * and then use React Router to render different pages. I wrote a blog article about this, with code examples.
in the setup I have, I use webpack to compile my backend code, just like I do with the frontend code. I use the watch mechanism to listen for code changes and automatically restart the node server after recompiling. No need for nodemon.
#!/usr/bin/env node
const path = require('path');
const webpack = require('webpack');
const spawn = require('child_process').spawn;
const serverConfig = require('webpack.config.server');
const compiler = webpack(serverConfig);
const watchConfig = {
aggregateTimeout: 300,
poll: 1000,
ignored: '**/*.scss'
};
let serverControl;
compiler.watch(watchConfig, (err, stats) => {
if (err) {
console.error(err.stack || err);
if (err.details) {
console.error(err.details);
}
return;
}
const info = stats.toJson();
if (stats.hasErrors()) {
info.errors.forEach(message => console.log(message));
return;
}
if (stats.hasWarnings()) {
info.warnings.forEach(message => console.log(message));
}
if (serverControl) {
serverControl.kill();
}
serverControl = spawn('node', [path.resolve(__dirname, '../../dist/polly-server.js')]);
serverControl.stdout.on('data', data => console.log(`${new Date().toISOString()} [LOG] ${data}`));
serverControl.stderr.on('data', data => console.error(`${new Date().toISOString()} [ERROR] ${data}`));
});
yes, Google crawls client-side React code, but server-side rendering is still a good idea, because crawl results may be inconsistent, especially if you load parts of the page dynamically after Ajax calls

Karma/Jasmine Unit Testing an AngularJS Service with Dependencies

I'm a novice programmer who is very new to both AngularJS and the practice of unit testing. I've spent hours trying to find the solution to this but I'm becoming increasingly more confused. If anyone could point me in the right direction I would greatly appreciate it. I'll try to be as descriptive as possible.
The situation is this:
I have created a service in AngularJS (Service A) that has a couple of functions. Each of these functions makes an $http GET request to a REST API and returns an $http promise object that contains JSON data. Within these functions, the URL is constructed through the implementation of another very simple service (Service B) that has been injected as a dependency into Service A. I have created a mock of Service B to isolate it from all of its dependencies. Both of these services are defined inside of the same module named "services". In this case, there is no real need for this dependency but I just want to understand how it works.
Using Jasmine, I would like to construct a unit test for Service A to ensure that the requests it is making to the API are constructed correctly and possibly if the correct JSON data is being returned. At the same time, I do not want any real API calls to be made.
This is what I know:
$httpBackend mock is what I need to be able to make fake calls to the API and it provides functionality to expect certain requests and return specified results.
I need to test the real Service A and inject the mock I've created of Service B. I know there are ways to do this using Jasmine Spies and $provide. I've also seen examples where sinon.js is used, and I'm not sure which is the best approach.
I will post my source code below, which is written in CoffeeScript.
Service A:
'use strict'
angular.module("services")
.service("ServiceA", ["$http", "ServiceB", ($http, ServiceB) ->
#Uses underscore.js to set this default attribute
defaults = withCredentials:true
getVarset: (itemName, options={}) ->
options.method = "GET"
options.url = ServiceB.makeUrl("item/#{itemName}")
$http _.defaults(options, defaults)
getVarsets: (options = {}) ->
options.method = "GET"
options.url = ServiceB.makeUrl("items")
$http _.defaults(options, defaults)
getModelsForVarset: (itemName, options = {}) ->
options.method = "GET"
options.url = ServiceB.makeUrl("item/#{itemName}/prices")
$http _.defaults(options, defaults)
])
Service B:
'use strict'
angular.module('services')
.service 'ServiceB', [ ->
# Just return the string
# This service builds the real URL, but I've removed this
makeUrl: (Url) ->
"#{Url}"
]
so are you saying that you know how to do this with $provide/Jasmine spies and are looking for alternatives? I've mostly just used the $provide/spy method for mocking and it's worked out really well for me so far.
something like:
beforeEach(function() {
// set up a default value for your mock
bMock = {
makeUrl: jasmine.createSpy('makeUrl() mock').andReturn('http://www....')
}
// use the $provide service to replace ServiceB
// with your mock
module('services', function($provide) {
$provide.value('ServiceB', bMock);
});
});
it('should do what its supposed to do', function() {
// test...
});
then, if you want to use $httpBackend to mock the http requests in service A, you just need to use the $injector service to grab $httpBackend, then call .when(...) on it to set things up, a la http://docs.angularjs.org/api/ngMock.$httpBackend

node.js and socket.io: different connections for different "sessions"

I've got a node.js application that 'streams' tweets to users. At the moment, it just searches Twitter for a hard-coded string, but I'd like to allow users to configure this in the URL (eg. by visiting /?q=stackoverflow).
At the moment, my code looks a bit like this:
app.get('/', function (req, res) {
// page rendering skipped
io.sockets.on('connection', function (socket) {
twit.stream('user', {track: 'stackoverflow'}, function(stream) {
stream.on('data', function (data) {
socket.volatile.emit('tweet', data);
}
});
});
});
The question is, how do I make it so that each user can see a different stream of tweets simultaneously? At the moment, it works fine in a single browser tab, but it falls over as soon as a second one is opened - and the error is fairly deep down inside socket.io. Am I misusing it?
I haven't fully got my head around socket.io yet, so that could be the issue.
Thanks in advance!
Every time a new request comes in, you are redefining the connection callback with io.sockets.on - you should move that block of code outside of app.get, after your initialization statement of the io object.