274 lines
5.0 KiB
Go
274 lines
5.0 KiB
Go
package reader
|
|
|
|
import (
|
|
"reflect"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestORPIndex(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
word string
|
|
expected int
|
|
}{
|
|
{"empty", "", 0},
|
|
{"one character", "a", 0},
|
|
{"two characters", "go", 1},
|
|
{"three characters", "cat", 1},
|
|
{"five characters", "hello", 1},
|
|
{"six characters", "reader", 2},
|
|
{"nine characters", "wonderful", 2},
|
|
{"ten characters", "technology", 3},
|
|
{"long word", "extraordinary", 3},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got := ORPIndex([]rune(tt.word))
|
|
|
|
if got != tt.expected {
|
|
t.Errorf("ORPIndex(%q) = %d, want %d",
|
|
tt.word, got, tt.expected)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestSplitWord(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input string
|
|
expected Word
|
|
}{
|
|
{
|
|
name: "normal word",
|
|
input: "hello",
|
|
expected: Word{
|
|
Text: "hello",
|
|
Prefix: "h",
|
|
Focus: "e",
|
|
Suffix: "llo",
|
|
},
|
|
},
|
|
{
|
|
name: "unicode word",
|
|
input: "café",
|
|
expected: Word{
|
|
Text: "café",
|
|
Prefix: "c",
|
|
Focus: "a",
|
|
Suffix: "fé",
|
|
},
|
|
},
|
|
{
|
|
name: "emoji",
|
|
input: "🙂hello",
|
|
expected: Word{
|
|
Text: "🙂hello",
|
|
Prefix: "🙂h",
|
|
Focus: "e",
|
|
Suffix: "llo",
|
|
},
|
|
},
|
|
{
|
|
name: "empty word",
|
|
input: "",
|
|
expected: Word{},
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got := SplitWord(tt.input)
|
|
|
|
if !reflect.DeepEqual(got, tt.expected) {
|
|
t.Errorf("SplitWord(%q) = %+v, want %+v",
|
|
tt.input, got, tt.expected)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestTokenize(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
input string
|
|
expectedCount int
|
|
}{
|
|
{"normal text", "Hello world", 2},
|
|
{"multiple spaces", "Hello world", 2},
|
|
{"newlines", "Hello\nworld", 2},
|
|
{"tabs", "Hello\tworld", 2},
|
|
{"mixed whitespace", " Hello\n world\tagain ", 3},
|
|
{"empty input", "", 0},
|
|
{"whitespace only", " \n\t ", 0},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got := Tokenize(tt.input)
|
|
|
|
if len(got) != tt.expectedCount {
|
|
t.Errorf("Tokenize(%q) returned %d words, want %d",
|
|
tt.input, len(got), tt.expectedCount)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestTokenizePreservesWords(t *testing.T) {
|
|
input := "Hello, world!"
|
|
words := Tokenize(input)
|
|
|
|
expected := []string{"Hello,", "world!"}
|
|
|
|
for i, word := range words {
|
|
if word.Text != expected[i] {
|
|
t.Errorf("word %d = %q, want %q",
|
|
i, word.Text, expected[i])
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestIsSentenceEnding(t *testing.T) {
|
|
tests := []struct {
|
|
word string
|
|
expected bool
|
|
}{
|
|
{"hello.", true},
|
|
{"hello!", true},
|
|
{"hello?", true},
|
|
{"hello…", true},
|
|
{`hello."`, true},
|
|
{"hello!)", true},
|
|
{"hello", false},
|
|
{"hello,", false},
|
|
{"", false},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.word, func(t *testing.T) {
|
|
got := IsSentenceEnding(tt.word)
|
|
|
|
if got != tt.expected {
|
|
t.Errorf("IsSentenceEnding(%q) = %t, want %t",
|
|
tt.word, got, tt.expected)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestIsPausePunctuation(t *testing.T) {
|
|
tests := []struct {
|
|
word string
|
|
expected bool
|
|
}{
|
|
{"hello,", true},
|
|
{"hello;", true},
|
|
{"hello:", true},
|
|
{`hello,"`, true},
|
|
{"hello", false},
|
|
{"hello.", false},
|
|
{"", false},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.word, func(t *testing.T) {
|
|
got := IsPausePunctuation(tt.word)
|
|
|
|
if got != tt.expected {
|
|
t.Errorf("IsPausePunctuation(%q) = %t, want %t",
|
|
tt.word, got, tt.expected)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestWordDuration(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
word string
|
|
wpm int
|
|
expected time.Duration
|
|
}{
|
|
{
|
|
name: "normal word",
|
|
word: "hello",
|
|
wpm: 300,
|
|
expected: 200 * time.Millisecond,
|
|
},
|
|
{
|
|
name: "sentence ending",
|
|
word: "hello.",
|
|
wpm: 300,
|
|
expected: 500 * time.Millisecond,
|
|
},
|
|
{
|
|
name: "comma pause",
|
|
word: "hello,",
|
|
wpm: 300,
|
|
expected: 350 * time.Millisecond,
|
|
},
|
|
{
|
|
name: "long word",
|
|
word: "extraordinary",
|
|
wpm: 300,
|
|
expected: 250 * time.Millisecond,
|
|
},
|
|
{
|
|
name: "sentence ending and long word",
|
|
word: "extraordinary.",
|
|
wpm: 300,
|
|
expected: 550 * time.Millisecond,
|
|
},
|
|
{
|
|
name: "minimum WPM clamp",
|
|
word: "hello",
|
|
wpm: 50,
|
|
expected: 600 * time.Millisecond,
|
|
},
|
|
{
|
|
name: "maximum WPM clamp",
|
|
word: "hello",
|
|
wpm: 1500,
|
|
expected: 60 * time.Millisecond,
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got := WordDuration(tt.word, tt.wpm)
|
|
|
|
if got != tt.expected {
|
|
t.Errorf("WordDuration(%q, %d) = %v, want %v",
|
|
tt.word, tt.wpm, got, tt.expected)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestRuneLength(t *testing.T) {
|
|
tests := []struct {
|
|
word string
|
|
expected int
|
|
}{
|
|
{"hello", 5},
|
|
{"café", 4},
|
|
{"🙂", 1},
|
|
{"🙂hello", 6},
|
|
{"", 0},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.word, func(t *testing.T) {
|
|
got := RuneLength(tt.word)
|
|
|
|
if got != tt.expected {
|
|
t.Errorf("RuneLength(%q) = %d, want %d",
|
|
tt.word, got, tt.expected)
|
|
}
|
|
})
|
|
}
|
|
}
|