add tests for controllers and ActionCable channels; improve main backend docs
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
require "rails_helper"
|
||||
|
||||
RSpec.describe ApplicationCable::Connection, type: :channel do
|
||||
include ActionCable::Connection::TestCase::Behavior
|
||||
|
||||
let(:user) { User.create!(nickname: "CaptainCook", password: "password123") }
|
||||
let(:token) { JwtService.encode(user_id: user.id) }
|
||||
|
||||
describe "#connect" do
|
||||
it "connects successfully with token in query params" do
|
||||
connect "/cable", params: { token: token }
|
||||
expect(connection.current_user).to eq(user)
|
||||
end
|
||||
|
||||
it "connects successfully with Bearer token in Authorization header" do
|
||||
connect "/cable", headers: { "Authorization" => "Bearer #{token}" }
|
||||
expect(connection.current_user).to eq(user)
|
||||
end
|
||||
|
||||
it "rejects connection when no token is provided" do
|
||||
expect { connect "/cable" }.to have_rejected_connection
|
||||
end
|
||||
|
||||
it "rejects connection when token is invalid" do
|
||||
expect {
|
||||
connect "/cable", params: { token: "invalid.jwt.token" }
|
||||
}.to have_rejected_connection
|
||||
end
|
||||
|
||||
it "rejects connection when token is expired" do
|
||||
expired_token = JwtService.encode(user_id: user.id, exp: 1.hour.ago.to_i)
|
||||
expect {
|
||||
connect "/cable", params: { token: expired_token }
|
||||
}.to have_rejected_connection
|
||||
end
|
||||
|
||||
it "rejects connection when user does not exist in the database" do
|
||||
orphan_token = JwtService.encode(user_id: 999_999)
|
||||
expect {
|
||||
connect "/cable", params: { token: orphan_token }
|
||||
}.to have_rejected_connection
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,68 @@
|
||||
require "rails_helper"
|
||||
|
||||
RSpec.describe MatchmakingChannel, type: :channel do
|
||||
let(:user) { User.create!(nickname: "Blackbeard", password: "password123", rating: 1250) }
|
||||
|
||||
before do
|
||||
stub_connection current_user: user
|
||||
end
|
||||
|
||||
describe "#subscribed" do
|
||||
it "subscribes successfully and streams from the user's private channel" do
|
||||
subscribe
|
||||
expect(subscription).to be_confirmed
|
||||
expect(subscription).to have_stream_from("matchmaking:#{user.id}")
|
||||
expect(transmissions).to be_empty
|
||||
end
|
||||
|
||||
it "transmits a claimed match if one was ready before or during connection" do
|
||||
match_payload = {
|
||||
type: "matched",
|
||||
match_id: "test-match-uuid",
|
||||
game_token: "jwt-game-token",
|
||||
game_server: "ws://localhost:8080",
|
||||
players: [ user.id, 999 ]
|
||||
}
|
||||
allow(MatchmakingService).to receive(:claim).with(user.id).and_return(match_payload)
|
||||
|
||||
subscribe
|
||||
|
||||
expect(subscription).to be_confirmed
|
||||
expect(transmissions.last).to eq(match_payload.as_json)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#start" do
|
||||
it "calls MatchmakingService.enqueue with the user's id and current rating" do
|
||||
subscribe
|
||||
|
||||
expect(MatchmakingService).to receive(:enqueue).with(user.id, rating: 1250)
|
||||
perform :start
|
||||
end
|
||||
|
||||
it "accepts extra parameters in data hash without error" do
|
||||
subscribe
|
||||
|
||||
expect(MatchmakingService).to receive(:enqueue).with(user.id, rating: 1250)
|
||||
perform :start, { "custom" => "data" }
|
||||
end
|
||||
end
|
||||
|
||||
describe "#stop" do
|
||||
it "calls MatchmakingService.cancel for the current user" do
|
||||
subscribe
|
||||
|
||||
expect(MatchmakingService).to receive(:cancel).with(user.id)
|
||||
perform :stop
|
||||
end
|
||||
end
|
||||
|
||||
describe "#unsubscribed" do
|
||||
it "cancels matchmaking search when unsubscribing" do
|
||||
subscribe
|
||||
|
||||
expect(MatchmakingService).to receive(:cancel).with(user.id)
|
||||
unsubscribe
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,41 @@
|
||||
require "rails_helper"
|
||||
|
||||
RSpec.describe Api::MatchmakingController, type: :controller do
|
||||
routes do
|
||||
ActionDispatch::Routing::RouteSet.new.tap do |r|
|
||||
r.draw do
|
||||
delete "destroy", to: "api/matchmaking#destroy"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
let(:user) { User.create!(nickname: "CaptainHook", password: "password123") }
|
||||
let(:token) { JwtService.encode(user_id: user.id) }
|
||||
|
||||
describe "DELETE #destroy" do
|
||||
context "when authenticated" do
|
||||
it "cancels matchmaking for current user and returns success message" do
|
||||
request.headers["Authorization"] = "Bearer #{token}"
|
||||
expect(MatchmakingService).to receive(:cancel).with(user.id)
|
||||
|
||||
delete :destroy
|
||||
|
||||
expect(response).to have_http_status(:ok)
|
||||
json = JSON.parse(response.body)
|
||||
expect(json["message"]).to eq("Matchmaking cancelled")
|
||||
end
|
||||
end
|
||||
|
||||
context "when unauthenticated" do
|
||||
it "returns 401 unauthorized and does not call cancel" do
|
||||
expect(MatchmakingService).not_to receive(:cancel)
|
||||
|
||||
delete :destroy
|
||||
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
json = JSON.parse(response.body)
|
||||
expect(json["error"]).to eq("Unauthorized")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,114 @@
|
||||
require "rails_helper"
|
||||
|
||||
RSpec.describe Api::RegistrationsController, type: :controller do
|
||||
describe "POST #create" do
|
||||
context "with valid parameters" do
|
||||
let(:valid_params) do
|
||||
{
|
||||
user: {
|
||||
nickname: "CaptainNemo",
|
||||
password: "secretpassword"
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
it "creates a new user and returns 201 with user data and JWT token" do
|
||||
expect {
|
||||
post :create, params: valid_params
|
||||
}.to change(User, :count).by(1)
|
||||
|
||||
expect(response).to have_http_status(:created)
|
||||
|
||||
json = JSON.parse(response.body)
|
||||
expect(json["token"]).to be_present
|
||||
expect(json["user"]).to include(
|
||||
"nickname" => "CaptainNemo",
|
||||
"avatar_url" => nil
|
||||
)
|
||||
expect(json["user"]["id"]).to be_present
|
||||
expect(json["user"]["created_at"]).to be_present
|
||||
|
||||
# Verify token is valid and decodes to created user
|
||||
decoded = JwtService.decode(json["token"])
|
||||
expect(decoded[:user_id]).to eq(json["user"]["id"])
|
||||
end
|
||||
|
||||
it "attaches avatar and returns avatar_url when avatar is provided" do
|
||||
avatar = fixture_file_upload(
|
||||
Rails.root.join("spec", "fixtures", "files", "avatar.png"),
|
||||
"image/png"
|
||||
) rescue Rack::Test::UploadedFile.new(
|
||||
StringIO.new("\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x01\x00\x00\x00\x01\x08\x06\x00\x00\x00\x1f\x15c4"),
|
||||
"image/png",
|
||||
original_filename: "avatar.png"
|
||||
)
|
||||
|
||||
params_with_avatar = valid_params.deep_merge(user: { avatar: avatar })
|
||||
|
||||
post :create, params: params_with_avatar
|
||||
expect(response).to have_http_status(:created)
|
||||
|
||||
json = JSON.parse(response.body)
|
||||
expect(json["user"]["avatar_url"]).to be_present
|
||||
|
||||
user = User.find(json["user"]["id"])
|
||||
expect(user.avatar).to be_attached
|
||||
end
|
||||
end
|
||||
|
||||
context "with invalid parameters" do
|
||||
it "returns 422 unprocessable entity when nickname is missing" do
|
||||
post :create, params: { user: { nickname: "", password: "password123" } }
|
||||
|
||||
expect(response).to have_http_status(:unprocessable_content)
|
||||
json = JSON.parse(response.body)
|
||||
expect(json["errors"]).to be_an(Array)
|
||||
expect(json["errors"]).to include("Nickname can't be blank")
|
||||
end
|
||||
|
||||
it "returns 422 unprocessable entity when password is too short" do
|
||||
post :create, params: { user: { nickname: "CaptainNemo", password: "123" } }
|
||||
|
||||
expect(response).to have_http_status(:unprocessable_content)
|
||||
json = JSON.parse(response.body)
|
||||
expect(json["errors"]).to include("Password is too short (minimum is 6 characters)")
|
||||
end
|
||||
|
||||
it "returns 422 unprocessable entity when nickname is already taken" do
|
||||
User.create!(nickname: "CaptainNemo", password: "password123")
|
||||
|
||||
post :create, params: { user: { nickname: "captainnemo", password: "password123" } }
|
||||
|
||||
expect(response).to have_http_status(:unprocessable_content)
|
||||
json = JSON.parse(response.body)
|
||||
expect(json["errors"]).to include("Nickname has already been taken")
|
||||
end
|
||||
|
||||
it "returns 422 when avatar has an unsupported content type" do
|
||||
invalid_avatar = Rack::Test::UploadedFile.new(
|
||||
StringIO.new("plain text content"),
|
||||
"text/plain",
|
||||
original_filename: "test.txt"
|
||||
)
|
||||
|
||||
post :create, params: {
|
||||
user: {
|
||||
nickname: "CaptainNemo",
|
||||
password: "password123",
|
||||
avatar: invalid_avatar
|
||||
}
|
||||
}
|
||||
|
||||
expect(response).to have_http_status(:unprocessable_content)
|
||||
json = JSON.parse(response.body)
|
||||
expect(json["errors"]).to include("Avatar must be a PNG, JPEG, GIF or WebP image")
|
||||
end
|
||||
|
||||
it "raises ParameterMissing when user param is omitted" do
|
||||
expect {
|
||||
post :create, params: {}
|
||||
}.to raise_error(ActionController::ParameterMissing)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,154 @@
|
||||
require "rails_helper"
|
||||
|
||||
RSpec.describe Api::SessionsController, type: :controller do
|
||||
let!(:user) { User.create!(nickname: "AdmiralNelson", password: "securepassword") }
|
||||
let(:token) { JwtService.encode(user_id: user.id) }
|
||||
|
||||
describe "POST #create" do
|
||||
context "with valid credentials" do
|
||||
it "returns 200 OK with user info and JWT token" do
|
||||
post :create, params: { nickname: "AdmiralNelson", password: "securepassword" }
|
||||
|
||||
expect(response).to have_http_status(:ok)
|
||||
json = JSON.parse(response.body)
|
||||
expect(json["token"]).to be_present
|
||||
expect(json["user"]).to include(
|
||||
"id" => user.id,
|
||||
"nickname" => "AdmiralNelson",
|
||||
"avatar_url" => nil
|
||||
)
|
||||
|
||||
decoded = JwtService.decode(json["token"])
|
||||
expect(decoded[:user_id]).to eq(user.id)
|
||||
end
|
||||
end
|
||||
|
||||
context "with invalid credentials" do
|
||||
it "returns 401 when password does not match" do
|
||||
post :create, params: { nickname: "AdmiralNelson", password: "wrongpassword" }
|
||||
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
json = JSON.parse(response.body)
|
||||
expect(json["error"]).to eq("Invalid nickname or password")
|
||||
expect(json["token"]).to be_nil
|
||||
end
|
||||
|
||||
it "returns 401 when user does not exist" do
|
||||
post :create, params: { nickname: "GhostCaptain", password: "securepassword" }
|
||||
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
json = JSON.parse(response.body)
|
||||
expect(json["error"]).to eq("Invalid nickname or password")
|
||||
end
|
||||
|
||||
it "returns 401 when nickname is omitted" do
|
||||
post :create, params: { password: "securepassword" }
|
||||
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
json = JSON.parse(response.body)
|
||||
expect(json["error"]).to eq("Invalid nickname or password")
|
||||
end
|
||||
|
||||
it "returns 401 when password is omitted" do
|
||||
post :create, params: { nickname: "AdmiralNelson" }
|
||||
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
json = JSON.parse(response.body)
|
||||
expect(json["error"]).to eq("Invalid nickname or password")
|
||||
end
|
||||
|
||||
it "returns 401 when credentials are blank" do
|
||||
post :create, params: { nickname: "", password: "" }
|
||||
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
json = JSON.parse(response.body)
|
||||
expect(json["error"]).to eq("Invalid nickname or password")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "DELETE #destroy" do
|
||||
context "when authenticated" do
|
||||
it "returns 200 with success message" do
|
||||
request.headers["Authorization"] = "Bearer #{token}"
|
||||
delete :destroy
|
||||
|
||||
expect(response).to have_http_status(:ok)
|
||||
json = JSON.parse(response.body)
|
||||
expect(json["message"]).to eq("Signed out successfully")
|
||||
end
|
||||
end
|
||||
|
||||
context "when unauthenticated" do
|
||||
it "returns 401 unauthorized" do
|
||||
delete :destroy
|
||||
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
json = JSON.parse(response.body)
|
||||
expect(json["error"]).to eq("Unauthorized")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "GET #me" do
|
||||
context "when authenticated with Authorization header" do
|
||||
it "returns 200 with user data" do
|
||||
request.headers["Authorization"] = "Bearer #{token}"
|
||||
get :me
|
||||
|
||||
expect(response).to have_http_status(:ok)
|
||||
json = JSON.parse(response.body)
|
||||
expect(json["user"]).to include(
|
||||
"id" => user.id,
|
||||
"nickname" => "AdmiralNelson",
|
||||
"avatar_url" => nil
|
||||
)
|
||||
end
|
||||
|
||||
it "includes avatar_url when user has an attached avatar" do
|
||||
user.avatar.attach(
|
||||
io: StringIO.new("\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x01\x00\x00\x00\x01\x08\x06\x00\x00\x00\x1f\x15c4"),
|
||||
filename: "avatar.png",
|
||||
content_type: "image/png"
|
||||
)
|
||||
|
||||
request.headers["Authorization"] = "Bearer #{token}"
|
||||
get :me
|
||||
|
||||
expect(response).to have_http_status(:ok)
|
||||
json = JSON.parse(response.body)
|
||||
expect(json["user"]["avatar_url"]).to be_present
|
||||
end
|
||||
end
|
||||
|
||||
context "when authenticated with token in query params" do
|
||||
it "returns 200 with user data" do
|
||||
get :me, params: { token: token }
|
||||
|
||||
expect(response).to have_http_status(:ok)
|
||||
json = JSON.parse(response.body)
|
||||
expect(json["user"]["id"]).to eq(user.id)
|
||||
end
|
||||
end
|
||||
|
||||
context "when unauthenticated" do
|
||||
it "returns 401 unauthorized" do
|
||||
get :me
|
||||
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
json = JSON.parse(response.body)
|
||||
expect(json["error"]).to eq("Unauthorized")
|
||||
end
|
||||
end
|
||||
|
||||
context "when token is expired" do
|
||||
it "returns 401 unauthorized" do
|
||||
expired_token = JwtService.encode(user_id: user.id, exp: 1.hour.ago.to_i)
|
||||
request.headers["Authorization"] = "Bearer #{expired_token}"
|
||||
get :me
|
||||
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,58 @@
|
||||
require "rails_helper"
|
||||
|
||||
RSpec.describe ApplicationController, type: :controller do
|
||||
controller do
|
||||
def index
|
||||
render json: { user_id: current_user.id }
|
||||
end
|
||||
end
|
||||
|
||||
let(:user) { User.create!(nickname: "alice", password: "password123") }
|
||||
let(:token) { JwtService.encode(user_id: user.id) }
|
||||
|
||||
describe "#authenticate_request!" do
|
||||
context "with valid Bearer token in Authorization header" do
|
||||
it "sets current_user and succeeds" do
|
||||
request.headers["Authorization"] = "Bearer #{token}"
|
||||
get :index
|
||||
expect(response).to have_http_status(:ok)
|
||||
expect(JSON.parse(response.body)).to eq({ "user_id" => user.id })
|
||||
end
|
||||
end
|
||||
|
||||
context "with valid token in params" do
|
||||
it "sets current_user and succeeds" do
|
||||
get :index, params: { token: token }
|
||||
expect(response).to have_http_status(:ok)
|
||||
expect(JSON.parse(response.body)).to eq({ "user_id" => user.id })
|
||||
end
|
||||
end
|
||||
|
||||
context "without token" do
|
||||
it "returns 401 unauthorized" do
|
||||
get :index
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
expect(JSON.parse(response.body)).to eq({ "error" => "Unauthorized" })
|
||||
end
|
||||
end
|
||||
|
||||
context "with invalid token" do
|
||||
it "returns 401 unauthorized" do
|
||||
request.headers["Authorization"] = "Bearer invalid_token"
|
||||
get :index
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
expect(JSON.parse(response.body)).to eq({ "error" => "Unauthorized" })
|
||||
end
|
||||
end
|
||||
|
||||
context "with token for nonexistent user" do
|
||||
it "returns 401 unauthorized" do
|
||||
orphan_token = JwtService.encode(user_id: 999_999)
|
||||
request.headers["Authorization"] = "Bearer #{orphan_token}"
|
||||
get :index
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
expect(JSON.parse(response.body)).to eq({ "error" => "Unauthorized" })
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,10 @@
|
||||
require "rails_helper"
|
||||
|
||||
RSpec.describe MatchmakingSweepJob, type: :job do
|
||||
describe "#perform" do
|
||||
it "calls MatchmakingService.sweep" do
|
||||
expect(MatchmakingService).to receive(:sweep)
|
||||
described_class.new.perform
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -38,6 +38,27 @@ RSpec.describe User, type: :model do
|
||||
expect(duplicate).not_to be_valid
|
||||
expect(duplicate.errors[:nickname]).to be_present
|
||||
end
|
||||
|
||||
it "accepts valid image formats for avatar" do
|
||||
user = User.new(valid_attributes)
|
||||
user.avatar.attach(
|
||||
io: StringIO.new("\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x01\x00\x00\x00\x01\x08\x06\x00\x00\x00\x1f\x15c4"),
|
||||
filename: "avatar.png",
|
||||
content_type: "image/png"
|
||||
)
|
||||
expect(user).to be_valid
|
||||
end
|
||||
|
||||
it "rejects unsupported mime types for avatar" do
|
||||
user = User.new(valid_attributes)
|
||||
user.avatar.attach(
|
||||
io: StringIO.new("plain text"),
|
||||
filename: "test.txt",
|
||||
content_type: "text/plain"
|
||||
)
|
||||
expect(user).not_to be_valid
|
||||
expect(user.errors[:avatar]).to include("must be a PNG, JPEG, GIF or WebP image")
|
||||
end
|
||||
end
|
||||
|
||||
describe "rating" do
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
if ENV["COVERAGE"]
|
||||
require "simplecov"
|
||||
SimpleCov.start "rails" do
|
||||
add_filter "/spec/"
|
||||
skip "/spec/"
|
||||
end
|
||||
end
|
||||
require 'spec_helper'
|
||||
@@ -69,7 +69,7 @@ RSpec.configure do |config|
|
||||
# behaviour is considered legacy and will be removed in a future version.
|
||||
#
|
||||
# To enable this behaviour uncomment the line below.
|
||||
# config.infer_spec_type_from_file_location!
|
||||
config.infer_spec_type_from_file_location!
|
||||
|
||||
# Filter lines from Rails gems in backtraces.
|
||||
config.filter_rails_from_backtrace!
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
require "rails_helper"
|
||||
|
||||
RSpec.describe "Registrations API", type: :request do
|
||||
describe "POST /api/register" do
|
||||
let(:valid_attributes) do
|
||||
{
|
||||
user: {
|
||||
nickname: "Sinbad",
|
||||
password: "password123"
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
context "with valid parameters" do
|
||||
it "registers a new user and returns 201 Created with token" do
|
||||
expect {
|
||||
post "/api/register", params: valid_attributes, as: :json
|
||||
}.to change(User, :count).by(1)
|
||||
|
||||
expect(response).to have_http_status(:created)
|
||||
json = JSON.parse(response.body)
|
||||
|
||||
expect(json["token"]).to be_present
|
||||
expect(json["user"]["nickname"]).to eq("Sinbad")
|
||||
expect(json["user"]["id"]).to eq(User.last.id)
|
||||
expect(json["user"]["avatar_url"]).to be_nil
|
||||
expect(json["user"]["created_at"]).to be_present
|
||||
end
|
||||
end
|
||||
|
||||
context "with invalid parameters" do
|
||||
it "returns 422 Unprocessable Content when nickname is taken" do
|
||||
User.create!(nickname: "Sinbad", password: "password123")
|
||||
|
||||
post "/api/register", params: valid_attributes, as: :json
|
||||
|
||||
expect(response).to have_http_status(422)
|
||||
json = JSON.parse(response.body)
|
||||
expect(json["errors"]).to include("Nickname has already been taken")
|
||||
end
|
||||
|
||||
it "returns 422 Unprocessable Content when password is too short" do
|
||||
invalid_attrs = { user: { nickname: "Sinbad", password: "123" } }
|
||||
post "/api/register", params: invalid_attrs, as: :json
|
||||
|
||||
expect(response).to have_http_status(422)
|
||||
json = JSON.parse(response.body)
|
||||
expect(json["errors"]).to include("Password is too short (minimum is 6 characters)")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,61 @@
|
||||
require "rails_helper"
|
||||
|
||||
RSpec.describe "Sessions API", type: :request do
|
||||
let!(:user) { User.create!(nickname: "Columbus", password: "securepassword") }
|
||||
let(:token) { JwtService.encode(user_id: user.id) }
|
||||
|
||||
describe "POST /api/login" do
|
||||
it "logs in with valid credentials and returns 200 OK with token" do
|
||||
post "/api/login", params: { nickname: "Columbus", password: "securepassword" }, as: :json
|
||||
|
||||
expect(response).to have_http_status(:ok)
|
||||
json = JSON.parse(response.body)
|
||||
expect(json["token"]).to be_present
|
||||
expect(json["user"]["id"]).to eq(user.id)
|
||||
expect(json["user"]["nickname"]).to eq("Columbus")
|
||||
end
|
||||
|
||||
it "returns 401 Unauthorized with invalid credentials" do
|
||||
post "/api/login", params: { nickname: "Columbus", password: "wrongpassword" }, as: :json
|
||||
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
json = JSON.parse(response.body)
|
||||
expect(json["error"]).to eq("Invalid nickname or password")
|
||||
end
|
||||
end
|
||||
|
||||
describe "DELETE /api/logout" do
|
||||
it "signs out successfully when bearer token is supplied" do
|
||||
delete "/api/logout", headers: { "Authorization" => "Bearer #{token}" }
|
||||
|
||||
expect(response).to have_http_status(:ok)
|
||||
json = JSON.parse(response.body)
|
||||
expect(json["message"]).to eq("Signed out successfully")
|
||||
end
|
||||
|
||||
it "returns 401 Unauthorized when unauthenticated" do
|
||||
delete "/api/logout"
|
||||
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
|
||||
describe "GET /api/me" do
|
||||
it "returns user profile with Bearer authorization header" do
|
||||
get "/api/me", headers: { "Authorization" => "Bearer #{token}" }
|
||||
|
||||
expect(response).to have_http_status(:ok)
|
||||
json = JSON.parse(response.body)
|
||||
expect(json["user"]["id"]).to eq(user.id)
|
||||
expect(json["user"]["nickname"]).to eq("Columbus")
|
||||
end
|
||||
|
||||
it "returns 401 Unauthorized when Authorization header is missing" do
|
||||
get "/api/me"
|
||||
|
||||
expect(response).to have_http_status(:unauthorized)
|
||||
json = JSON.parse(response.body)
|
||||
expect(json["error"]).to eq("Unauthorized")
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user