Add shell plugin model tests
This commit is contained in:
Executable
+24
@@ -0,0 +1,24 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
ROOT=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)
|
||||
TEST_DIR="$ROOT/test/shell.d"
|
||||
|
||||
shopt -s nullglob
|
||||
tests=()
|
||||
for test in "$TEST_DIR"/*-test.sh; do
|
||||
[[ $(basename "$test") == "base-test.sh" ]] && continue
|
||||
tests+=("$test")
|
||||
done
|
||||
shopt -u nullglob
|
||||
|
||||
if (( ${#tests[@]} == 0 )); then
|
||||
echo "No shell tests found in $TEST_DIR" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for test in "${tests[@]}"; do
|
||||
printf '==> %s\n' "${test#$ROOT/}"
|
||||
bash "$test"
|
||||
done
|
||||
@@ -1,80 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [[ ${BASH_SOURCE[0]} == "$0" ]]; then
|
||||
echo "source test/shell/base-test.sh from a shell test; do not run it directly" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ROOT=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/../.." && pwd)
|
||||
SHELL_TEST_DIR="$ROOT/test/shell"
|
||||
|
||||
export ROOT
|
||||
|
||||
pass() {
|
||||
printf 'ok - %s\n' "$1"
|
||||
}
|
||||
|
||||
fail() {
|
||||
local description="$1"
|
||||
local detail="${2:-}"
|
||||
|
||||
[[ -n $detail ]] && printf '%s\n' "$detail" >&2
|
||||
printf 'not ok - %s\n' "$description" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
require_command() {
|
||||
local command="$1"
|
||||
|
||||
command -v "$command" >/dev/null || fail "required command is available: $command"
|
||||
}
|
||||
|
||||
run_node_test() {
|
||||
require_command node
|
||||
|
||||
{
|
||||
cat <<'JS_PRELUDE'
|
||||
const path = require('path')
|
||||
const root = process.env.ROOT
|
||||
|
||||
function fail(description, detail) {
|
||||
if (detail) console.error(detail)
|
||||
console.error(`not ok - ${description}`)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
function pass(description) {
|
||||
console.log(`ok - ${description}`)
|
||||
}
|
||||
|
||||
function assert(condition, description, detail) {
|
||||
if (!condition) fail(description, detail)
|
||||
pass(description)
|
||||
}
|
||||
|
||||
function assertEqual(actual, expected, description) {
|
||||
assert(
|
||||
actual === expected,
|
||||
description,
|
||||
`expected: ${expected}\nactual: ${actual}`
|
||||
)
|
||||
}
|
||||
|
||||
function assertDeepEqual(actual, expected, description) {
|
||||
const actualJson = JSON.stringify(actual)
|
||||
const expectedJson = JSON.stringify(expected)
|
||||
assert(
|
||||
actualJson === expectedJson,
|
||||
description,
|
||||
`expected: ${expectedJson}\nactual: ${actualJson}`
|
||||
)
|
||||
}
|
||||
|
||||
function requireFromRoot(relativePath) {
|
||||
return require(path.join(root, relativePath))
|
||||
}
|
||||
|
||||
JS_PRELUDE
|
||||
cat
|
||||
} | node
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
source "$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)/base-test.sh"
|
||||
|
||||
run_node_test <<'JS'
|
||||
const fs = require('fs')
|
||||
const emojis = requireFromRoot('shell/plugins/emojis/EmojiSearch.js')
|
||||
|
||||
const raw = fs.readFileSync(path.join(root, 'shell/plugins/emojis/emojis.json'), 'utf8')
|
||||
const data = emojis.parseEmojis(raw)
|
||||
|
||||
assert(data.length > 1000, 'emoji dataset parses')
|
||||
assertDeepEqual(emojis.parseEmojis('{'), [], 'invalid emoji JSON parses as empty list')
|
||||
assertDeepEqual(emojis.parseEmojis('{"e":"nope"}'), [], 'non-array emoji JSON parses as empty list')
|
||||
|
||||
const fixture = [
|
||||
{ e: 'a', k: 'grinning face smile happy' },
|
||||
{ e: 'b', k: 'face with tears of joy joy tears' },
|
||||
{ e: 'c', k: 'flag: united states us america' }
|
||||
]
|
||||
|
||||
assertDeepEqual(
|
||||
emojis.filterEmojis(fixture, ' JOY ').map(item => item.e),
|
||||
['b'],
|
||||
'emoji filtering trims and lowercases query'
|
||||
)
|
||||
|
||||
assertDeepEqual(
|
||||
emojis.filterEmojis(fixture, '', 2).map(item => item.e),
|
||||
['a', 'b'],
|
||||
'emoji filtering honors result limit'
|
||||
)
|
||||
|
||||
assertDeepEqual(
|
||||
emojis.filterEmojis(fixture, '', 0),
|
||||
[],
|
||||
'emoji filtering supports zero result limit'
|
||||
)
|
||||
|
||||
assertEqual(
|
||||
emojis.filterEmojis(data, 'face with tears')[0].e,
|
||||
'\u{1F602}',
|
||||
'emoji filtering finds face with tears of joy'
|
||||
)
|
||||
JS
|
||||
@@ -1,68 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
source "$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)/base-test.sh"
|
||||
|
||||
run_node_test <<'JS'
|
||||
const search = requireFromRoot('shell/plugins/launcher/LauncherSearch.js')
|
||||
|
||||
const entries = [
|
||||
{
|
||||
name: 'Google Contacts',
|
||||
genericName: 'Address Book',
|
||||
comment: 'Manage contacts',
|
||||
keywords: ['contacts', 'address book', 'people'],
|
||||
id: 'google-contacts.desktop'
|
||||
},
|
||||
{
|
||||
name: 'Calculator',
|
||||
genericName: 'Calculator',
|
||||
comment: 'Perform arithmetic, scientific or financial calculations',
|
||||
keywords: ['calculation', 'arithmetic', 'scientific', 'financial'],
|
||||
id: 'org.gnome.Calculator.desktop'
|
||||
},
|
||||
{
|
||||
name: 'OBS Studio',
|
||||
genericName: 'Streaming/Recording Software',
|
||||
comment: 'Free and Open Source Streaming/Recording Software',
|
||||
keywords: ['streaming', 'recording', 'capture'],
|
||||
id: 'com.obsproject.Studio.desktop'
|
||||
},
|
||||
{
|
||||
name: 'Aether',
|
||||
genericName: '',
|
||||
comment: 'Minimal internet radio player',
|
||||
keywords: ['audio', 'music', 'radio'],
|
||||
id: 'io.github.taqi.aether.desktop'
|
||||
},
|
||||
{
|
||||
name: 'Xournal++',
|
||||
genericName: 'Notetaking',
|
||||
comment: 'Take handwritten notes',
|
||||
keywords: ['notes', 'pdf', 'annotation'],
|
||||
id: 'com.github.xournalpp.xournalpp.desktop'
|
||||
},
|
||||
{
|
||||
name: 'RustDesk',
|
||||
genericName: 'Remote Desktop',
|
||||
comment: 'Remote desktop control',
|
||||
keywords: ['remote', 'desktop', 'control'],
|
||||
id: 'com.rustdesk.RustDesk.desktop'
|
||||
}
|
||||
]
|
||||
|
||||
const contactMatches = search.sortedEntries(entries, 'contact').map(row => search.entryName(row.entry))
|
||||
assertDeepEqual(contactMatches, ['Google Contacts'], 'contact search only returns direct contact matches')
|
||||
|
||||
assert(
|
||||
search.fuzzyScore(entries[1], 'contact') < 0,
|
||||
'calculator does not match contact as a loose subsequence'
|
||||
)
|
||||
|
||||
const acronymMatches = search.sortedEntries(entries, 'gc').map(row => search.entryName(row.entry))
|
||||
assertEqual(acronymMatches[0], 'Google Contacts', 'short acronym matching still works')
|
||||
|
||||
const directMatches = search.sortedEntries(entries, 'obs').map(row => search.entryName(row.entry))
|
||||
assertEqual(directMatches[0], 'OBS Studio', 'direct app-name matching still works')
|
||||
JS
|
||||
Reference in New Issue
Block a user