Skip to content

Commit

Permalink
merge(mongo-sample): merge mongo-sample branch to master
Browse files Browse the repository at this point in the history
* fix(actions): update GitHub actions

Actions are now 1-to-1 mapped for each application to run its own tests

* feat(mongo): add test suite for mongo

This suite covers a basic CRUD application for mongodb and NestJS

Related to #3
  • Loading branch information
jmcdo29 authored Nov 18, 2019
1 parent b873c7f commit 4fe628b
Show file tree
Hide file tree
Showing 22 changed files with 837 additions and 18 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
name: Node CI
name: Complex Sample

on:
on:
pull_request:
branches:
branches:
- 'master'
push:

Expand All @@ -14,7 +14,6 @@ jobs:
strategy:
matrix:
node-version: [10.x, 12.x]
sample-name: [complex-sample, simple-sample, typeorm-sample, typeorm-graphql-sample]

steps:
- uses: actions/checkout@v1
Expand All @@ -25,6 +24,6 @@ jobs:
- name: npm install
run: npm ci
- name: npm test
run: npm test -- ${{ matrix.sample-name }}
run: npm test -- complex-sample
env:
CI: true
29 changes: 29 additions & 0 deletions .github/workflows/mongo.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: Mongo Sample

on:
pull_request:
branches:
- 'master'
push:

jobs:
test:

runs-on: ubuntu-latest

strategy:
matrix:
node-version: [10.x, 12.x]

steps:
- uses: actions/checkout@v1
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- name: npm install
run: npm ci
- name: npm test
run: npm test -- mongo-sample
env:
CI: true
29 changes: 29 additions & 0 deletions .github/workflows/simple.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: Simple Sample

on:
pull_request:
branches:
- 'master'
push:

jobs:
test:

runs-on: ubuntu-latest

strategy:
matrix:
node-version: [10.x, 12.x]

steps:
- uses: actions/checkout@v1
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- name: npm install
run: npm ci
- name: npm test
run: npm test -- simple-sample
env:
CI: true
29 changes: 29 additions & 0 deletions .github/workflows/typeorm-graphql.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: TypeORM GraphQL Sample

on:
pull_request:
branches:
- 'master'
push:

jobs:
test:

runs-on: ubuntu-latest

strategy:
matrix:
node-version: [10.x, 12.x]

steps:
- uses: actions/checkout@v1
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- name: npm install
run: npm ci
- name: npm test
run: npm test -- typeorm-graphql-sample
env:
CI: true
29 changes: 29 additions & 0 deletions .github/workflows/typeorm.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: TypeORM Sample

on:
pull_request:
branches:
- 'master'
push:

jobs:
test:

runs-on: ubuntu-latest

strategy:
matrix:
node-version: [10.x, 12.x]

steps:
- uses: actions/checkout@v1
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- name: npm install
run: npm ci
- name: npm test
run: npm test -- typeorm-sample
env:
CI: true
6 changes: 0 additions & 6 deletions Contributing.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,6 @@ Or run tests in watch mode:
npm run test:watch
```

To update Jest snapshots:

```bash
npm run test:jest -- -u
```

**Don’t forget to add tests and update documentation for your changes.**

**Please update npm lock file (`package-lock.json`) if you add or update dependencies.**
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ This is not necessarily the Nest canonical way to test an application, nor is it
1. `git clone https://github.com/jmcdo29/testing-nestjs.git`
2. `cd testing-nestjs/<folderName>`
3. `npm install` OR `yarn add`
4. `npm run test` OR `npm run test:e2e` OR `yarn test` OR `yarn test:e2e`
4. `npm run test` OR `yarn test`

## Contributing

Expand Down
11 changes: 11 additions & 0 deletions apps/mongo-sample/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<p align="center">
<img src="./testCoverage.png"/>
</p>

# Mongo Sample

Welcome to the example of using MongoDB with Nest and running tests! My _second favorite_ topic! I decided to go with a very simple CRUD application for a single database object, but if there is enough of a demand I will extend this out to a larger repository with more objects and options. Not much else to say other than I hope this is found as helpful to the community!

## Side Note

For this application, I have added a side package called `@golevelup/nestjs-testing` (name subject to change) to help with mocking Repository objects without needing to create the entire mock on your own. I did run into a few issues with the library this time around, namely matching mocks to mocks, so that's something I'll need to work on updating in the future. In the meantime, enjoy the tests!
4 changes: 3 additions & 1 deletion apps/mongo-sample/src/app.module.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { Module } from '@nestjs/common';
import { MongooseModule } from '@nestjs/mongoose';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { CatModule } from './cat/cat.module';

