Я использую ChaiJS с моим плагином Casper-Chai, и я не уверен, как решить конкретную проблему, с которой я сталкиваюсь.Как (и нужно ли) модифицировать объект в цепочке Chai BDD
Я хотел бы иметь возможность писать тесты, такие как:
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')
Когда вызывается «видимый», он может читать соответствующий флаг. Если модификация «объекта», по-видимому, полезна, при вызове, например, «длина» позже. Тем не менее, я несколько обеспокоен неожиданными побочными эффектами изменения «объекта».
Я также могу изменить объект, для испытаний «длиной», вниз по цепочке, например:
// 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- Чай должен быть плагином Chai, а не просто альтернативой существующему API Каспер. Каспер - обертка вокруг браузера PhantomJS без головы, и таким образом Каспер запускает две эффективно две различные виртуальные машины: A «Контроллер» и безгласный веб-браузер.
В контроллере нет объекта DOM или "document" или "window"; Контроллер в этом отношении очень похож на Node.js, хотя и использует парсер WebKit javascript. Параллельно PhantomJS запускает безгласный веб-браузер. Затем контроллер может взаимодействовать с API-интерфейсом PhantomJS/Casper в браузере без браузера. Контроллер может сказать безгласному браузеру, какие страницы загружать, какой javascript запускать (что похоже на ввод javascript в консоль) и даже имитировать такие события, как ввод с клавиатуры и щелчки мышью. В браузере без гарнитуры есть полный стек DOM и javascript: это веб-страница, загруженная в WebKit. Вы можете capture screenshots того, что визуализировал WebKit.
Casper-Chai запускается в контроллере. Тесты, созданные в Mocha + Chai в контроллере, предназначены для оценки состояния безгласного браузера. Хотя мы можем скопировать состояние из браузера в контроллер и запустить тесты в этом скопированном состоянии, мои ограниченные эксперименты с этим дизайном выявили проблемы, присущие дизайну (например, эффективность, условия гонки, производительность и потенциальные побочные эффекты). Проблема в том, что состояние браузера является динамичным, сложным и может быть громоздким.
Так что, принимая пример Джона, expect(casper.find("#waldo")).to.be.visible
не будет работать, так как нет DOM, если объект, возвращенный Каспером, не сделал своего рода ленивую оценку/посредничество. Даже если мы сериализовали и скопировали HTML-элемент там, в контроллере нет CSS. Тогда, даже если бы существовали CSS для #waldo
, невозможно проверить иерархию, как если бы это был веб-браузер. Нам пришлось бы копировать значительную часть DOM и все CSS, а затем реплицировать веб-браузер, чтобы проверить, видно ли #waldo
- для каждого отдельного теста. Каспер-Чай должен избегать этой проблемы, выполнив тесты в браузере.
Просто для небольшого дополнительного освещения тривиальное сравнение позволяет получить количество элементов, соответствующих селектору. Можно написать expect(casper.evaluate(function() {return __utils__.findAll('.my_class')}).to.have.length(4)
, где casper.evaluate
запускает данную функцию в браузере без заголовка и возвращает список элементов DOM, соответствующих селектору в виде строк; и вы можете думать о __utils__
как версия jQuery Каспера. В качестве альтернативы можно было бы написать expect(casper).selector('.my_class').to.have.length(4)
, где selector
становится «объектом» и имеет геттер .length
, который вызывает «casper.evaluate (function() {return utils .findAll ('. My_class'). Length`. Только целая длина возвращается, для небольшого числа тестов либо работает нормально, но для большего числа тестов эта характеристика производительности становится эффективной (здесь, в этой упрощенной форме и, возможно, в значительно большей степени в более сложных случаях).
может, конечно, написать expect(casper.evaluate(function() { __utils__.findAll('.my_class').length }).equal(4)
, но если вы собираетесь писать такие тесты, зачем беспокоиться о BDD/Chai? Это исключает преимущества читаемости, которые предлагает Chai.
Также стоит отметить, что в контроллере может быть несколько экземпляров Каспера, соответствующих нескольким страницам PhantomJS. Думайте о них как о жутких вкладках.
Так что, учитывая ответ Доменика о том, что изменение флага «объект» является подходящим способом для этого, это кажется наиболее практичным способом - с учетом любых мыслей в свете приведенного выше описания.
Надеюсь, что выше описано, почему Каспер-Чай должен быть плагином, а не просто расширением API для Каспера. Я также запустил это автор Каспера, чтобы узнать, есть ли у него какие-либо данные.
Это может быть не идеальное отношение, но я надеюсь, что Каспер & Chai может ладить с удовольствием. :)
Благодаря @John - это хорошая мысль, и, конечно, возможность –
я сделал правку (извините за длину) на вопрос, который описывает обоснование для плагина. Я думаю, что то, что вы предлагаете, по-прежнему может быть лучшим вариантом, чем изменение «объекта»; вопрос может заключаться в том, вводим ли мы посредника в цепочку Чай (что не должно быть ленивым), или у Каспера есть нативный ленивый посредник. Я должен подумать об этом еще немного. :) –
Вот как бы я это сделал: https://gist.github.com/4365642 – John