/ spec / fASTQuery_spec.lua
fASTQuery_spec.lua
  1  dofile('init.lua')
  2  local Q, describe, it = fASTQuery, describe, it
  3  describe("wrapper", function ()
  4  	it("wraps and references make unwrapping not needed", function ()
  5  		local dom = { type = "box", color = "#FFFFFF" }
  6  		Q(dom).color = "#000000"
  7  		assert.same(dom, { type = "box", color = "#000000" }, "color was changed")
  8  	end)
  9  	it("works with multiple nodes too!", function ()
 10  		local dom = {
 11  			type = "container",
 12  			{ type = "box", color = "#FFFFFF" },
 13  			{ type = "label", label = "asdf" },
 14  			{ type = "box", color = "#aFFFFF" }
 15  		}
 16  		Q(dom):all{ type = "box" }.color = "#000000"
 17  		assert.same(dom, {
 18  			type = "container",
 19  			{ type = "box", color = "#000000" },
 20  			{ type = "label", label = "asdf" },
 21  			{ type = "box", color = "#000000" }
 22  		}, "modified only the colors")
 23  	end)
 24  	it("supports getting children, and children are also wrapped", function ()
 25  		local dom = { type = "container", { type = "box", color = "#FFFFFF" } }
 26  		local wrapped_child = Q(dom)[1]
 27  		assert.truthy(wrapped_child, "child found")
 28  		assert.equal(wrapped_child.type, dom[1].type, "child type is the same")
 29  		assert.equal(wrapped_child.color, dom[1].color, "child color is the same")
 30  		assert.truthy(wrapped_child.all, "child is wrapped")
 31  		wrapped_child.color = "#000000"
 32  		assert.equal(wrapped_child.color, dom[1].color, "child color is still the same")
 33  		assert.same(dom, { type = "container", { type = "box", color = "#000000" } }, "child was modified")
 34  	end)
 35  	it("supports getting number of children for first match using #", function ()
 36  		local dom = {
 37  			type = "container",
 38  			{ type = "box", color = "#FFFFFF"},
 39  			{ type = "box", color = "#FFFFFF"},
 40  			{ type = "box", color = "#FFFFFF"}
 41  		}
 42  		assert.equal(#Q(dom), 3)
 43  	end)
 44  end)
 45  describe("navigation", function ()
 46  	describe("all", function ()
 47  		it("can search by table", function ()
 48  			local dom = { type = "container", { type = "box", color = "#FFFFFF" }, { type = "box", color = "#aFFFFF" } }
 49  			Q(dom):all{ type = "box" }.color = "#000000"
 50  			assert.same(dom, { type = "container", { type = "box", color = "#000000" }, { type = "box", color = "#000000" } })
 51  		end)
 52  		it("returns all if no args provided", function ()
 53  			local dom = { type = "container", { type = "box", color = "#FFFFFF" }, { type = "box", color = "#aFFFFF" } }
 54  			Q(dom):all().k = "v"
 55  			assert.same({
 56  				type = "container",
 57  				k = "v",
 58  				{ type = "box", color = "#FFFFFF", k = "v" },
 59  				{ type = "box", color = "#aFFFFF", k = "v" }
 60  			}, dom)
 61  		end)
 62  		it("can accept a function as the key", function ()
 63  			local dom = { type = "container", { type = "box", color = "#FFFFFF" }, { type = "box", color = "#aFFFFF" } }
 64  			Q(dom):all(function (elm)
 65  				return elm.type == "box"
 66  			end).color = "#000000"
 67  			assert.same(dom, { type = "container", { type = "box", color = "#000000" }, { type = "box", color = "#000000" } })
 68  		end)
 69  	end)
 70  	describe("first", function ()
 71  		it("only finds one element", function ()
 72  			local dom = { type = "container", { type = "box", color = "#FFFFFF" }, { type = "box", color = "#aFFFFF" } }
 73  			Q(dom):first{ type = "box" }.color = "#000000"
 74  			assert.same(dom, { type = "container", { type = "box", color = "#000000" }, { type = "box", color = "#aFFFFF" } })
 75  		end)
 76  		it("gives the first element when no args", function ()
 77  			local dom = { type = "container", { type = "box", color = "#FFFFFF" }, { type = "box", color = "#aFFFFF" } }
 78  			-- Remember, all is slow. This is bad. Don't do this, just do :first(pattern). Reduce first, then pattern
 79  			Q(dom):all{ type = "box" }:first().color = "#000000"
 80  			assert.same(dom, { type = "container", { type = "box", color = "#000000" }, { type = "box", color = "#aFFFFF" } })
 81  		end)
 82  		it("provides a way to tell if none were found", function ()
 83  			local dom = { type = "container", { type = "label", label = "lol" } }
 84  			assert.equal(Q(dom):first{ type = "box" }:count(), 0, "none should be found")
 85  		end)
 86  		it("can accept a function", function ()
 87  			local dom = { type = "container", { type = "box", color = "#FFFFFF" }, { type = "box", color = "#aFFFFF" } }
 88  			Q(dom):first(function (elm)
 89  				return elm.type == "box"
 90  			end).color = "#000000"
 91  			assert.same(dom, { type = "container", { type = "box", color = "#000000" }, { type = "box", color = "#aFFFFF" } })
 92  		end)
 93  	end)
 94  	describe("children", function ()
 95  		it("finds all children of all selected elements", function ()
 96  			local dom = {
 97  				type = "container",
 98  				{ type = "container", findMe = "pls", { type = "box", color = "#FFFFFF" }, { type = "box", color = "#aFFFFF" } },
 99  				{ type = "box", color = "#bFFFFF" },
100  				{ type = "container", findMe = "pls", { type = "box", color = "#cFFFFF" }, { type = "box", color = "#dFFFFF" } }
101  			}
102  			Q(dom):all{ findMe = "pls" }:children().color = "#000000"
103  			assert.same(dom, {
104  				type = "container",
105  				{ type = "container", findMe = "pls", { type = "box", color = "#000000" }, { type = "box", color = "#000000" } },
106  				{ type = "box", color = "#bFFFFF" },
107  				{ type = "container", findMe = "pls", { type = "box", color = "#000000" }, { type = "box", color = "#000000" } }
108  			})
109  		end)
110  	end)
111  	describe("include", function ()
112  		it("adds elements found in a different search into this search", function ()
113  			local dom = {
114  				type = "container",
115  				{ type = "box", color = "#FFFFFF" },
116  				{ type = "box", color = "#cFFFFF" },
117  				{ type = "container", { type = "box", color = "#aFFFFF" }, { type = "box", color = "#bFFFFF" } }
118  			}
119  			local first = Q(dom):first{ type = "box" }
120  			Q(dom)[3]:all{ type = "box" }:include(first).color = "#000000"
121  			assert.same(dom, {
122  				type = "container",
123  				{ type = "box", color = "#000000" },
124  				{ type = "box", color = "#cFFFFF" },
125  				{ type = "container", { type = "box", color = "#000000" }, { type = "box", color = "#000000" } }
126  			})
127  		end)
128  	end)
129  	describe("count", function ()
130  		it("counts the number of matches made", function ()
131  			local dom = {
132  				type = "container",
133  				{ type = "box", color = "#FFFFFF" },
134  				{ type = "label", label = "hi"},
135  				{ type = "box", color = "#FFFFFF" },
136  				{ type = "box", color = "#FFFFFF" }
137  			}
138  			local container = Q(dom)
139  			assert.equal(container:all{ type = "box" }:count(), 3, "there are three matches")
140  			assert.equal(container:first{ type = "box" }:count(), 1, "first found only just the one")
141  		end)
142  	end)
143  	describe("each", function ()
144  		it("is an iterator returning wrapped elements", function ()
145  			local dom = {
146  				type = "container",
147  				{ type = "container", findMe = "pls", { type = "box", color = "#FFFFFF" }, { type = "box", color = "#aFFFFF" } },
148  				{ type = "box", color = "#bFFFFF" },
149  				{ type = "container", findMe = "pls", { type = "box", color = "#cFFFFF" }, { type = "box", color = "#dFFFFF" } }
150  			}
151  			for elm in Q(dom):all{ findMe = "pls" }:children():each() do
152  				elm.color = "#000000"
153  				assert.is.truthy(elm.each, "is wrapped")
154  			end
155  			assert.same(dom, {
156  				type = "container",
157  				{ type = "container", findMe = "pls", { type = "box", color = "#000000" }, { type = "box", color = "#000000" } },
158  				{ type = "box", color = "#bFFFFF" },
159  				{ type = "container", findMe = "pls", { type = "box", color = "#000000" }, { type = "box", color = "#000000" } }
160  			})
161  		end)
162  	end)
163  	describe("parents", function ()
164  		it("returns the parents of each element", function ()
165  			local dom = {
166  				type = "container",
167  				{ type = "container", { type = "box", color = "#FFFFFF" } },
168  				{ type = "container", { type = "box", color = "#FFFFFF" } }
169  			}
170  			Q(dom):all{ type = "box" }:parents().type = "vbox"
171  			assert.same(dom, {
172  				type = "container",
173  				{ type = "vbox", { type = "box", color = "#FFFFFF" } },
174  				{ type = "vbox", { type = "box", color = "#FFFFFF" } }
175  			})
176  		end)
177  		it("does not match duplicates", function ()
178  			local dom = {
179  				type = "container",
180  				{ type = "container", { type = "box", color = "#FFFFFF" }, { type = "box", color = "#FFFFFF" } }
181  			}
182  			local count = 0
183  			for _ in Q(dom):all{ type = "box" }:parents():each() do
184  				count = count + 1
185  			end
186  			assert.equal(1, count)
187  		end)
188  	end)
189  	--TODO slice (or something that performs subsets on _path, by a good name)
190  end)
191  describe("manipulation", function ()
192  	describe("getKey", function ()
193  		it("gets a key, regardless of if that key is shadowed by this api", function ()
194  			local dom = { type = "box", getKey = 3 }
195  			assert.equal(Q(dom):getKey("getKey"), 3)
196  		end)
197  		it("only returns the first key", function()
198  			local dom = {
199  				type = "container",
200  				{ type = "box", color = "#FFFFFF" },
201  				{ type = "box", color = "#aFFFFF" }
202  			}
203  			assert.equal(Q(dom):children():getKey("color"), "#FFFFFF")
204  		end)
205  		it("is an unalias for just getting the key conventionally", function ()
206  			local dom = { type = "container", { type = "box", color = "#FFFFFF" }, { type = "box", color = "#aFFFFF" } }
207  			assert.equal(Q(dom):children().color, "#FFFFFF")
208  		end)
209  	end)
210  	describe("append", function ()
211  		it("inserts a new DOM element at the end", function ()
212  			local dom = { type = "container", { type = "label", label = "hi" } }
213  			Q(dom):append{ type = "box", color = "#FFFFFF" }
214  			assert.same(dom, {
215  				type = "container",
216  				{ type = "label", label = "hi" },
217  				{ type = "box", color = "#FFFFFF" }
218  			})
219  		end)
220  	end)
221  	-- insert (take the last two [or one] arguments from table.insert)
222  	describe("insert", function ()
223  		it("inserts a new DOM element at a given location", function ()
224  			local dom = {
225  				type = "container",
226  				{ type = "label", label = "hi" },
227  				{ type = "label", label = "hi1" }
228  			}
229  			Q(dom):insert(2, { type = "box", color = "#FFFFFF" })
230  			assert.same(dom, {
231  				type = "container",
232  				{ type = "label", label = "hi" },
233  				{ type = "box", color = "#FFFFFF" },
234  				{ type = "label", label = "hi1" }
235  			})
236  		end)
237  		it("falls back to append() if no index", function ()
238  			local dom = { type = "container", { type = "label", label = "hi" } }
239  			Q(dom):insert{ type = "box", color = "#FFFFFF" }
240  			assert.same({
241  				type = "container",
242  				{ type = "label", label = "hi" },
243  				{ type = "box", color = "#FFFFFF" }
244  			}, dom)
245  		end)
246  	end)
247  	-- TODO remove
248  	-- TODO replaceWith
249  	-- TODO wrap
250  	-- TODO unwrap
251  	-- TODO before
252  	-- TODO after
253  end)