我正在使用ChaiJS插件使用Casper-Chai,但不确定如何解决遇到的特定问题。
我希望能够编写如下测试:
expect(casper).selector("#waldo").to.be.visible;
这非常简单,例如
utils.addChainableMethod(chai.Assertion.prototype, 'selector',
selectorMethod, selectorChainableMethod);
utils.addMethod(chai.Assertion.prototype, 'visible', visibleMethod);
*Method
引用涉及执行相应测试或可链接调用的函数。我的问题是拥有例如“选择器”修改链中的后代。我想到两个选择:
utils.flag(chai, 'object')
将其更改为选择器;或utils.flag(chai, 'casper-selector')
调用“visible”时,它可以读取相应的标志。修改``对象''似乎有用的地方是在调用例如“长度”稍后。但是,我有点担心更改“对象”的意外副作用。
我可能还想修改对象,以便进行“长度”测试,例如:
// there can be only one!
expect(casper).selector("#waldo").length(1)
// but that one has 4 classes
expect(casper).selector("#waldo").class.to.have.length(4)
感谢您的任何想法和投入。
---- 编辑 ----
好的,这是植根于Casper-Chai的概念挑战,它需要对Casper是什么以及为什么Casper-Chai应该是Chai插件而不是现有Casper API的替代品进行一些描述。 Casper是PhantomJS无头Web浏览器的包装,因此,Casper可有效运行两个不同的虚拟机:A
“ Controller ”和无头Web浏览器。
Controller 中没有DOM或“文档”或“窗口”对象;尽管使用WebKit javascript解析器,但Controller在这方面与Node.js非常相似。同时,PhantomJS启动了无头Web浏览器。然后, Controller 可以通过PhantomJS / Casper API与无头浏览器进行通信。 Controller可以告诉无头浏览器加载哪些页面,运行什么javascript(就像在控制台中键入javascript),甚至模拟事件,例如键盘输入和鼠标单击。无头浏览器具有完整的DOM和JavaScript堆栈:它是WebKit中加载的网页。您可以capture screenshots WebKit将呈现的内容。
Casper-Chai在Controller中运行。在Controller的Mocha + Chai中创建的测试旨在根据无头浏览器的状态进行评估。尽管我们可以将状态从浏览器复制到Controller并在复制的状态上运行测试,但是我对该设计的有限实验揭示了该设计固有的问题(即效率,竞争条件,性能和潜在的副作用)。问题在于浏览器状态是动态的,复杂的,并且可能笨拙。
因此,以约翰为例,由于没有DOM,因此
expect(casper.find("#waldo")).to.be.visible
将不起作用,除非Casper返回的对象进行了某种惰性的评估/中介。即使我们序列化并复制了HTML元素,Controller中也没有CSS。然后,即使#waldo
拥有CSS,也无法像浏览器一样测试层次结构。我们必须复制DOM的大部分内容和所有CSS,然后复制一个Web浏览器以测试#waldo
是否可见-对于每个测试。 Casper-Chai旨在通过在浏览器中运行测试来避免此问题。仅需要一点点额外的照明,一个简单的比较就是获得与选择器匹配的元素数量。可以编写
expect(casper.evaluate(function () {return __utils__.findAll('.my_class')}).to.have.length(4)
,其中casper.evaluate
在无头浏览器中运行给定的函数,并以字符串形式返回与选择器匹配的DOM元素列表;您可以将__utils__
视为Casper的jQuery版本。或者,可以编写expect(casper).selector('.my_class').to.have.length(4)
,其中selector
成为“对象”,并且它具有调用“casper.evaluate(function(){return utils .findAll('。my_class')。length”的 setter/getter .length
。仅整数长度对于少量的测试,它们都可以正常工作,但是对于大量的测试,此性能特征会产生影响(此处以这种简单的形式出现,在更复杂的情况下可能会更大程度地发挥作用)。当然可以写
expect(casper.evaluate(function () { __utils__.findAll('.my_class').length }).equal(4)
,但是如果要编写这样的测试,为什么还要麻烦BDD / Chai?它消除了Chai提供的可读性的好处。还值得注意的是,Controller中可能有多个Casper实例,对应于多个PhantomJS页面。将它们视为怪异的标签。
因此,根据Domenic的回答,修改'object'标志是解决该问题的适当方法,这似乎是最实用的方法-鉴于以上描述,应考虑任何想法。
我希望以上内容描述了为什么Casper-Chai应该是插件,而不仅仅是Casper的API扩展。我还将由Casper的作者运行此命令,以查看他是否有任何输入。
这可能不是一个完美的关系,但我希望Casper&Chai能够和睦相处。 :)
最佳答案
困难源于casper具有高度程序化的API(使用Casper#click(String selector)
和Casper#fetchText(String selector)
之类的方法)的事实。为了自然地适应chai,需要一个面向对象的API,例如Casper#find(String selector)
(返回CasperSelection
对象),CasperSelection#click()
,CasperSelection#text()
等。
因此,我建议您使用find
或selector
方法extend the casper object itself,它返回一个可以作为断言基础的对象。然后,您将不需要更改对象标志。
expect(casper.find("#waldo")).to.be.visible;
expect(casper.find("#waldo")).to.have.length(1)
expect(casper.find("#waldo").class).to.have.length(4)
关于chai - 如何(以及是否)修改Chai BDD链中的对象,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/13999229/