spec/cues_spec.lua (5102 bytes)
1 local Cues = require("subread.cues") 2 local Srt = require("subread.srt") 3 4 local function build(triples) 5 local list = {} 6 for _, t in ipairs(triples) do 7 list[#list + 1] = { 8 start = t[1], stop = t[2], text = t[3], 9 norm = t[3], no_place = false, 10 } 11 end 12 return Cues.new(list) 13 end 14 15 local SIMPLE = { 16 { 0, 2, "alpha one" }, 17 { 2, 4, "beta two" }, 18 { 4, 6, "gamma three" }, 19 { 8, 10, "delta four" }, -- a gap from 6 to 8 20 } 21 22 describe("SubRead cues", function() 23 it("counts the cues", function() 24 assert.equals(4, build(SIMPLE):count()) 25 assert.equals(0, Cues.new({}):count()) 26 end) 27 28 it("finds the last cue that started", function() 29 local index = build(SIMPLE) 30 assert.equals(0, index:lastStartedAt(-1)) 31 assert.equals(1, index:lastStartedAt(0)) 32 assert.equals(1, index:lastStartedAt(1.9)) 33 assert.equals(3, index:lastStartedAt(7)) 34 assert.equals(4, index:lastStartedAt(100)) 35 end) 36 37 it("finds the cue that is on", function() 38 local index = build(SIMPLE) 39 assert.equals(1, index:findByTime(0)) 40 assert.equals(1, index:findByTime(1.99)) 41 assert.equals(2, index:findByTime(2)) 42 assert.equals(4, index:findByTime(9)) 43 end) 44 45 it("returns nil in a gap and outside the file", function() 46 local index = build(SIMPLE) 47 assert.is_nil(index:findByTime(7)) 48 assert.is_nil(index:findByTime(-1)) 49 assert.is_nil(index:findByTime(11)) 50 end) 51 52 it("agrees with a slow reference for every time", function() 53 local index = build(SIMPLE) 54 local function reference(t) 55 local best 56 for i, cue in ipairs(index.list) do 57 if cue.start <= t and t < cue.stop then best = i end 58 end 59 return best 60 end 61 for step = -20, 240 do 62 local t = step / 20 63 assert.equals(reference(t), index:findByTime(t)) 64 end 65 end) 66 67 it("lets the latest overlapping cue win", function() 68 local index = build({ 69 { 0, 100, "long background cue" }, 70 { 10, 12, "short cue on top" }, 71 }) 72 assert.equals(1, index:findByTime(5)) 73 assert.equals(2, index:findByTime(11)) 74 -- After the short cue ends the long one is still on. 75 assert.equals(1, index:findByTime(20)) 76 end) 77 78 it("finds the next cue start", function() 79 local index = build(SIMPLE) 80 assert.equals(1, index:nextAfter(-5)) 81 assert.equals(2, index:nextAfter(0)) 82 assert.equals(4, index:nextAfter(6)) 83 assert.is_nil(index:nextAfter(8)) 84 end) 85 86 it("steps over cues that share a start time", function() 87 local index = build({ { 0, 1, "a" }, { 5, 6, "b" }, { 5, 7, "c" }, { 9, 10, "d" } }) 88 assert.equals(4, index:nextAfter(5)) 89 end) 90 91 it("finds the nearest cue for a start time", function() 92 local index = build(SIMPLE) 93 assert.equals(1, index:findNearest(-3)) 94 assert.equals(3, index:findNearest(6.5)) -- gap, nearer the cue before 95 assert.equals(4, index:findNearest(7.9)) -- gap, nearer the cue after 96 assert.equals(4, index:findNearest(50)) 97 assert.is_nil(Cues.new({}):findNearest(1)) 98 end) 99 100 it("finds the cue that holds a piece of text", function() 101 local index = build(SIMPLE) 102 assert.equals(2, index:findIndexContaining("beta")) 103 assert.is_nil(index:findIndexContaining("missing")) 104 assert.is_nil(index:findIndexContaining("")) 105 end) 106 107 it("starts the text search at the given index", function() 108 local index = build({ { 0, 1, "same words" }, { 1, 2, "same words" } }) 109 assert.equals(1, index:findIndexContaining("same")) 110 assert.equals(2, index:findIndexContaining("same", 2)) 111 end) 112 113 it("treats the needle as plain text, not a pattern", function() 114 local index = build({ { 0, 1, "cost is 5 % of it" } }) 115 assert.equals(1, index:findIndexContaining("5 %")) 116 end) 117 118 it("finds the cue for a page of book text", function() 119 local index = build(SIMPLE) 120 -- Book text with other white space than the cue text. 121 assert.equals(2, index:findIndexForText("beta\n two and more words")) 122 assert.is_nil(index:findIndexForText("nothing here at all matches")) 123 assert.is_nil(index:findIndexForText("")) 124 end) 125 126 it("skips over page text that no cue holds", function() 127 local index = build({ { 0, 1, "the real sentence of the book" } }) 128 -- The page starts with a running head that is not in any cue. 129 local page = "CHAPTER ONE 12 the real sentence of the book" 130 assert.equals(1, index:findIndexForText(page)) 131 end) 132 133 it("builds from a parsed file", function() 134 local data = "1\n00:00:00,000 --> 00:00:01,000\nhello there friend\n" 135 local index = Cues.new(Srt.parse(data)) 136 assert.equals(1, index:count()) 137 assert.equals(1, index:findByTime(0.5)) 138 assert.equals("hello there friend", index:get(1).norm) 139 end) 140 end)