@Module({
imports: [],
imports: [MongooseModule.forRoot(process.env.MONGODB_URI), CatModule],
controllers: [AppController],
providers: [AppService],
})
Expand Down
168 changes: 168 additions & 0 deletions apps/mongo-sample/src/cat/cat.controller.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
import { createMock, DeepMocked } from '@golevelup/nestjs-testing';
import { Test, TestingModule } from '@nestjs/testing';
import { CatController } from './cat.controller';
import { CatDTO } from './cat.dto';
import { CatService } from './cat.service';
import { Cat } from './interfaces/cat.interface';

describe('Cat Controller', () => {
let controller: CatController;
let service: CatService;

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
controllers: [CatController],
// If you've looked at the complex sample you'll notice that these functions
// are a little bit more in depth using mock implementation
// to give us a little bit more control and flexibility in our tests
// this is not necessary, but can sometimes be helpful in a test scenario
providers: [
{
provide: CatService,
useValue: {
getAll: jest
.fn()
.mockResolvedValue([
{ name: 'Test Cat 1', breed: 'Test Breed 1', age: 4 },
{ name: 'Test Cat 2', breed: 'Test Breed 2', age: 3 },
{ name: 'Test Cat 3', breed: 'Test Breed 3', age: 2 },
]),
getOne: jest.fn().mockImplementation((id: string) =>
Promise.resolve({
name: 'Test Cat 1',
breed: 'Test Breed 1',
age: 4,
_id: id,
}),
),
getOneByName: jest
.fn()
.mockImplementation((name: string) =>
Promise.resolve({ name, breed: 'Test Breed 1', age: 4 }),
),
insertOne: jest
.fn()
.mockImplementation((cat: CatDTO) =>
Promise.resolve({ _id: 'a uuid', ...cat }),
),
updateOne: jest
.fn()
.mockImplementation((cat: CatDTO) =>
Promise.resolve({ _id: 'a uuid', ...cat }),
),
deleteOne: jest.fn().mockResolvedValue({ deleted: true }),
},
},
],
}).compile();

controller = module.get<CatController>(CatController);
service = module.get<CatService>(CatService);
});

it('should be defined', () => {
expect(controller).toBeDefined();
});

describe('getCats', () => {
it('should get an array of cats', () => {
expect(controller.getCats()).resolves.toEqual([
{
name: 'Test Cat 1',
breed: 'Test Breed 1',
age: 4,
},
{
name: 'Test Cat 2',
breed: 'Test Breed 2',
age: 3,
},
{
name: 'Test Cat 3',
breed: 'Test Breed 3',
age: 2,
},
]);
});
});
describe('getById', () => {
it('should get a single cat', () => {
expect(controller.getById('a strange id')).resolves.toEqual({
name: 'Test Cat 1',
breed: 'Test Breed 1',
age: 4,
_id: 'a strange id',
});
expect(controller.getById('a different id')).resolves.toEqual({
name: 'Test Cat 1',
breed: 'Test Breed 1',
age: 4,
_id: 'a different id',
});
});
});
describe('getByName', () => {
it('should get a cat back', async () => {
expect(controller.getByName('Ventus')).resolves.toEqual({
name: 'Ventus',
breed: 'Test Breed 1',
age: 4,
});
// using the really cool @golevelup/nestjs-testing module's utility function here
// otherwise we need to pass `as any` or we need to mock all 54+ attributes of Document
const aquaMock = createMock<Cat>({
name: 'Aqua',
breed: 'Maine Coon',
age: 5,
});
const getByNameSpy = jest
.spyOn(service, 'getOneByName')
.mockResolvedValueOnce(aquaMock);
const getResponse = await controller.getByName('Aqua');
expect(getResponse).toEqual(aquaMock);
expect(getByNameSpy).toBeCalledWith('Aqua');
});
});
describe('newCat', () => {
it('should create a new cat', () => {
const newCatDTO: CatDTO = {
name: 'New Cat 1',
breed: 'New Breed 1',
age: 4,
};
expect(controller.newCat(newCatDTO)).resolves.toEqual({
_id: 'a uuid',
...newCatDTO,
});
});
});
describe('updateCat', () => {
it('should update a new cat', () => {
const newCatDTO: CatDTO = {
name: 'New Cat 1',
breed: 'New Breed 1',
age: 4,
};
expect(controller.updateCat(newCatDTO)).resolves.toEqual({
_id: 'a uuid',
...newCatDTO,
});
});
});
describe('deleteCat', () => {
it('should return that it deleted a cat', () => {
expect(controller.deleteCat('a uuid that exists')).resolves.toEqual({
deleted: true,
});
});
it('should return that it did not delete a cat', () => {
const deleteSpy = jest
.spyOn(service, 'deleteOne')
.mockResolvedValueOnce({ deleted: false });
expect(
controller.deleteCat('a uuid that does not exist'),
).resolves.toEqual({ deleted: false });
expect(deleteSpy).toBeCalledWith('a uuid that does not exist');
});
});
});
Loading

0 comments on commit 4fe628b

Please sign in to comment.