Skip to content

Commit

Permalink
feat(example-todo-list): add navigational properties to todo-list exa…
Browse files Browse the repository at this point in the history
…mple
  • Loading branch information
nabdelgadir committed Jun 19, 2019
1 parent 0737e39 commit 1e9fdd6
Show file tree
Hide file tree
Showing 10 changed files with 358 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,20 @@ import {
toJSON,
} from '@loopback/testlab';
import {TodoListApplication} from '../../application';
import {TodoList} from '../../models/';
import {TodoListRepository} from '../../repositories/';
import {givenTodoList} from '../helpers';
import {Todo, TodoList} from '../../models/';
import {TodoListRepository, TodoRepository} from '../../repositories/';
import {givenTodo, givenTodoList} from '../helpers';

describe('TodoListApplication', () => {
let app: TodoListApplication;
let client: Client;
let todoRepo: TodoRepository;
let todoListRepo: TodoListRepository;

before(givenRunningApplicationWithCustomConfiguration);
after(() => app.stop());

before(givenTodoListRepository);
before(givenTodoRepositories);
before(() => {
client = createRestAppClient(app);
});
Expand Down Expand Up @@ -178,6 +179,20 @@ describe('TodoListApplication', () => {
.expect(200, [toJSON(listInBlack)]);
});

it('includes Todos in query result', async () => {
const list = await givenTodoListInstance();
const todo = await givenTodoInstance({todoListId: list.id});
const filter = JSON.stringify({include: [{relation: 'todos'}]});

const response = await client.get('/todo-lists').query({filter: filter});

expect(response.body).to.have.length(1);
expect(response.body[0]).to.deepEqual({
...toJSON(list),
todos: [toJSON(todo)],
});
});

/*
============================================================================
TEST HELPERS
Expand Down Expand Up @@ -210,14 +225,19 @@ describe('TodoListApplication', () => {
await app.start();
}

async function givenTodoListRepository() {
async function givenTodoRepositories() {
todoRepo = await app.getRepository(TodoRepository);
todoListRepo = await app.getRepository(TodoListRepository);
}

async function givenTodoListInstance(todoList?: Partial<TodoList>) {
return await todoListRepo.create(givenTodoList(todoList));
}

async function givenTodoInstance(todo?: Partial<Todo>) {
return await todoRepo.create(givenTodo(todo));
}

function givenMutlipleTodoListInstances() {
return Promise.all([
givenTodoListInstance(),
Expand Down
16 changes: 15 additions & 1 deletion examples/todo-list/src/__tests__/acceptance/todo.acceptance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
} from '@loopback/testlab';
import {TodoListApplication} from '../../application';
import {Todo, TodoList} from '../../models/';
import {TodoRepository, TodoListRepository} from '../../repositories/';
import {TodoListRepository, TodoRepository} from '../../repositories/';
import {givenTodo, givenTodoList} from '../helpers';

describe('TodoListApplication', () => {
Expand Down Expand Up @@ -149,6 +149,20 @@ describe('TodoListApplication', () => {
.expect(200, [toJSON(todoInProgress)]);
});

it('includes TodoList in query result', async () => {
const list = await givenTodoListInstance();
const todo = await givenTodoInstance({todoListId: list.id});
const filter = JSON.stringify({include: [{relation: 'todoList'}]});

const response = await client.get('/todos').query({filter: filter});

expect(response.body).to.have.length(1);
expect(response.body[0]).to.deepEqual({
...toJSON(todo),
todoList: toJSON(list),
});
});

/*
============================================================================
TEST HELPERS
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import {expect, givenHttpServerConfig} from '@loopback/testlab';
import {TodoListApplication} from '../../application';
import {Todo, TodoList} from '../../models';
import {TodoListRepository, TodoRepository} from '../../repositories';
import {givenTodo, givenTodoList} from '../helpers';

describe('TodoListApplication', () => {
let app: TodoListApplication;
let todoRepo: TodoRepository;
let todoListRepo: TodoListRepository;

before(givenRunningApplicationWithCustomConfiguration);
after(() => app.stop());

before(givenTodoRepositories);

it('includes Todos in find method result', async () => {
const list = await givenTodoListInstance();
const todo = await givenTodoInstance({todoListId: list.id});

const response = await todoListRepo.find({
include: [{relation: 'todos'}],
});

expect(response[0]).to.containEql(list);
expect(response[0]).to.containEql({
todos: [todo],
});
});

it('includes Todos in findById result', async () => {
const list = await givenTodoListInstance();
const todo = await givenTodoInstance({todoListId: list.id});

const response = await todoListRepo.findById(list.id, {
include: [{relation: 'todos'}],
});

expect(response).to.containEql(list);
expect(response).to.containEql({
todos: [todo],
});
});

// TOOD: refactor this to the helpers file so it's not duplicated

async function givenRunningApplicationWithCustomConfiguration() {
app = new TodoListApplication({
rest: givenHttpServerConfig(),
});

await app.boot();

/**
* Override default config for DataSource for testing so we don't write
* test data to file when using the memory connector.
*/
app.bind('datasources.config.db').to({
name: 'db',
connector: 'memory',
});

// Start Application
await app.start();
}

async function givenTodoRepositories() {
todoRepo = await app.getRepository(TodoRepository);
todoListRepo = await app.getRepository(TodoListRepository);
}

async function givenTodoInstance(todo?: Partial<Todo>) {
return await todoRepo.create(givenTodo(todo));
}

async function givenTodoListInstance(data?: Partial<TodoList>) {
return await todoListRepo.create(givenTodoList(data));
}
});
79 changes: 79 additions & 0 deletions examples/todo-list/src/__tests__/integration/todo.integration.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import {expect, givenHttpServerConfig} from '@loopback/testlab';
import {TodoListApplication} from '../../application';
import {Todo, TodoList} from '../../models';
import {TodoListRepository, TodoRepository} from '../../repositories';
import {givenTodo, givenTodoList} from '../helpers';

