Skip to content

Commit

Permalink
Merge pull request #179 from mbland/add-api-for-search
Browse files Browse the repository at this point in the history
added api for searching and Mike's refactor for search helpers
  • Loading branch information
mbland authored Apr 23, 2018
2 parents cd4c067 + 1167730 commit 0082ed0
Show file tree
Hide file tree
Showing 4 changed files with 130 additions and 4 deletions.
16 changes: 16 additions & 0 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,22 @@ function assembleApiRouter(linkDb, logger) {
req.params.link, req.user.id))
})

router.get('/search', (req, res) => {
var search

if (req.query.link) {
search = linkDb.searchShortLinks(req.query.link)
} else if (req.query.target) {
search = linkDb.searchTargetLinks(req.query.target)
} else {
res.status(400)
}

search.then(results => {
res.status(200).json(results)
}).catch(errorHandler(req, res, logger, 'json'))
})

router.all('/*', (req, res) => res.sendStatus(400))

return router
Expand Down
21 changes: 20 additions & 1 deletion lib/link-db.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ function rethrowError(message) {
function LinkDb(client, logger) {
this.client = client
this.logger = logger
this.fetchLinkData = links => this.client.fetchLinkData(links)
}

LinkDb.prototype.userExists = function(user) {
Expand Down Expand Up @@ -71,7 +72,7 @@ LinkDb.prototype.createLink = function(link, target, user) {
LinkDb.prototype.getOwnedLinks = function(user) {
return this.userExists(user)
.then(() => this.client.getOwnedLinks(user))
.then(links => this.client.fetchLinkData(links))
.then(this.fetchLinkData)
}

LinkDb.prototype.getLinkIfOwner = function(link, user) {
Expand All @@ -86,8 +87,26 @@ LinkDb.prototype.getLinkIfOwner = function(link, user) {
})
}

LinkDb.prototype.searchShortLinks = function(searchString) {
return this.client.searchShortLinks(searchString)
.then(this.fetchLinkData)
}

LinkDb.prototype.searchTargetLinks = function(searchString) {
return this.client.searchTargetLinks(searchString)
.then(targetUrlToCustomLinks => {
var result = {}
const promises = Object.keys(targetUrlToCustomLinks)
.reduce((promises, target) => {
promises.push(this.fetchLinkData(targetUrlToCustomLinks[target])
.then(linkInfo => {
result[target] = linkInfo
}))
return promises
}, [])
return Promise.all(promises)
.then(() => result)
})
}

LinkDb.prototype.updateProperty = function(link, user, property, value) {
Expand Down
65 changes: 65 additions & 0 deletions tests/server/app-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,71 @@ describe('assembleApp', function() {
})
})
})

describe('/search', function() {
var searchShortLinks
var searchTargetLinks

beforeEach(function() {
searchShortLinks = sinon.stub(linkDb, 'searchShortLinks')
searchTargetLinks = sinon.stub(linkDb, 'searchTargetLinks')
})

afterEach(function() {
searchShortLinks.restore()
searchTargetLinks.restore()
})

it('returns all related links for the matched short link', function() {
// Not including the owner, though it would be normally.
var matchingLinks = [
'/bar', '/foobar'
]

searchShortLinks.withArgs('bar')
.returns(Promise.resolve(matchingLinks))

return request(app)
.get('/api/search?link=bar')
.set('cookie', sessionCookie)
.expect(200)
.expect('Content-Type', 'application/json; charset=utf-8')
.then(function(res) {
expect(res.body).to.eql(matchingLinks)
})
})

it('returns all related links for the matched target link', function() {
// Not including the owner, though it would be normally.
var mblandLinks = [
{ link: '/foo', target: LINK_TARGET, clicks: 27 },
{ link: '/bar', target: LINK_TARGET, clicks: 28 },
{ link: '/baz', target: LINK_TARGET, clicks: 29 }
]

var mblandLinksObject = { 'https://mbland.com': mblandLinks}

searchTargetLinks.withArgs('mbland')
.returns(Promise.resolve(mblandLinksObject))

return request(app)
.get('/api/search?target=mbland')
.set('cookie', sessionCookie)
.expect(200)
.expect('Content-Type', 'application/json; charset=utf-8')
.then(function(res) {
expect(res.body).to.eql(mblandLinksObject)
})
})

it('returns error when link or target is not provided as query param',
function() {
return request(app)
.get('/api/search')
.set('cookie', sessionCookie)
.expect(400)
})
})
})

describe('sessionParams', function() {
Expand Down
32 changes: 29 additions & 3 deletions tests/server/link-db-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -298,18 +298,44 @@ describe('LinkDb', function() {
.should.be.rejectedWith('/foo is owned by msb')
})
})

describe('searchTargetLinks', function() {
it('returns all links', () => {
const mblandLinks = [
{
link: '/baz',
owner: 'mbland'
},
{
link: '/bar',
owner: 'mbland'
},
{
link: '/foo',
owner: 'mbland'
}
]
const akashLinks = [
{
link: '/test',
owner: 'akash'
}
]

stubClientMethod('searchTargetLinks')
.withArgs('')
.returns(Promise.resolve({
'https://mike-bland.com/': ['/baz', '/bar', '/foo'],
'https://akash.com': ['/test']
}))
stubClientMethod('fetchLinkData')
.withArgs(['/baz', '/bar', '/foo'])
.returns(Promise.resolve(mblandLinks))
.withArgs(['/test'])
.returns(Promise.resolve(akashLinks))
return linkDb.searchTargetLinks('').should.become({
'https://mike-bland.com/': ['/baz', '/bar', '/foo'],
'https://akash.com': ['/test']
'https://mike-bland.com/': mblandLinks,
'https://akash.com': akashLinks
})
})
})
Expand Down

0 comments on commit 0082ed0

Please sign in to comment.