How to test Ember.Router - testing

I would like to test my router which for the sake of simplicity looks as follows:
// app.router.js
import Ember from 'ember';
import config from './config/environment';
const Router = Ember.Router.extend({
location: config.locationType
});
Router.map(function() {
this.route('sessions', function() {
this.route('login');
this.route('logout');
});
this.route('profile');
});
export default Router;
Is it possible to unit-test it?
I tried using acceptance tests but I was not successful:
import Ember from 'ember';
import { test } from 'qunit';
import moduleForAcceptance from 'transformed-admin/tests/helpers/module-for-acceptance';
import startApp from 'transformed-admin/tests/helpers/start-app';
moduleForAcceptance('Acceptance | configuration', {
beforeEach: function() {
this.application = startApp();
},
afterEach: function() {
Ember.run(this.application, 'destroy');
}
});
test('should map routes correctly', function(assert) {
visit('/');
const app = this.application;
andThen(function() {
app.Router.detect("profile"); // false
app.Router.detect("Profile"); // false
const a = app.Router.extend({});
a.detect("profile"); // false
a.detect("Profile"); // false
});
});
What are the best practices here? Do you test Router.map() at all? Or do you rely on testing of concrete routes as a guarantee that the Router.map() is written correctly?

Not quite sure what you want to do. You could write acceptance tests for each route if you want to make sure that they are visible:
import { test } from 'qunit';
import moduleForAcceptance from 'people/tests/helpers/module-for-acceptance';
moduleForAcceptance('Acceptance | login');
test('visiting /', function(assert) {
visit('/');
andThen(function() {
assert.equal(currentURL(), '/index');
assert.equal(currentPath(), 'index');
});
});
test('visiting /profile', function(assert) {
visit('/profile');
andThen(function() {
assert.equal(currentURL(), '/profile');
assert.equal(currentPath(), 'profile');
});
});
You could also write unit tests for your routes.
You should not test Ember.js internals. Ember.Router is covered by tests. You should test your application specific logic (eg. handling a specific action in a route by unit test) and behavior (eq. a specific route exists by acceptance test).

Related

using Nuxt 3 with Nest

Currently we are able to build nuxt as following. But are unable to handle routes. We basically want to serve nuxt app from Nestjs.
import { NestFactory } from '#nestjs/core';
import { AppModule } from './app.module.js';
import { loadNuxt } from 'nuxt3';
import { buildNuxt, Resolver } from '#nuxt/kit';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
// Check if we need to run Nuxt in development mode
const isDev = process.env.NODE_ENV !== 'production'
// Get a ready to use Nuxt instance
const nuxt = await loadNuxt({ rootDir: 'src/client-app/' })
// Enable live build & reloading on dev
if (isDev) {
buildNuxt(nuxt)
}
await app.listen(3001);
}
bootstrap();
Following is next (react) equivalent code which is working and trying to achieve in Nuxt 3.
https://github.com/hnviradiya/contact-list/blob/e38a72167d5710fcc9f3ed9718fa9bfe8ebb7d00/src/server/client-app/client-app.service.ts#L25
import { Injectable } from '#nestjs/common';
import { ConfigService } from '#nestjs/config';
import { IncomingMessage, ServerResponse } from 'http';
import createServer, { NextServer } from 'next/dist/server/next';
#Injectable()
export class ClientAppService {
private nextServer: NextServer;
constructor(private configService: ConfigService) {}
async onModuleInit(): Promise<void> {
try {
this.nextServer = createServer({
dev: this.configService.get<string>('NODE_ENV') !== 'production',
dir: './src/client',
});
await this.nextServer.prepare();
} catch (error) {
console.error(error);
}
}
handler(req: IncomingMessage, res: ServerResponse) {
return this.nextServer.getRequestHandler()(req, res);
}
}
In nuxt 2 there were nuxt.render(req, res) or nuxt.renderRoute(route, context). But these methods are not available in nuxt3.
https://nuxtjs.org/docs/internals-glossary/nuxt/
So how to serve nuxt app through NestJs.
Following is the repo where nuxt 3 code is there but it is not serving nuxt app.
https://github.com/hnviradiya/nest-nuxt
while Nestjs is a great server, it's angular style #decorators and modular setup is too unlike Nuxt3's scaffold simplicity.
This conception feels like a bad idea.

How do I create a dummy component to use in an Ember integration test?

