Как я могу проверить Stripe.js, используя poltergeist и Capybara?
Я с ума сходил, пытаясь написать автоматизированный тест для моей учетной записи пользователя. Пользователям будет взиматься постоянная подписка через Stripe. Они вводят свои основные сведения (адрес электронной почты, пароль и т.д.) И данные своей кредитной карты в одной и той же форме, затем происходит следующий поток:
- (На стороне клиента) stripe.js делает запрос AJAX для серверов Stripe, который (при условии, что все действительно) возвращает токен кредитной карты.
- Мой javascript заполняет скрытый ввод в форме HTML с помощью токена кредитной карты и отправляет форму на мой сервер Rails.
- (Теперь на стороне сервера): Я проверяю основные данные пользователя. Если они недействительны, верните (потому что нет смысла взимать их с помощью Stripe, если, например, их адрес электронной почты недействителен, поэтому они не могут создать учетную запись.)
- Если они действительны, попытайтесь создать объект
Stripe::Customer
, добавьте правильную подписку и зарядите их, используя Stripe ruby gem и т.д.
Все это прекрасно работает... за исключением того, что я не могу понять, как его протестировать. Шаг 4 тестирования достаточно прост, так как он имеет место на стороне сервера, поэтому я могу издеваться над вызовами Stripe с камнем, подобным VCR.
Шаг № 1 - это то, что мне неприятно. Я попытался проверить это, используя как puffing-billy
, так и stripe-ruby-mock
, но ничего не работает. Здесь мой собственный javascript (упрощенный):
var stripeResponseHandler = function (status, response) {
console.log("response handler called");
if (response.error) {
// show the errors on the form
} else {
// insert the token into the form so it gets submitted to the server
$("#credit_card_token").val(response.id);
// Now submit the form.
$form.get(0).submit();
}
}
$form.submit(function (event) {
// Disable the submit button to prevent repeated clicks
$submitBtn.prop("disabled", true);
event.preventDefault();
console.log("creating token...");
Stripe.createToken(
// Get the credit card details from the form
// and input them here.
}, stripeResponseHandler);
// Prevent the form from submitting the normal way.
return false;
});
Чтобы повторить, все это отлично работает, когда я тестирую его вручную. Но мои автоматические тесты терпят неудачу:
Failure/Error: expect{submit_form}.to change{User.count}.by(1)
expected result to have changed by 1, but was changed by 0
Когда я пытаюсь использовать gem puffing-billy
, он, похоже, сам кэширует stripe.js
(который загружается с собственных серверов Stripe на js.stripe.com
, не подается из моего собственного приложения, так как Stripe не поддерживает это.), но вызов, инициированный Stripe.createToken
, не кэшируется. Фактически, когда я вхожу в журналы журналов Stripe Server, кажется, что вызов даже не был выполнен (или, по крайней мере, Stripe не получает его.)
Обратите внимание на те инструкции console.log
в моем JS выше. Когда я запускаю свой тестовый пакет, строка "Создание токена..." печатается, но "обработчик ответа называется". не делает. Похоже, обработчик ответа никогда не называется.
Я забыл некоторые детали, потому что этот вопрос уже очень длинный, но может добавить больше по запросу. Что я здесь делаю неправильно? Как я могу проверить свою страницу регистрации?
ОБНОВЛЕНИЕ См. [мой комментарий к этой проблеме Github] на stripe-ruby-mock для получения дополнительной информации о том, что я пробовал и не смог.
Ответы
Ответ 1
Если я правильно понимаю...
Capybara не будет знать ваши запросы ajax. Вы должны быть в состоянии заглушить запросы AJAX с Sinatra. Попросите его вернуть приборы так же, как и видеомагнитофон.
Вот статья об этом.
https://robots.thoughtbot.com/using-capybara-to-test-javascript-that-makes-http
Вам нужно загрузить приложение Sinatra в Capybara, а затем сопоставить URL-адреса в ваших вызовах ajax.
Что-то вроде:
class FakeContinousIntegration < Sinatra::Base
def self.boot
instance = new
Capybara::Server.new(instance).tap { |server| server.boot }
end
get '/some/ajax'
# send ajax back to capybara
end
end
При загрузке сервера он вернет адрес и порт, которые вы можете записать в конфигурацию, которую может использовать ваш js.
@server = App.boot
Затем я использую адрес и порт для настройки приложения JS
def write_js_config
config['api'] = "http://#{@server.host}:#{@server.port}"
config.to_json
end
В spec_helper.rb
отправьте конфигурацию в js, чтобы ваш script указывал на ваше приложение synatra. Шахта компилируется с помощью gulp. Так что я просто создаю конфигурацию в файл перед запуском тестов:
system('gulp build --env capybara')
Ответ 2
У меня были тесты, которые работали на ручном сбое в Capybara/poltergeist из-за таймаута. В моем случае решение должно было дождаться завершения всех запросов AJAX. Ссылка
Не уверен, что Stripe.js использует JQuery внутренне, попробуйте проверить условие, установленное stripeResponseHandler
.
Ответ 3
В дополнение к трюку wait_for_ajax
, похоже, вы вызываете expect
до того, как ваша база данных была обновлена. Один из способов проверить, было бы добавить точку останова в вашем коде (binding.pry
) и проверить, является ли это проблемой гонки или нет.
Кроме того, согласно документации Capybara, введение ожидания изменения пользовательского интерфейса делает его "ловко" ожиданием завершения вызовов ajax:
expect(page).not_to have_content('Enter credit card details')