Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Add support for hashtag conversion #35

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .github/workflows/run-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,4 @@ jobs:
run: npm run lint

- name: Run tests
env:
MEDIA_ENDPOINT_URL: http://localhost:3334/
ROOT_URL: http://localhost:4444/
run: npm test
3 changes: 3 additions & 0 deletions app.arc
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ logs
expires TTL
contacts
nickname *String
hashtag-replacements
hashtag *String
replacement String

@indexes
posts
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"description": "Personal website Micropub server",
"scripts": {
"start": "PORT=3333 arc sandbox",
"test": "NODE_ENV=testing PORT=3334 tape test/*-test.js",
"test": "NODE_ENV=testing PORT=3334 MEDIA_ENDPOINT_URL=http://localhost:3334/ ROOT_URL=http://localhost:4444/ tape test/*-test.js",
"lint": "standard"
},
"dependencies": {
Expand Down
37 changes: 37 additions & 0 deletions src/http/get-micropub/hashtag-replacement.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
const arc = require('@architect/functions')

async function toResponse (items) {
const inner = items.reduce(function (result, item, _) {
result[item.hashtag] = item.replacement
return result
}, {})

return {
replacements: inner
}
}

async function hashtagReplacements (filter) {
const data = await arc.tables()
const table = data['hashtag-replacements']
if (filter) {
const results = await table.scan({
ScanFilter: {
hashtag: {
ComparisonOperator: 'BEGINS_WITH',
AttributeValueList: [
`#${filter}`
]
}
}
})
return await toResponse(results.Items)
} else {
const results = await table.scan({})
return await toResponse(results.Items)
}
}

module.exports = {
hashtagReplacements
}
3 changes: 3 additions & 0 deletions src/http/get-micropub/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const config = require('./config')
const query = require('./query')
const { setWebmentions } = require('./webmentions')
const { setContexts } = require('./contexts')
const { hashtagReplacements } = require('./hashtag-replacement')

async function getPost (params, scopes) {
const url = params.url.replace(process.env.ROOT_URL, '')
Expand Down Expand Up @@ -103,6 +104,8 @@ exports.handler = async function http (req) {
return await { 'post-types': config.postTypes }
case 'contact':
return await config.contact(params.filter)
case 'hashtag-replacement':
return await hashtagReplacements(params.filter)
}
}
return {
Expand Down
104 changes: 104 additions & 0 deletions test/get-micropub-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,29 @@ const fetch = require('node-fetch')
const { isValidURL } = require('../src/shared/utils')
const micropubUrl = 'http://localhost:3334/micropub'

async function addReplacements () {
const data = await arc.tables()
data['hashtag-replacements'].put({
hashtag: '#IndieWeb',
replacement: 'indieweb'
})
data['hashtag-replacements'].put({
hashtag: '#IndieAuth',
replacement: 'indieauth'
})
data['hashtag-replacements'].put({
hashtag: '#TechNott',
replacement: 'tech-nottingham'
})
}

async function removeReplacements () {
const data = await arc.tables()
await data['hashtag-replacements'].delete({ hashtag: '#IndieWeb' })
await data['hashtag-replacements'].delete({ hashtag: '#IndieAuth' })
await data['hashtag-replacements'].delete({ hashtag: '#TechNott' })
}

test('start', async t => {
t.plan(1)
const result = await sandbox.start()
Expand Down Expand Up @@ -82,6 +105,87 @@ test('q=post-types returns a valid response', async t => {
t.ok(body['post-types'].length > 0, 'post-types is not empty')
})

test('q=hashtag-replacement returns HTTP 200', async t => {
const response = await fetch(`${micropubUrl}?q=hashtag-replacement`)
t.ok(response.status === 200, 'hashtag-replacement should be present')
})

test('q=hashtag-replacement returns JSON', async t => {
const response = await fetch(`${micropubUrl}?q=hashtag-replacement`)
t.ok(response.headers.get('content-type') === 'application/json', 'hashtag-replacement should be UTF-8 JSON')
})

test('q=hashtag-replacement returns empty object by default', async t => {
const response = await fetch(`${micropubUrl}?q=hashtag-replacement`)
const body = await response.json()
t.ok(Object.keys(body.replacements).length === 0, 'hashtag-replacement should not have any values')
})

test('q=hashtag-replacement returns replacements when present', async t => {
await addReplacements()

const response = await fetch(`${micropubUrl}?q=hashtag-replacement`)
const body = await response.json()

const expected = {
replacements: {
'#IndieAuth': 'indieauth',
'#IndieWeb': 'indieweb',
'#TechNott': 'tech-nottingham'
}
}

t.deepEqual(body, expected)

t.teardown(async function () {
await removeReplacements()
})
})

test('q=hashtag-replacement returns empty replacements when filtered, but not present', async t => {
const response = await fetch(`${micropubUrl}?q=hashtag-replacement&filter=indie`)
const body = await response.json()

const expected = {
replacements: {}
}

t.deepEqual(body, expected)
})

test('q=hashtag-replacement returns filtered replacements when filtered and present', async t => {
await addReplacements()

const response = await fetch(`${micropubUrl}?q=hashtag-replacement&filter=Indie`)
const body = await response.json()

const expected = {
replacements: {
'#IndieAuth': 'indieauth',
'#IndieWeb': 'indieweb'
}
}

t.deepEqual(body, expected)

t.teardown(async function () {
await removeReplacements()
})
})

test('q=hashtag-replacement filtering is case sensitive', async t => {
await addReplacements()

const response = await fetch(`${micropubUrl}?q=hashtag-replacement&filter=INDIE`)
const body = await response.json()

t.ok(Object.keys(body.replacements).length === 0, 'hashtag-replacement should not have any values')

t.teardown(async function () {
await removeReplacements()
})
})

test('end', async t => {
t.plan(1)
const result = await sandbox.end()
Expand Down