I have a component some-container that takes a hash of ids mapped to other ember components. This is how it's used:
{{modules/some-container
pageKey="foo"
widgetIdToComponent=(hash
foo=(component "modules/dummy-component")
)
}}
I'm writing an integration test for this component and I want to keep the test independent of other components. Is there a way to define dummy components within an Ember integration test file?
The existing answer from #Tyler Becks is good for legacy ember-qunit, but with native qunit (since: 2017: https://github.com/emberjs/rfcs/blob/master/text/0232-simplify-qunit-testing-api.md), you'd want something like this (known to work with at least Ember Octane (3.16+)):
import { test, module } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { hbs } from 'ember-cli-htmlbars';
import { render } from '#ember/test-helpers';
import { setComponentTemplate } from '#ember/component';
import templateOnly from '#ember/component/template-only';
import Component from '#glimmer/component';
module('name of test suite', function(hooks) {
setupRenderingTest(hooks);
test('name of test', async function(assert) {
class MyComponent extends Component {}
setComponetTemplate(hbs`your template here`, MyComponent);
this.owner.register('component:component-name', MyComponent);
await render(hbs`<ComponentName />`);
});
// alternatively, things get a bit simpler if you're using
// ember-source 3.25+
test('name of test 2', async function(assert) {
class MyComponent extends Component {}
setComponetTemplate(hbs`your template here`, MyComponent);
this.setProperties({ MyComponent });
await render(hbs`<this.MyComponent />`);
});
// template-only components are even simpler still
test('name of test 3', async function(assert) {
this.setProperties({
MyComponent: setComponetTemplate(
hbs`your template here`,
templateOnly()
);
});
await render(hbs`<this.MyComponent />`);
});
});
Figured it out! The solution is to use this.register. See below:
moduleForComponent('some-container', 'Integration | Component | some-container', {
integration: true,
beforeEach() {
this.register(
'component:foo-div',
Component.extend({
layout: hbs`<div data-test-foo />`
})
);
this.register(
'component:bar-div',
Component.extend({
layout: hbs`<div data-test-bar />`
})
);
this.component = hbs`
{{modules/some-container
pageKey="foo"
widgetIdToComponent=(hash
fooId=(component "foo-div")
barId=(component "bar-div")
)
}}`;
}
});
test('it renders foo div when only foo div is returned', function(assert) {
this.render(this.component);
assert.dom('[data-test-foo]').exists('foo div renders');
assert.dom('[data-test-bar]').doesNotExist('foo div renders');
});

How can I retrieve a route's model() when writing a test?