describe('TodoApplication', () => {
let app: TodoListApplication;
let todoRepo: TodoRepository;
let todoListRepo: TodoListRepository;

before(givenRunningApplicationWithCustomConfiguration);
after(() => app.stop());

before(givenTodoRepositories);

it('includes TodoList in find method result', async () => {
const list = await givenTodoListInstance();
const todo = await givenTodoInstance({todoListId: list.id});

const response = await todoRepo.find({
include: [{relation: 'todoList'}],
});

expect(response[0]).to.containEql(todo);
expect(response[0]).to.containEql({
todoList: list,
});
});

it('includes TodoList in findById result', async () => {
const list = await givenTodoListInstance({color: 'grey'});
const todo = await givenTodoInstance({todoListId: list.id});

const response = await todoRepo.findById(todo.id, {
include: [{relation: 'todoList'}],
});

expect(response).to.containEql(todo);
expect(response).to.containEql({
todoList: list,
});
});

// TOOD: refactor this to the helpers file so it's not duplicated

async function givenRunningApplicationWithCustomConfiguration() {
app = new TodoListApplication({
rest: givenHttpServerConfig(),
});

await app.boot();

/**
* Override default config for DataSource for testing so we don't write
* test data to file when using the memory connector.
*/
app.bind('datasources.config.db').to({
name: 'db',
connector: 'memory',
});

// Start Application
await app.start();
}

async function givenTodoRepositories() {
todoRepo = await app.getRepository(TodoRepository);
todoListRepo = await app.getRepository(TodoListRepository);
}

async function givenTodoInstance(todo?: Partial<Todo>) {
return await todoRepo.create(givenTodo(todo));
}

async function givenTodoListInstance(data?: Partial<TodoList>) {
return await todoListRepo.create(givenTodoList(data));
}
});
24 changes: 20 additions & 4 deletions examples/todo-list/src/controllers/todo-list.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
del,
get,
getFilterSchemaFor,
getModelSchemaRef,
getWhereSchemaFor,
param,
patch,
Expand Down Expand Up @@ -60,7 +61,14 @@ export class TodoListController {
responses: {
'200': {
description: 'Array of TodoList model instances',
content: {'application/json': {schema: {'x-ts-type': TodoList}}},
content: {
'application/json': {
schema: {
type: 'array',
items: getModelSchemaRef(TodoList, {includeRelations: true}),
},
},
},
},
},
})
Expand Down Expand Up @@ -91,12 +99,20 @@ export class TodoListController {
responses: {
'200': {
description: 'TodoList model instance',
content: {'application/json': {schema: {'x-ts-type': TodoList}}},
content: {
'application/json': {
schema: getModelSchemaRef(TodoList, {includeRelations: true}),
},
},
},
},
})
async findById(@param.path.number('id') id: number): Promise<TodoList> {
return await this.todoListRepository.findById(id);
async findById(
@param.path.number('id') id: number,
@param.query.object('filter', getFilterSchemaFor(TodoList))
filter?: Filter<TodoList>,
): Promise<TodoList> {
return await this.todoListRepository.findById(id, filter);
}

@patch('/todo-lists/{id}', {
Expand Down
17 changes: 13 additions & 4 deletions examples/todo-list/src/controllers/todo.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
del,
get,
getFilterSchemaFor,
getModelSchemaRef,
param,
patch,
post,
Expand Down Expand Up @@ -36,15 +37,20 @@ export class TodoController {
responses: {
'200': {
description: 'Todo model instance',
content: {'application/json': {schema: {'x-ts-type': Todo}}},
content: {
'application/json': {
schema: getModelSchemaRef(Todo, {includeRelations: true}),
},
},
},
},
})
async findTodoById(
@param.path.number('id') id: number,
@param.query.boolean('items') items?: boolean,
@param.query.object('filter', getFilterSchemaFor(Todo))
filter?: Filter<Todo>,
): Promise<Todo> {
return await this.todoRepo.findById(id);
return await this.todoRepo.findById(id, filter);
}

@get('/todos', {
Expand All @@ -53,7 +59,10 @@ export class TodoController {
description: 'Array of Todo model instances',
content: {
'application/json': {
schema: {type: 'array', items: {'x-ts-type': Todo}},
schema: {
type: 'array',
items: getModelSchemaRef(Todo, {includeRelations: true}),
},
},
},
},
Expand Down
2 changes: 1 addition & 1 deletion examples/todo-list/src/models/todo.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export class Todo extends Entity {
}

export interface TodoRelations {
todoList?: TodoListWithRelations[];
todoList?: TodoListWithRelations;
}

export type TodoWithRelations = Todo & TodoRelations;
Loading

0 comments on commit 1e9fdd6

Please sign in to comment.