test: more tests and fixes for database

This commit is contained in:
Nolan Lawson 2020-06-06 20:45:01 -07:00
parent 44d4398d24
commit c4c0e72a72
7 changed files with 210 additions and 3 deletions

View File

@ -0,0 +1,37 @@
import { ALL_EMOJI, basicAfterEach, basicBeforeEach } from './shared'
import Database from '../Database'
beforeEach(basicBeforeEach)
afterEach(basicAfterEach)
describe('getEmojiByGroup', () => {
test('basic test', async () => {
const db = new Database({ dataSource: ALL_EMOJI })
expect((await db.getEmojiByGroup(1)).length).toBe(20)
expect((await db.getEmojiByGroup(2)).length).toBe(9)
expect((await db.getEmojiByGroup(3)).length).toBe(20)
await db.delete()
})
test('ordering', async () => {
const db = new Database({ dataSource: ALL_EMOJI })
const emojis = await db.getEmojiByGroup(1)
const orderings = emojis.map(_ => _.order)
expect(orderings.slice().sort((a, b) => a < b ? -1 : 1)).toStrictEqual(orderings)
await db.delete()
})
test('errors', async () => {
const db = new Database({ dataSource: ALL_EMOJI })
await expect(() => db.getEmojiByGroup()).rejects.toThrow()
await expect(() => db.getEmojiByGroup('foo')).rejects.toThrow()
await expect(() => db.getEmojiByGroup(null)).rejects.toThrow()
await expect(() => db.getEmojiByGroup('')).rejects.toThrow()
await db.delete()
})
})

View File

@ -1,6 +1,9 @@
import allEmoji from 'emojibase-data/en/data.json'
import Database from '../Database'
import { pick } from 'lodash-es'
import { basicAfterEach, basicBeforeEach, ALL_EMOJI } from './shared'
import { basicAfterEach, basicBeforeEach, ALL_EMOJI, truncatedEmoji } from './shared'
const { Response } = fetch
beforeEach(basicBeforeEach)
afterEach(basicAfterEach)
@ -66,4 +69,103 @@ describe('getEmojiBySearchQuery', () => {
expect(await search('monk face')).toStrictEqual([])
await db.delete()
})
test('ordering', async () => {
const db = new Database({ dataSource: ALL_EMOJI })
const checkOrdering = emojis => {
expect(emojis.length).toBeGreaterThan(0)
const orderings = emojis.map(_ => _.order)
expect(orderings.slice().sort((a, b) => a < b ? -1 : 1)).toStrictEqual(orderings)
}
checkOrdering(await db.getEmojiBySearchQuery('face'))
checkOrdering(await db.getEmojiBySearchQuery('smile'))
checkOrdering(await db.getEmojiBySearchQuery('grin'))
checkOrdering(await db.getEmojiBySearchQuery('monkey'))
checkOrdering(await db.getEmojiBySearchQuery('cat'))
await db.delete()
})
test('emoticons', async () => {
const db = new Database({ dataSource: ALL_EMOJI })
expect((await db.getEmojiBySearchQuery(';)')).map(_ => _.annotation)).toStrictEqual([
'winking face'
])
expect((await db.getEmojiBySearchQuery(':*')).map(_ => _.annotation)).toStrictEqual([
'kissing face with closed eyes'
])
expect((await db.getEmojiBySearchQuery(':)')).map(_ => _.annotation)).toStrictEqual([
'slightly smiling face'
])
await db.delete()
})
test('apostrophes', async () => {
const emojiWithTwelveOclock = [
...truncatedEmoji,
allEmoji.find(_ => _.annotation === 'twelve oclock'),
allEmoji.find(_ => _.annotation === 'womans boot')
]
const EMOJI_WITH_APOS = 'http://localhost/apos.json'
fetch.get(EMOJI_WITH_APOS, () => new Response(JSON.stringify(emojiWithTwelveOclock), {
headers: { ETag: 'W/apos' }
}))
fetch.head(EMOJI_WITH_APOS, () => new Response(null, { headers: { ETag: 'W/apos' } }))
const db = new Database({ dataSource: EMOJI_WITH_APOS })
expect((await db.getEmojiBySearchQuery("o'clock")).map(_ => _.annotation)).toStrictEqual([
'twelve oclock'
])
expect((await db.getEmojiBySearchQuery('oclock')).map(_ => _.annotation)).toStrictEqual([
'twelve oclock'
])
expect((await db.getEmojiBySearchQuery("woman's boot")).map(_ => _.annotation)).toStrictEqual([
'womans boot'
])
expect((await db.getEmojiBySearchQuery('womans boot')).map(_ => _.annotation)).toStrictEqual([
'womans boot'
])
await db.delete()
})
test('colons', async () => {
const emoji = [
...truncatedEmoji,
allEmoji.find(_ => _.annotation === 'person: blond hair')
]
const EMOJI = 'http://localhost/apos.json'
fetch.get(EMOJI, () => new Response(JSON.stringify(emoji), {
headers: { ETag: 'W/blond' }
}))
fetch.head(EMOJI, () => new Response(null, { headers: { ETag: 'W/blond' } }))
const db = new Database({ dataSource: EMOJI })
expect((await db.getEmojiBySearchQuery('person')).map(_ => _.annotation)).toContain('person: blond hair')
expect((await db.getEmojiBySearchQuery('blond')).map(_ => _.annotation)).toContain('person: blond hair')
expect((await db.getEmojiBySearchQuery('hair')).map(_ => _.annotation)).toContain('person: blond hair')
expect((await db.getEmojiBySearchQuery('blon')).map(_ => _.annotation)).toContain('person: blond hair')
await db.delete()
})
test('errors', async () => {
const db = new Database({ dataSource: ALL_EMOJI })
await expect(() => db.getEmojiBySearchQuery()).rejects.toThrow()
await expect(() => db.getEmojiBySearchQuery(1)).rejects.toThrow()
await expect(() => db.getEmojiBySearchQuery(null)).rejects.toThrow()
await expect(() => db.getEmojiBySearchQuery('')).rejects.toThrow()
await db.delete()
})
})

