質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.37%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

RSpec

RSpecはRuby用のBDD(behaviour-driven development)フレームワークです。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Docker

Dockerは、Docker社が開発したオープンソースのコンテナー管理ソフトウェアの1つです

Q&A

0回答

1161閲覧

payjp で購入する統合テストでトークンを渡せない

divclass123

総合スコア35

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

RSpec

RSpecはRuby用のBDD(behaviour-driven development)フレームワークです。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Docker

Dockerは、Docker社が開発したオープンソースのコンテナー管理ソフトウェアの1つです

1グッド

1クリップ

投稿2021/04/20 06:15

編集2021/04/20 15:47

実現したいこと,前提

個人アプリで、購入機能の結合テストを書いていて、
購入ページに遷移=>購入に必要な項目を入力=>購入ボタンをクリック=>購入完了ページにリダイレクト

みたいな一連の動作を書いています。

購入機能に用いたgemはpayjpです。

エラー内容

docker-compose exec web bundle exec rspec spec/system/trade_addresses_spec.rb TradeAddresses 購入ができる時 必須項目を入力 (FAILED - 1) 購入ができない時 ログインしてないと購入ページに行っても、ログインページにリダイレクト 必須情報の抜け漏れ Failures: 1) TradeAddresses 購入ができる時 必須項目を入力 Failure/Error: expect{ find('input[name="commit"]').click save_page }.to change { Trade.count }.by(1) expected `Trade.count` to have changed by 1, but was changed by 0 # ./spec/system/trade_addresses_spec.rb:69:in `block (3 levels) in <main>' Finished in 3.02 seconds (files took 4.04 seconds to load) 3 examples, 1 failure Failed examples: rspec ./spec/system/trade_addresses_spec.rb:32 # TradeAddresses 購入ができる時 必須項目を入力 ERROR: 1

エラー内容はTrade.countが+1されてない。と言うことなので、
購入に必要な際の必須情報の入力漏れが起きています。
下記に記述しますが、おそらく購入の際のtokenが抜けていて、
tokenを差し込んんで購入をするテストを書くにはどうしたらいいのか。
と言うとこまでたどり着きました。

該当のソースコード

私のgithubです

trade_address_spec.rb

require 'rails_helper' RSpec.describe "TradeAddresses", type: :system do before do @user = FactoryBot.create(:user) @trade_address = FactoryBot.build(:trade_address) @admin_user = User.create(id: 6, nickname: "hoge", email: "hoge@gmail.com", password: "hogehoge", password_confirmation: "hogehoge", activated: true) @drinks = Drink.create( name: "商品", price: 340, explain: "商品の説明", user_id: 6, image: ActiveStorage::Blob.create_and_upload!(io: File.open("app/assets/images/break_first.jpg"),filename: "breake_first.jpg") ) # @drinks = @admin_user.drinks.paginate(page: params[:page],per_page: 10) # NoMethodError: # undefined method `drinks' for nil:NilClass end context "購入ができる時" do it "必須項目を入力" do # ログイン visit login_path fill_in 'email', with: @user.email fill_in 'password', with: @user.password find('input[name="commit"]').click expect(current_path).to eq(user_path(@user)) expect(page).to have_content('商品を購入') # 商品一覧ページに遷移 visit buy_path # 購入ページに遷移 visit drink_trades_path(@drinks.id) # その商品の写真が表示される # その商品の名前が表示される # その商品の値段が表示される # 必須項目を入力 fill_in 'card-number' ,with: 4242424242424242 fill_in 'card-exp-month' ,with: 12 fill_in 'card-exp-year' ,with: 24 fill_in 'card-cvc' ,with: 123 fill_in 'fam_name' ,with: @trade_address.fam_name fill_in 'first_name' ,with: @trade_address.first_name fill_in 'fam_name_kana' ,with: @trade_address.fam_name_kana fill_in 'first_name_kana' ,with: @trade_address.first_name_kana select '1960', from: '_birthday_1i' select '8', from: '_birthday_2i' select '19', from: '_birthday_3i' fill_in 'postal-code' ,with: @trade_address.postal_code find("#prefecture").find("option[value='2']").select_option fill_in 'city' ,with: @trade_address.city fill_in 'addresses' ,with: @trade_address.house_num fill_in 'phone-number' ,with: @trade_address.phone_num # 購入するをクリック # file:///Users/soichirohara/coffee_passport/capybara-202104200420558290187332.html # find('input[name="commit"]').click # expect(page).to have_content("Token can't be blank") # 当たり前だが、購入ページには遷移できていない。 # このテストがパスすると言うことはtokenが入ってない expect{ find('input[name="commit"]').click }.to change {Trade.count}.by(1) # 購入完了ページに遷移 expect(page).to have_content("商品をご購入いただきありがとうございます! ")