I have a route that has its own model, which does not come from the Ember store (let's say it can come from "anywhere" for the sake of this question).
model() {
return RSVP.hash({
value: someCall()
});
}
this.owner.lookup('route:routeName').model() does not seem to work, neither does this.owner.lookup('controller:controllerName').get('model.X') or any of the other things I've tried.
Nor does it seem to be mentioned at https://guides.emberjs.com/v3.1.0/testing/testing-routes/
How would you retrieve a route's model in a test?
The Ember router doesn't appear to have any kind of public interface to get the model according to the official docs (https://emberjs.com/api/ember/3.1/classes/EmberRouter). It can access the model function internally though. This feels a bit hackish, but I was able to get it to work:
Router:
import Route from '#ember/routing/route';
import { hash } from 'rsvp';
export default Route.extend({
model() {
return hash({
value: 'wibble'
});
},
getMyModel: function() {
return this.get('model')();
}
});
Router test:
import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
module('Unit | Route | test', function(hooks) {
setupTest(hooks);
test('do something with the router model...', function(assert) {
let route = this.owner.lookup('route:test');
assert.ok(route);
route.getMyModel().then(function(model) {
console.log(model);
assert.equal(model.value, 'wibble');
});
});
});
You can go with:
route.get('model')()

Login Test with Ember Test

I have write a ember test file for a login formular. The redirect Page is a Dashboard with a Time Ticker Sidebar. Now, when i tested this, i became a test time out after 60000ms. Can i exclude the Time Ticker Component in ember test?
My Test Code:
import {test} from 'qunit';
import moduleForAcceptance from 'frontend/tests/helpers/module-for-acceptance';
moduleForAcceptance('Acceptance | Login', {
integration: true
});
test('visiting /user_session/new', function (assert) {
visit('/user_session/new');
fillIn('input#login-email', 'test#example.de');
fillIn('input#login-password', 'blabla');
click('button.btn-primary');
let done = assert.async();
andThen(() => {
Ember.run.later(null, () => {
assert.equal(currentURL(), '/dashboard', 'redirects to the dashboard');
done();
}, 1000);
});
});
The Time Ticker Component:
import Ember from 'ember';
export default Ember.Component.extend({
tagName: 'time',
date: moment().format('DD.MM.YYYY'),
time: Ember.computed('value', function() {
return moment().format('HH:mm:ss');
}),
didInsertElement: function() {
this.tick();
},
tick: function() {
this.set('nextTick', Ember.run.later(this, function() {
this.notifyPropertyChange('value');
this.tick();
}, 1000));
},
willDestroyElement: function() {
Ember.run.cancel(this.get('nextTick'));
}
});
Wrap ticking mechanism in a service and use that service in your component.
During test, mock that service and inject the mock in your component. Although mocking in acceptence test is not a good thing for me, I can go with mocking approach in this scenario.
Also you can consider using ember-moment's live update in your pages. It provides the live update of time. Here there is.

How to use a mocked data with react-apollo for tests

I'm using react-apollo to build a client that consumes a GraphQL API, however, I'm very stuck on testing. What I want is to mock the server so I can easily test the application without needing to make network calls.
I've found some pointers on how to mock the server:
https://dev-blog.apollodata.com/mocking-your-server-with-just-one-line-of-code-692feda6e9cd
http://dev.apollodata.com/tools/graphql-tools/mocking.html#addMockFunctionsToSchema
But there isn't really an example on how to use this mocked server in my app tests to avoid hitting the server.
My goal is to setup integration tests to assert that the app is actually working:
describe('Profile feature', () => {
beforeAll(() => {
store = setupStore();
app = mount(
<ApolloProvider store={store} client={apolloClient}>
<ConnectedRouter history={history}>
<App />
</ConnectedRouter>
</ApolloProvider>
);
});
});
The store is using Redux and the client is being created like this:
const networkInterface = createNetworkInterface({
uri: process.env.REACT_APP_API_URL
});
export const apolloClient = new ApolloClient({
networkInterface
});
How can I use a mocked server with graphql-tools here instead of the actual API?
I found 2 different ways of creating mocked data for apollo-client queries:
The first is to use graphql-tools to create a mocked server based on your backend schema, in order to connect this mocked server with your tests it's possible to create a mockNetworkInterface like this:
const { mockServer } = require("graphql-tools");
const { print } = require("graphql/language/printer");
class MockNetworkInterface {
constructor(schema, mocks = {}) {
if (schema === undefined) {
throw new Error('Cannot create Mock Api without specifying a schema');
}
this.mockServer = mockServer(schema, mocks);
}
query(request) {
return this.mockServer.query(print(request.query), request.variables);
}
}
You can pass this network interface to the ApolloClient component and it should work just fine!
Having this setup requires to have your API schema up to date in your client, so I found it a bit of a pain to do.
Another way of doing this is using the mockNetworkInterface provided by apollo-client/test-utils
You can use it this way:
import App from './App';
import { UserMock, PublicationMock } from '../__mocks__/data';
import { mockNetworkInterface } from 'react-apollo/test-utils';
import ApolloClient from 'apollo-client';
import { ApolloProvider } from 'react-apollo';
// We will be using here the exact same Query defined in our components
// We will provide a custom result or a custom error
const GraphQLMocks = [
{
request: {
query: UserProfileQuery,
variables: {}
},
result: {
data: {
current_user: UserMock
}
}
}
];
// To set it up we pass the mocks to the mockNetworkInterface
const setupTests = () => {
const networkInterface = mockNetworkInterface.apply(null, GraphQLMocks);
const client = new ApolloClient({ networkInterface, addTypename: false });
const wrapper = mount(
<ApolloProvider client={client}>
<App />
</ApolloProvider>
);
return {
store,
wrapper
};
};
// Then the tests look like this
describe('Profile feature', () => {
test('Profile view should render User details', async () => {
const { wrapper, store } = setupTests();
const waitFor = createWaitForElement('.profile');
await waitFor(wrapper);
const tag = wrapper.find('.profile-username');
expect(tag.text()).toEqual(`${UserMock.first_name} ${UserMock.last_name}`);
});
});
It is important to pass addTypename: false to the ApolloClient instance, otherwise you will need to add __typename to all your queries manually.
You can inspect the implementation of the mockNetworkInterface here: https://github.com/apollographql/apollo-test-utils/blob/master/src/mocks/mockNetworkInterface.ts
You can also use MockedProvider, which makes it even simpler.
withPersons.js
import { gql, graphql } from 'react-apollo'
export const PERSONS_QUERY = gql`
query personsQuery {
persons {
name
city
}
}
`
export const withPersons = graphql(PERSONS_QUERY)
withPersons.test.js
/* eslint-disable react/prop-types */
import React, { Component } from 'react'
import { MockedProvider } from 'react-apollo/test-utils'
import { withPersons, PERSONS_QUERY } from '../withPersons'
it('withPersons', (done) => {
const mockedData = {
persons: [
{
name: 'John',
city: 'Liverpool',
},
{
name: 'Frank',
city: 'San Diego',
},
],
}
const variables = { cache: false }
class Dummy extends Component {
componentDidMount() {
const { loading, persons } = this.props.data
expect(loading).toBe(true)
expect(persons).toBe(undefined)
}
componentWillReceiveProps(nextProps) {
const { loading, persons } = nextProps.data
expect(loading).toBe(false)
expect(persons).toEqual(mockedData.persons)
done()
}
render() {
return null
}
}
const DummyWithPersons = withPersons(Dummy)
mount(
<MockedProvider
removeTypename
mocks={[
{
request: { query: PERSONS_QUERY, variables },
result: { data: mockedData } },
]}
>
<DummyWithPersons />
</MockedProvider>,
)
})
Note: By using a Dummy component you just test your graphql() Queries and Mutations and the way you have configured them (options, props, skip, variables, etc.) So you don't mount your actual React components. It's better to test those in their 'unconnected' state.
I wrote up a blog post a while that might be helpful: http://blog.dideric.is/2018/03/18/Testing-apollo-containers/
Apollo has something called LinkSchema that makes the first approach Carlos mentioned a lot easier. It still takes some setup, but I think it's worth it. If you're creating responses manually, you have to worry a lot more about keeping your tests up to date/getting false positives when the schema changes and you haven't accounted for it in your code.