Rspec 3 jak testować wiadomości flash

81

Chcę przetestować działanie kontrolera i obecność wiadomości flash za pomocą rspec.

akcja :

def create
  user = Users::User.find_by_email(params[:email])
  if user
    user.send_reset_password_instructions
    flash[:success] = "Reset password instructions have been sent to #{user.email}."
  else
    flash[:alert] = "Can't find user with this email: #{params[:email]}"
  end

  redirect_to root_path
end

specyfikacja :

describe "#create" do
  it "sends reset password instructions if user exists" do
    post :create, email: "[email protected]"      
    expect(response).to redirect_to(root_path)
    expect(flash[:success]).to be_present
  end
...

Ale mam błąd:

Failure/Error: expect(flash[:success]).to be_present
   expected `nil.present?` to return true, got false
Mike Andrianov
źródło

Odpowiedzi:

67

Testujesz obecność flash[:success], ale używasz kontroleraflash[:notice]

rabusmar
źródło
Och, przepraszam, po prostu się tu poślizgnęłam. Ten sam błąd z flashowaniem [: notice]
Mike Andrianov
3
W takim przypadku problem prawdopodobnie dotyczy kodu kontrolera i / lub danych testowych. Spróbuj zmienić expect(flash[:notice])TO expect(flash[:alert]), a jeśli test przechodzi następnie prawdopodobnie jest to tylko, że wiadomość testowa nie istnieje.
rabusmar
48

Najlepszym sposobem testowania wiadomości flash jest klejnot powinien .

Oto trzy przykłady:

expect(controller).to set_flash
expect(controller).to set_flash[:success]
expect(controller).to set_flash[:alert].to(/are not valid/).now
Robin Daugherty
źródło
34

Jeśli jesteś bardziej zainteresowany treścią wiadomości flash, możesz użyć tego:

expect(flash[:success]).to match(/Reset password instructions have been sent to .*/)

lub

expect(flash[:alert]).to match(/Can't find user with this email: .*/)

Odradzałbym sprawdzanie konkretnej wiadomości, chyba że jest ona krytyczna i / lub nie zmienia się często.

Mugur „Bud” Chirica
źródło
5

Z: gem 'shoulda-matchers', '~> 3.1'

.nowPowinny być wywoływane bezpośrednio na set_flash.

Używanie set_flashz nowkwalifikatorem i określanie nowpo innych kwalifikatorach nie jest już dozwolone.

Będziesz chciał użyć nownatychmiast po set_flash. Na przykład:

# Valid
should set_flash.now[:foo]
should set_flash.now[:foo].to('bar')

# Invalid
should set_flash[:foo].now
should set_flash[:foo].to('bar').now
killerkiara
źródło
0

Innym podejściem jest pominięcie faktu, że kontroler ma komunikaty flash i zamiast tego napisać test integracji. W ten sposób zwiększysz szanse, że nie będziesz musiał zmieniać testu, gdy zdecydujesz się pokazać tę wiadomość za pomocą JavaScript lub w inny sposób.

Zobacz też https://stackoverflow.com/a/13897912/2987689

Artur Beljajev
źródło