View File

@ -17,4 +17,15 @@ describe('getEmojiByShortcode', () => {
expect((await db.getEmojiByShortcode(':monkey_face:'))).toBe(null)
await db.delete()
})
test('errors', async () => {
const db = new Database({ dataSource: ALL_EMOJI })
await expect(() => db.getEmojiByShortcode()).rejects.toThrow()
await expect(() => db.getEmojiByShortcode(1)).rejects.toThrow()
await expect(() => db.getEmojiByShortcode(null)).rejects.toThrow()
await expect(() => db.getEmojiByShortcode('')).rejects.toThrow()
await db.delete()
})
})

View File

@ -0,0 +1,45 @@
import allEmoji from 'emojibase-data/en/data.json'
import { ALL_EMOJI, basicAfterEach, basicBeforeEach, truncatedEmoji } from './shared'
import Database from '../Database'
const { Response } = fetch
beforeEach(basicBeforeEach)
afterEach(basicAfterEach)
describe('getEmojiByUnicode', () => {
test('basic test', async () => {
const pirate = allEmoji.find(_ => _.annotation === 'pirate flag')
const emojiPlusPirateFlag = [
...truncatedEmoji,
pirate
]
const EMOJI_WITH_PIRATES = 'http://localhost/pirate.json'
fetch.get(EMOJI_WITH_PIRATES, () => new Response(JSON.stringify(emojiPlusPirateFlag), {
headers: { ETag: 'W/yarrr' }
}))
fetch.head(EMOJI_WITH_PIRATES, () => new Response(null, { headers: { ETag: 'W/yarrr' } }))
const db = new Database({ dataSource: EMOJI_WITH_PIRATES })
expect((await db.getEmojiByUnicode('😀')).annotation).toBe('grinning face')
expect((await db.getEmojiByUnicode(pirate.emoji)).annotation).toBe('pirate flag')
expect((await db.getEmojiByUnicode(pirate.emoji.substring(0, 1)))).toBe(null)
expect((await db.getEmojiByUnicode('smile'))).toBe(null)
expect((await db.getEmojiByUnicode('monkey_face'))).toBe(null)
await db.delete()
})
test('errors', async () => {
const db = new Database({ dataSource: ALL_EMOJI })
await expect(() => db.getEmojiByUnicode()).rejects.toThrow()
await expect(() => db.getEmojiByUnicode(1)).rejects.toThrow()
await expect(() => db.getEmojiByUnicode(null)).rejects.toThrow()
await expect(() => db.getEmojiByUnicode('')).rejects.toThrow()
await db.delete()
})
})

View File

@ -135,6 +135,6 @@ export async function getEmojiByShortcode (db, shortcode) {
export async function getEmojiByUnicode (db, unicode) {
return dbPromise(db, STORE_EMOJI, MODE_READONLY, (emojiStore, cb) => {
emojiStore.get(unicode).onsuccess = e => cb(e.target.result)
emojiStore.get(unicode).onsuccess = e => cb(e.target.result || null)
})
}

View File

@ -2,6 +2,11 @@ export function extractTokens (str) {
return str
.split(/[\s_]+/)
.map(word => {
if (!word.match(/\w/)) {
// for pure emoticons like :) or :-), just leave them as-is
return word
}
return word
.replace(/[)(:,]/g, '')
.replace(//g, "'")

View File

@ -30,6 +30,8 @@ export default class Database {
/**
* Returns all emoji belonging to a group, ordered by `order`.
*
* Non-numbers throw an error.
* @param group - the group number
*/
getEmojiByGroup(group: number): Promise<Emoji[]> {
@ -38,6 +40,9 @@ export default class Database {
/**
* Returns all emoji matching the given search query, ordered by `order`.
*
* Empty/null strings throw an error.
*
* @param query - search query string
*/
getEmojiBySearchQuery(query: string): Promise<Emoji[]> {
@ -49,7 +54,7 @@ export default class Database {
*
* The colons around the shortcode should not be included when querying, e.g.
* use "slight_smile", not ":slight_smile:". Uppercase versus lowercase
* does not matter.
* does not matter. Empty/null strings throw an error.
* @param shortcode
*/
getEmojiByShortcode(shortcode: string): Promise<Emoji | null> {
@ -58,6 +63,8 @@ export default class Database {
/**
* Return a single emoji matching the unicode string, or null if not found.
*
* Empty/null strings throw an error.
* @param unicode - unicode string
*/
getEmojiByUnicode(unicode: string): Promise<Emoji | null> {