Skip to content

Commit

Permalink
refactor(example-getting-started): restore original code for migration
Browse files Browse the repository at this point in the history
  • Loading branch information
Kevin Delisle committed Jan 19, 2018
1 parent dbbfb2c commit 99bb50e
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 71 deletions.
77 changes: 35 additions & 42 deletions packages/example-getting-started/src/controllers/todo.controller.ts
Original file line number Diff line number Diff line change
@@ -1,63 +1,56 @@
// Copyright IBM Corp. 2017,2018. All Rights Reserved.
// Node module: @loopback/example-getting-started
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT

import {Filter, Where} from '@loopback/repository';
import {post, param, get, put, patch, del} from '@loopback/openapi-v2';
import {inject} from '@loopback/context';
import {Todo} from '../models';
import {TodoRepository} from '../repositories';
import {HttpErrors} from '@loopback/rest';
import {TodoSchema, Todo} from '../models';
import {repository} from '@loopback/repository';
import {TodoRepository} from '../repositories/index';

export class TodoController {
// TODO(bajtos) Fix documentation (and argument names?) of @repository()
// to allow the usage below.
// See https://github.com/strongloop/loopback-next/issues/744
constructor(
@inject('repositories.TodoRepository')
public todoRepository: TodoRepository,
@repository(TodoRepository.name) protected todoRepo: TodoRepository,
) {}

@post('/todo')
async create(@param.body('obj') obj: Todo): Promise<Todo> {
return await this.todoRepository.create(obj);
@param.body('todo', TodoSchema)
async createTodo(todo: Todo) {
// TODO(bajtos) This should be handled by the framework
// See https://github.com/strongloop/loopback-next/issues/118
if (!todo.title) {
return Promise.reject(new HttpErrors.BadRequest('title is required'));
}
return await this.todoRepo.create(todo);
}

@get('/todo/count')
async count(@param.query.string('where') where: Where): Promise<number> {
return await this.todoRepository.count(where);
@get('/todo/{id}')
@param.path.number('id')
@param.query.boolean('items')
async findTodoById(id: number, items?: boolean): Promise<Todo> {
return await this.todoRepo.findById(id);
}

@get('/todo')
async find(@param.query.string('filter') filter: Filter): Promise<Todo[]> {
return await this.todoRepository.find(filter);
}

@patch('/todo')
async updateAll(
@param.query.string('where') where: Where,
@param.body('obj') obj: Todo,
): Promise<number> {
return await this.todoRepository.updateAll(where, obj);
}

@del('/todo')
async deleteAll(@param.query.string('where') where: Where): Promise<number> {
return await this.todoRepository.deleteAll(where);
async findTodos(): Promise<Todo[]> {
return await this.todoRepo.find();
}

@get('/todo/{id}')
async findById(@param.path.number('id') id: number): Promise<Todo> {
return await this.todoRepository.findById(id);
@put('/todo/{id}')
@param.path.number('id')
@param.body('todo', TodoSchema)
async replaceTodo(id: number, todo: Todo): Promise<boolean> {
return await this.todoRepo.replaceById(id, todo);
}

@patch('/todo/{id}')
async updateById(
@param.path.number('id') id: number,
@param.body('obj') obj: Todo,
): Promise<boolean> {
return await this.todoRepository.updateById(id, obj);
@param.path.number('id')
@param.body('todo', TodoSchema)
async updateTodo(id: number, todo: Todo): Promise<boolean> {
return await this.todoRepo.updateById(id, todo);
}

@del('/todo/{id}')
async deleteById(@param.path.number('id') id: number): Promise<boolean> {
return await this.todoRepository.deleteById(id);
@param.path.number('id')
async deleteTodo(id: number): Promise<boolean> {
return await this.todoRepo.deleteById(id);
}
}
17 changes: 10 additions & 7 deletions packages/example-getting-started/src/models/todo.model.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,29 @@
// Copyright IBM Corp. 2017,2018. All Rights Reserved.
// Node module: @loopback/example-getting-started
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT

import {Entity, property, model} from '@loopback/repository';
import {SchemaObject} from '@loopback/openapi-spec';

@model()
export class Todo extends Entity {
@property({
type: 'number',
id: true,
})
id?: number;

@property({
type: 'string',
required: true,
})
title: string;

@property() desc?: string;
@property({
type: 'string',
})
desc?: string;

@property() isComplete: boolean;
@property({
type: 'boolean',
})
isComplete: boolean;

getId() {
return this.id;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
// Copyright IBM Corp. 2017,2018. All Rights Reserved.
// Node module: @loopback/example-getting-started
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT

import {createClientForHandler, expect, supertest} from '@loopback/testlab';
import {RestServer} from '@loopback/rest';
import {TodoApplication} from '../../src/application';
Expand Down Expand Up @@ -48,6 +43,21 @@ describe('Application', () => {
.expect(200, todo);
});

it('replaces the todo by ID', async () => {
const todo = await givenTodoInstance();
const updatedTodo = givenTodo({
title: 'DO SOMETHING AWESOME',
desc: 'It has to be something ridiculous',
isComplete: true,
});
await client
.put(`/todo/${todo.id}`)
.send(updatedTodo)
.expect(200);
const result = await todoRepo.findById(todo.id);
expect(result).to.containEql(updatedTodo);
});

it('updates the todo by ID ', async () => {
const todo = await givenTodoInstance();
const updatedTodo = givenTodo({
Expand Down
7 changes: 1 addition & 6 deletions packages/example-getting-started/test/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
// Copyright IBM Corp. 2017,2018. All Rights Reserved.
// Node module: @loopback/example-getting-started
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT

import {Todo} from '../src/models/index';

/*
Expand All @@ -13,7 +8,7 @@ import {Todo} from '../src/models/index';
way to reduce duplication.
Other tips:
- Using the super awesome Partial<T> type in conjunction with Object.assign
means you can:
* customize the object you get back based only on what's important
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
// Copyright IBM Corp. 2017,2018. All Rights Reserved.
// Node module: @loopback/example-getting-started
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT

import {expect} from '@loopback/testlab';
import {TodoController} from '../../../src/controllers';
import {TodoRepository} from '../../../src/repositories';
Expand Down Expand Up @@ -45,20 +40,36 @@ describe('TodoController', () => {
let aChangedTodo: Todo;
let aTodoList: Todo[];

const noError = 'No error was thrown!';

beforeEach(resetRepositories);
describe('createTodo', () => {
it('creates a Todo', async () => {
create.resolves(aTodoWithId);
const result = await controller.create(aTodo);
const result = await controller.createTodo(aTodo);
expect(result).to.eql(aTodoWithId);
sinon.assert.calledWith(create, aTodo);
});

it('throws if the payload is missing a title', async () => {
const todo = givenTodo();
delete todo.title;
try {
await controller.createTodo(todo);
} catch (err) {
expect(err).to.match(/title is required/);
sinon.assert.notCalled(create);
return;
}
// Repository stub should not have been called!
throw new Error(noError);
});
});

describe('findTodoById', () => {
it('returns a todo if it exists', async () => {
findById.resolves(aTodoWithId);
expect(await controller.findById(aTodoWithId.id as number)).to.eql(
expect(await controller.findTodoById(aTodoWithId.id as number)).to.eql(
aTodoWithId,
);
sinon.assert.calledWith(findById, aTodoWithId.id);
Expand All @@ -68,23 +79,33 @@ describe('TodoController', () => {
describe('findTodos', () => {
it('returns multiple todos if they exist', async () => {
find.resolves(aTodoList);
expect(await controller.find({})).to.eql(aTodoList);
expect(await controller.findTodos()).to.eql(aTodoList);
sinon.assert.called(find);
});

it('returns empty list if no todos exist', async () => {
const expected: Todo[] = [];
find.resolves(expected);
expect(await controller.find({})).to.eql(expected);
expect(await controller.findTodos()).to.eql(expected);
sinon.assert.called(find);
});
});

describe('replaceTodo', () => {
it('successfully replaces existing items', async () => {
replaceById.resolves(true);
expect(
await controller.replaceTodo(aTodoWithId.id as number, aChangedTodo),
).to.eql(true);
sinon.assert.calledWith(replaceById, aTodoWithId.id, aChangedTodo);
});
});

describe('updateTodo', () => {
it('successfully updates existing items', async () => {
updateById.resolves(true);
expect(
await controller.updateById(aTodoWithId.id as number, aChangedTodo),
await controller.updateTodo(aTodoWithId.id as number, aChangedTodo),
).to.eql(true);
sinon.assert.calledWith(updateById, aTodoWithId.id, aChangedTodo);
});
Expand All @@ -93,7 +114,7 @@ describe('TodoController', () => {
describe('deleteTodo', () => {
it('successfully deletes existing items', async () => {
deleteById.resolves(true);
expect(await controller.deleteById(aTodoWithId.id as number)).to.eql(
expect(await controller.deleteTodo(aTodoWithId.id as number)).to.eql(
true,
);
sinon.assert.calledWith(deleteById, aTodoWithId.id);
Expand Down

0 comments on commit 99bb50e

Please sign in to comment.