Skip to content
Permalink
Browse files

Add feature tags (#17)

* Add function to jest to auto-refresh when test files changed.

* Add API for getting a quote by its ID.

* Change 'sample' folder to 'samples' and update gitignore and contributing files.

* Add web API for getting list of 'tags'.

* Remove duplicate web API in 'routes' for getting a quote by its ID.

* Rename 'samples' folder back to 'sample'.
  • Loading branch information
marekdano authored and lukePeavey committed Jan 28, 2020
1 parent 08002ac commit d8a2e1eff4f852c2c81b01edc25d11e56efcce19
Showing with 148 additions and 12 deletions.
  1. +2 −2 .gitignore
  2. +28 −7 README.md
  3. +8 −0 __tests__/integration.test.js
  4. +1 −1 contributing.md
  5. +58 −0 data/sample/tags.json
  6. +14 −1 scripts/seedDatabase.js
  7. +17 −0 src/controllers/tags/listTags.js
  8. +12 −0 src/models/Tags.js
  9. +2 −1 src/models/index.js
  10. +6 −0 src/routes.js
@@ -8,8 +8,8 @@

docs/
private/
data/
!data/samples
data/*
!data/sample

# misc
.DS_Store
@@ -61,7 +61,7 @@ https://api.quotable.io/quotes
{
// The number of quotes returned by this request
count: number,
// The total number or quotes matching this request
// The total number of quotes matching this request
totalCount: number
// The index of the last quote returned. When paginating through results,
// this value would be used as the `skip` parameter when requesting the next
@@ -118,12 +118,12 @@ https://api.quotable.io/authors
{
// The number of authors return by this request.
count: number,
// The total number or authors matching this request.
totalCount: number
// The total number of authors matching this request.
totalCount: number,
// The index of the last item returned. When paginating through results,
// this value would be used as the `skip` parameter when requesting the next
// "page" of results.
lastItemIndex: number
lastItemIndex: number,
// The array of authors
results: {_id: string, name: string, quoteCount: string}[]
}
@@ -136,7 +136,7 @@ Get all quotes a specific author
#### Request

```http
https://api.quotable.io/author/:id
https://api.quotable.io/authors/:id
```

#### Response
@@ -145,14 +145,35 @@ https://api.quotable.io/author/:id
{
_id: string,
// The author name
name: number,
name: string,
// The total number of quotes by this author
quoteCount: number
quoteCount: number,
// The array of quotes by this author
quotes: {_id: string, content: string, author: string}[]
}
```

### Get Tags

Get list of available tags

#### Request

```http
https://api.quotable.io/tags
```

#### Response

```ts
{
// The number of all tags by this request
count: number,
// The array of tags
results: {_id: string, name: string}[]
}
```

## Usage

**Get a random quote (fetch)**
@@ -84,3 +84,11 @@ describe('GET /quotes/:id', () => {
expect(response.type).toBe('application/json')
})
})

describe('GET /tags', () => {
it('Request completed successfully', async () => {
const response = await request(app).get('/tags')
expect(response.status).toBe(200)
expect(response.type).toBe('application/json')
})
})
@@ -70,7 +70,7 @@ $ npm run install
This will populate your database with the sample data included in the repository.

```shell
$ npm run database:seed
$ npm run database:seed data/sample
```

**4. Start the Server**
@@ -0,0 +1,58 @@
[
{
"_id": "lmOF86Cv",
"name": "famous-quotes"
},
{
"_id": "7HjmNmOIE",
"name": "life"
},
{
"_id": "ZY0PgehL1",
"name": "friendship"
},
{
"_id": "rYJgbbjOK",
"name": "science"
},
{
"_id": "ZBOfkMBWc",
"name": "technology"
},
{
"_id": "M97I8NOsF",
"name": "inspirational"
},
{
"_id": "PnbpDlRlC",
"name": "motivational"
},
{
"_id": "637eDKoGB",
"name": "literature"
},
{
"_id": "fqgdQmYNk",
"name": "art"
},
{
"_id": "BPCApygPx",
"name": "business"
},
{
"_id": "CkRvna8Tz",
"name": "love"
},
{
"_id": "AK9UKVnIm",
"name": "success"
},
{
"_id": "GADjjdrcd",
"name": "religion"
},
{
"_id": "8mV7Dhqt3",
"name": "social-justice"
}
]
@@ -7,6 +7,7 @@ const fs = require('fs')
const path = require('path')
const Quotes = require('../src/models/Quotes')
const Authors = require('../src/models/Authors')
const Tags = require('../src/models/Tags')

// Seeds the database with data from `quotes.json` and `authors.json`.
// This should be run when setting up a new database, or after modifying
@@ -17,6 +18,7 @@ console.log('==> Seeding database...')
const [dataDirectory] = process.argv.slice(2)
let _quotes
let _authors
let _tags

try {
_quotes = fs.readFileSync(
@@ -25,6 +27,9 @@ try {
_authors = fs.readFileSync(
path.join(__dirname, '../', dataDirectory, 'authors.json')
)
_tags = fs.readFileSync(
path.join(__dirname, '../', dataDirectory, 'tags.json')
)
} catch (error) {
console.log('==> [ERROR] Invalid data directory')
process.exit()
@@ -46,10 +51,18 @@ async function seedAuthors() {
console.log(`==> Added ${result.insertedCount} documents to Authors`)
}

async function seedTags() {
// Remove any existing data from the collection
await Tags.collection.deleteMany({})
// Import the items from authors.json
const result = await Tags.collection.insertMany(JSON.parse(_tags))
console.log(`==> Added ${result.insertedCount} documents to Tags`)
}

mongoose
.connect(process.env.MONGODB_URI, { useNewUrlParser: true })
.then(() => {
Promise.all([seedQuotes(), seedAuthors()]).then(() => {
Promise.all([seedQuotes(), seedAuthors(), seedTags()]).then(() => {
console.log('==> Finished!')
process.exit()
})
@@ -0,0 +1,17 @@
const Tags = require('../../models/Tags')

/**
* Get list of tags from the database.
*/
module.exports = async function listTags(req, res, next) {
try {
const results = await Tags.find({}).select('name')

res.status(200).json({
count: results.length,
results,
})
} catch (error) {
return next(error)
}
}
@@ -0,0 +1,12 @@
const { Schema, model } = require('mongoose')
const shortid = require('shortid')

const TagSchema = new Schema({
_id: { type: String, default: shortid.generate },
name: { type: String, required: true },
})

// To support full text search
TagSchema.index({ name: 'text' })

module.exports = model('Tag', TagSchema)
@@ -1,4 +1,5 @@
const Quotes = require('./Quotes')
const Authors = require('./Authors')
const Tags = require('./Tags')

module.exports = { Quotes, Authors }
module.exports = { Quotes, Authors, Tags }
@@ -4,6 +4,7 @@ const getQuoteById = require('./controllers/quotes/getQuoteById')
const randomQuote = require('./controllers/quotes/randomQuote')
const listAuthors = require('./controllers/authors/listAuthors')
const getAuthorById = require('./controllers/authors/getAuthorById')
const listTags = require('./controllers/tags/listTags')

const router = Router()

@@ -20,4 +21,9 @@ router.get('/random', randomQuote)
router.get('/authors', listAuthors)
router.get('/authors/:id', getAuthorById)

/**------------------------------------------------
** Tags
**-----------------------------------------------*/
router.get('/tags', listTags)

module.exports = router

0 comments on commit d8a2e1e

Please sign in to comment.
You can’t perform that action at this time.