trade_addresses.rb

FactoryBot.define do factory :trade_address do token {'sampleToken'} fam_name {"原"} first_name {"奏一郎"} fam_name_kana {"ハラ"} first_name_kana {"ソウイチロウ"} birthday {"2000-01-01"} postal_code {'200-2000'} prefecture_id {2} city {"東京都東区"} house_num {"青山1-1-1"} building_name {"ビル103"} phone_num {'08000000000'} end end

trade_address.rb

class TradeAddress include ActiveModel::Model include ActiveRecord::AttributeAssignment include SessionsHelper # form_withやrender等の色々な機能が使える attr_accessor :fam_name,:first_name,:fam_name_kana,:first_name_kana,:birthday,:postal_code, :city, :house_num, :building_name, :phone_num, :drink_id, :prefecture_id,:trade_id, :user_id, :price,:token,:authenticity_token,:number,:exp_month,:exp_year,:cvc,:commit with_options presence: true do with_options format: { with: /\A[ぁ-んァ-ン一-龥]/, message: 'は全角で入力してください。' } do validates :fam_name validates :first_name end with_options format: { with: /\A[ァ-ヶー-]+\z/, message: 'は全角カタカナで入力して下さい。' } do validates :fam_name_kana validates :first_name_kana end validates :birthday validates :postal_code,format: {with: /\A\d{3}[-]\d{4}\z/} validates :prefecture_id, numericality: { other_than: 1 } validates :city validates :house_num validates :phone_num, format: {with: /\A\d{10,11}\z/} validates :token end def save trade = Trade.create(user_id: user_id, drink_id: drink_id) Address.create(fam_name: fam_name,first_name: first_name,fam_name_kana: fam_name_kana,first_name_kana: first_name_kana,postal_code: postal_code, prefecture_id: prefecture_id, birthday: birthday,city: city, house_num: house_num, building_name: building_name, phone_num: phone_num, trade_id: trade.id,user_id: user_id) end end

trades_controller.rb

class TradesController < ApplicationController include SessionsHelper def index # 購入ページ @item = Drink.find(params[:drink_id]) @order = TradeAddress.new @user_address = current_user.address end def new @item = Drink.find(params[:drink_id]) @order = TradeAddress.new # 商品購入ページ end def create @item = Drink.find(params[:drink_id]) @order = TradeAddress.new(trade_params) if @order.valid? pay_item @order.save else render 'index' end end def edit end private def trade_params params.permit(:drink_id,:user_id,:fam_name,:first_name,:fam_name_kana,:first_name_kana,:birthday, :postal_code, :prefecture_id, :city, :house_num, :building_name, :phone_num, :trade_id,:authenticity_token, :number, :exp_month, :exp_year, :cvc, :commit).merge(user_id: current_user.id,price: @item.price,token: params[:token]) end def pay_item Payjp.api_key = ENV["PAYJP_SECRET_KEY"] # 秘密鍵をpayjpで Payjp::Charge.create( # 受け取った値を送信 amount: trade_params[:price], card: trade_params[:token], currency: 'jpy' ) end end

card.js

文字制限のため省略させていただきます。お手数ですが、githubを参照願います。

trades/index.html.erb

文字制限のため省略させていただきます。お手数ですが、githubを参照願います。

試したこと

save_pageメソッドを使って、

trade_addresses_spec.rbに

find('input[name="commit"]').click save_page

と記述して、クリックした後のページを見たところ、
token cant be blankとバリデーション のエラーが表示されてました。

念のため

expect(page).to have_content("Token can't be blank")

を実行すると、ここのテストがパスできました。
カード情報は

fill_in 'card-number' ,with: 4242424242424242 fill_in 'card-exp-month' ,with: 12 fill_in 'card-exp-year' ,with: 24 fill_in 'card-cvc' ,with: 123

このように記載しましたが、tokenが必要みたいで、そこら辺をどうすればいいのかが分かりません。
また、payjpを用いた購入機能は某techcampの物のマルパクリなので、
他の誰かがすでにやってるのでは、と思ったのですが
モデルの単体テストばっかで、結合テストの記述が見つかりませんでした。

環境

docker上で開発をしています。
mac,docker,Docker version 20.10.5,ruby 2.6.5p114,Rails 6.1.3.1

shinoharat2👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.37%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問