Skip to content

Commit

Permalink
♻️ Improve code and add unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
hirsch committed Jun 7, 2019
1 parent 9f0522e commit c3a3c39
Show file tree
Hide file tree
Showing 10 changed files with 130 additions and 20 deletions.
25 changes: 20 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ How does it work? Just create a factory for your entities (models) and a seed sc

## ❯ Installation

Before using this TypeORM extension please read the [TypeORM Getting Started](https://typeorm.io/#/) documentation. This explains how to setup a TypeORM project.

You can install our extension with `npm` or `yarn`.

```bash
npm i typeorm-seeding
```
Expand All @@ -43,6 +47,18 @@ or with yarn
yarn add typeorm-seeding
```

### Configuration

To configure the path to your seeds and factories change the TypeORM config file(ormconfig.js or ormconfig.json).

```JavaScript
module.exports = {
...
seeds: ['seeds/**/*.seed.ts'],
factories: ['factories/**/*.factory.ts'],
}
```

![divider](./w3tec-divider.png)

## ❯ Writing Seeders
Expand Down Expand Up @@ -171,11 +187,10 @@ Now you are able to execute your seeds with this command `npm run seed`.

### CLI Options

| Option | Default | Description |
| ---------------------- | -------------------- | --------------------------------------------- |
| `--config` or `--c` | `ormconfig.js` | Path to the typeorm config file (json or js). |
| `--seeds` or `--s` | `database/seeds` | Directory where seeds are. |
| `--factories` or `--f` | `database/factories` | Directory where enity factories are. |
| Option | Default | Description |
| ------------------ | -------------- | --------------------------------------------- |
| `--class` or `--c` | null | Option to specify a specific seeder class to run individually |
| `--config` | `ormconfig.js` | Path to the typeorm config file (json or js). |

## ❯ Example

Expand Down
8 changes: 0 additions & 8 deletions examples/ormconfig.js

This file was deleted.

1 change: 1 addition & 0 deletions src/commands/seed.command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export class SeedCommand implements yargs.CommandModule {
describe: 'Path to the typeorm config file (json or js).',
})
.option('class', {
alias: 'c',
describe: 'Specific seed class to run.',
})
}
Expand Down
66 changes: 66 additions & 0 deletions src/entity-factory.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { EntityFactory } from './entity-factory'

describe('make', () => {
// tslint:disable-next-line
class User {
constructor(public name: string) {}
}
// tslint:disable-next-line
class Pet {
constructor(public name: string, public user: User) {}
}

test('Should make a new entity', async () => {
const mockUserFactory = jest.fn()
const userFactory = new EntityFactory('User', User, mockUserFactory)
mockUserFactory.mockReturnValue(new User('Steve'))

const newUser = await userFactory.make()

expect(newUser.name).toBe('Steve')
})

test('Should override the enitys props', async () => {
const mockUserFactory = jest.fn()
const userFactory = new EntityFactory('User', User, mockUserFactory)
mockUserFactory.mockReturnValue(new User('Steve'))

const newUser = await userFactory.make({ name: 'Tony' })

expect(newUser.name).toBe('Tony')
})

test('Should call the nested entity factories', async () => {
const mockUserFactory = jest.fn()
const userFactory = new EntityFactory('User', User, mockUserFactory)

const mockPetFactory = jest.fn()
const petFactory = new EntityFactory('Pet', Pet, mockPetFactory)

mockUserFactory.mockReturnValue({
name: 'Pepper',
})

mockPetFactory.mockReturnValue({
name: 'Bunny',
user: userFactory,
})

const newPet = await petFactory.make()

expect(newPet.name).toBe('Bunny')
expect(newPet.user.name).toBe('Pepper')
})

test('Should call the map function', async () => {
const mockUserFactory = jest.fn()
const userFactory = new EntityFactory('User', User, mockUserFactory)
mockUserFactory.mockReturnValue(new User('Steve'))
const mockMap = jest.fn()

const newUsers = await userFactory.map(mockMap).makeMany(2)

expect(newUsers.length).toBe(2)
expect(mockMap).toBeCalledTimes(2)
})
})
4 changes: 3 additions & 1 deletion src/entity-factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ export class EntityFactory<Entity, Settings> {
}

for (const key in overrideParams) {
entity[key] = overrideParams[key]
if (overrideParams.hasOwnProperty(key)) {
entity[key] = overrideParams[key]
}
}

return entity
Expand Down
10 changes: 10 additions & 0 deletions src/helpers.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { times } from './helpers'

describe('times', () => {
test('Should call the func 2 times ', async () => {
const result = await times<string>(2, async () => 'a')

expect(result.length).toBe(2)
expect(result).toStrictEqual(['a', 'a'])
})
})
3 changes: 1 addition & 2 deletions src/typeorm-seeding.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import 'reflect-metadata'
import { Connection, ObjectType, ConnectionOptions } from 'typeorm'
import { Connection, ObjectType } from 'typeorm'

import { EntityFactory } from './entity-factory'
import { EntityFactoryDefinition, Factory, FactoryFunction, SeederConstructor, Seeder } from './types'
import { getNameOfEntity } from './utils/factory.util'
import { getConnectionOptions, createConnection } from './connection'

// -------------------------------------------------------------------------
// Handy Exports
Expand Down
2 changes: 1 addition & 1 deletion src/utils/factory.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ describe('getNameOfClass', () => {
expect(getNameOfEntity(UserEntity)).toBe('UserEntity')
})
test('Passing UserEnity function should return the name of the function', () => {
function UserEntity() {}
const UserEntity = () => void 0
expect(getNameOfEntity(UserEntity)).toBe('UserEntity')
})
test('Passing undefinde as a enity-class should throw an error', () => {
Expand Down
26 changes: 26 additions & 0 deletions src/utils/file.util.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { loadFiles } from './file.util'
import * as path from 'path'
import * as glob from 'glob'

describe('loadFiles', () => {
let syncMock: jest.Mock
beforeEach(() => {
syncMock = jest.fn()
;(glob as any).sync = syncMock
syncMock.mockReturnValue(['fileA', 'fileB'])
})

test('Should return a flat array', () => {
const results = loadFiles(['path/to/files', 'other/path/to/files'])

expect(results.length).toBe(4)
expect(results[0]).toBe('fileA')
expect(results[1]).toBe('fileB')
})

test('Should call the sync method with the cwd path', () => {
const results = loadFiles(['path/to/files'])

expect(syncMock).toBeCalledWith(path.join(process.cwd(), 'path/to/files'))
})
})
5 changes: 2 additions & 3 deletions src/utils/file.util.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import glob from 'glob'
import * as glob from 'glob'
import * as path from 'path'

export const importFiles = (filePaths: string[]) => filePaths.forEach(require)

export const loadFiles = (filePattern: string[]): string[] => {
const filePaths: string[] = filePattern
return filePattern
.map(pattern => glob.sync(path.join(process.cwd(), pattern)))
.reduce((acc, filePath) => acc.concat(filePath), [])
return filePaths
}

0 comments on commit c3a3c39

Please sign in to comment.