388 lines
12 KiB
Ruby
388 lines
12 KiB
Ruby
# frozen_sTring_literal: true
|
|
|
|
require "spec_helper"
|
|
|
|
describe Api::V1::PhotosController do
|
|
let(:auth) {
|
|
FactoryGirl.create(
|
|
:auth_with_default_scopes,
|
|
scopes: %w[openid public:read public:modify private:read private:modify]
|
|
)
|
|
}
|
|
|
|
let(:auth_public_only) {
|
|
FactoryGirl.create(
|
|
:auth_with_default_scopes,
|
|
scopes: %w[openid public:read public:modify]
|
|
)
|
|
}
|
|
|
|
let(:auth_read_only) {
|
|
FactoryGirl.create(
|
|
:auth_with_default_scopes,
|
|
scopes: %w[openid public:read private:read]
|
|
)
|
|
}
|
|
|
|
let(:auth_public_only_read_only) {
|
|
FactoryGirl.create(
|
|
:auth_with_default_scopes,
|
|
scopes: %w[openid public:read]
|
|
)
|
|
}
|
|
|
|
let(:auth_minimum_scopes) {
|
|
FactoryGirl.create(:auth_with_default_scopes)
|
|
}
|
|
|
|
let!(:access_token) { auth.create_access_token.to_s }
|
|
let!(:access_token_public_only) { auth_public_only.create_access_token.to_s }
|
|
let!(:access_token_read_only) { auth_read_only.create_access_token.to_s }
|
|
let!(:access_token_public_only_read_only) { auth_public_only_read_only.create_access_token.to_s }
|
|
let!(:access_token_minimum_scopes) { auth_minimum_scopes.create_access_token.to_s }
|
|
let(:invalid_token) { SecureRandom.hex(9) }
|
|
|
|
before do
|
|
alice_private_spec = alice.aspects.create(name: "private aspect")
|
|
alice.share_with(eve.person, alice_private_spec)
|
|
@private_photo1 = alice.post(:photo, pending: false, user_file: File.open(photo_fixture_name),
|
|
to: alice_private_spec.id)
|
|
@alice_public_photo = alice.post(:photo, pending: false, user_file: File.open(photo_fixture_name), public: true)
|
|
@user_photo1 = auth.user.post(:photo, pending: true, user_file: File.open(photo_fixture_name), to: "all")
|
|
@user_photo2 = auth.user.post(:photo, pending: true, user_file: File.open(photo_fixture_name), to: "all")
|
|
message_data = {status_message: {text: "Post with photos"}, public: true, photos: [@user_photo2.id.to_s]}
|
|
@status_message = StatusMessageCreationService.new(auth.user).create(message_data)
|
|
@user_photo2.reload
|
|
|
|
shared_spec = auth_public_only_read_only.user.aspects.create(name: "shared aspect")
|
|
auth_public_only_read_only.user.share_with(auth_public_only_read_only.user.person, shared_spec)
|
|
auth_public_only_read_only.user.share_with(auth_read_only.user.person, shared_spec)
|
|
|
|
@shared_photo1 = auth_public_only_read_only.user.post(
|
|
:photo,
|
|
pending: false,
|
|
user_file: File.open(photo_fixture_name),
|
|
to: shared_spec.id
|
|
)
|
|
end
|
|
|
|
describe "#show" do
|
|
context "succeeds" do
|
|
it "with correct GUID user's photo and access token" do
|
|
get(
|
|
api_v1_photo_path(@user_photo1.guid),
|
|
params: {access_token: access_token}
|
|
)
|
|
expect(response.status).to eq(200)
|
|
photo = response_body(response)
|
|
expect(photo.has_key?("post")).to be_falsey
|
|
confirm_photo_format(photo, @user_photo1, auth.user)
|
|
end
|
|
|
|
it "with correct GUID user's photo used in post and access token" do
|
|
get(
|
|
api_v1_photo_path(@user_photo2.guid),
|
|
params: {access_token: access_token}
|
|
)
|
|
expect(response.status).to eq(200)
|
|
photo = response_body(response)
|
|
expect(photo.has_key?("post")).to be_truthy
|
|
confirm_photo_format(photo, @user_photo2, auth.user)
|
|
end
|
|
|
|
it "with correct GUID of other user's public photo and access token" do
|
|
get(
|
|
api_v1_photo_path(@alice_public_photo.guid),
|
|
params: {access_token: access_token}
|
|
)
|
|
expect(response.status).to eq(200)
|
|
photo = response_body(response)
|
|
confirm_photo_format(photo, @alice_public_photo, alice)
|
|
end
|
|
end
|
|
|
|
context "fails" do
|
|
it "with other this user's private photo without private:read scope in token" do
|
|
get(
|
|
api_v1_photo_path(@shared_photo1.guid),
|
|
params: {access_token: access_token_public_only_read_only}
|
|
)
|
|
expect(response.status).to eq(404)
|
|
expect(response.body).to eq(I18n.t("api.endpoint_errors.photos.not_found"))
|
|
end
|
|
|
|
it "with other user's private photo" do
|
|
get(
|
|
api_v1_photo_path(@private_photo1.guid),
|
|
params: {access_token: access_token}
|
|
)
|
|
expect(response.status).to eq(404)
|
|
expect(response.body).to eq(I18n.t("api.endpoint_errors.photos.not_found"))
|
|
end
|
|
|
|
it "with invalid GUID" do
|
|
get(
|
|
api_v1_photo_path("999_999_999"),
|
|
params: {access_token: access_token}
|
|
)
|
|
expect(response.status).to eq(404)
|
|
expect(response.body).to eq(I18n.t("api.endpoint_errors.photos.not_found"))
|
|
end
|
|
|
|
it "with invalid access token" do
|
|
delete(
|
|
api_v1_photo_path(@user_photo1.guid),
|
|
params: {access_token: invalid_token}
|
|
)
|
|
expect(response.status).to eq(401)
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "#index" do
|
|
context "succeeds" do
|
|
it "with correct access token" do
|
|
get(
|
|
api_v1_photos_path,
|
|
params: {access_token: access_token}
|
|
)
|
|
expect(response.status).to eq(200)
|
|
photos = response_body_data(response)
|
|
expect(photos.length).to eq(2)
|
|
end
|
|
end
|
|
|
|
context "only lists public photos" do
|
|
before do
|
|
auth_public_only_read_only.user.post(:photo, pending: false, user_file: File.open(photo_fixture_name),
|
|
public: true)
|
|
end
|
|
|
|
it "with correct only public scope token" do
|
|
get(
|
|
api_v1_photos_path,
|
|
params: {access_token: access_token_public_only_read_only}
|
|
)
|
|
expect(response.status).to eq(200)
|
|
photos = response_body_data(response)
|
|
expect(photos.length).to eq(1)
|
|
end
|
|
end
|
|
|
|
context "fails" do
|
|
it "with invalid access token" do
|
|
delete(
|
|
api_v1_photos_path,
|
|
params: {access_token: invalid_token}
|
|
)
|
|
expect(response.status).to eq(401)
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "#create" do
|
|
before do
|
|
@encoded_photo = Rack::Test::UploadedFile.new(
|
|
Rails.root.join("spec", "fixtures", "button.png").to_s,
|
|
"image/png"
|
|
)
|
|
end
|
|
|
|
context "succeeds" do
|
|
it "with valid encoded file no arguments" do
|
|
post(
|
|
api_v1_photos_path,
|
|
params: {image: @encoded_photo, access_token: access_token}
|
|
)
|
|
expect(response.status).to eq(200)
|
|
photo = response_body(response)
|
|
ref_photo = auth.user.photos.reload.find_by(guid: photo["guid"])
|
|
expect(ref_photo.pending).to be_falsey
|
|
confirm_photo_format(photo, ref_photo, auth.user)
|
|
end
|
|
|
|
it "with valid encoded file set as pending" do
|
|
post(
|
|
api_v1_photos_path,
|
|
params: {image: @encoded_photo, pending: false, access_token: access_token}
|
|
)
|
|
expect(response.status).to eq(200)
|
|
photo = response_body(response)
|
|
expect(photo.has_key?("post")).to be_falsey
|
|
ref_photo = auth.user.photos.reload.find_by(guid: photo["guid"])
|
|
expect(ref_photo.pending).to be_falsey
|
|
confirm_photo_format(photo, ref_photo, auth.user)
|
|
|
|
post(
|
|
api_v1_photos_path,
|
|
params: {image: @encoded_photo, pending: true, access_token: access_token}
|
|
)
|
|
expect(response.status).to eq(200)
|
|
photo = response_body(response)
|
|
ref_photo = auth.user.photos.reload.find_by(guid: photo["guid"])
|
|
expect(ref_photo.pending).to be_truthy
|
|
end
|
|
|
|
it "with valid encoded file as profile photo" do
|
|
post(
|
|
api_v1_photos_path,
|
|
params: {image: @encoded_photo, set_profile_photo: true, access_token: access_token}
|
|
)
|
|
expect(response.status).to eq(200)
|
|
photo = response_body(response)
|
|
expect(auth.user.reload.person.profile.image_url_small).to eq(photo["sizes"]["small"])
|
|
end
|
|
end
|
|
|
|
context "fails" do
|
|
it "with no image" do
|
|
post(
|
|
api_v1_photos_path,
|
|
params: {access_token: access_token}
|
|
)
|
|
expect(response.status).to eq(422)
|
|
expect(response.body).to eq(I18n.t("api.endpoint_errors.photos.failed_create"))
|
|
end
|
|
|
|
it "with non-image file" do
|
|
text_file = Rack::Test::UploadedFile.new(
|
|
Rails.root.join("README.md").to_s,
|
|
"text/plain"
|
|
)
|
|
post(
|
|
api_v1_photos_path,
|
|
params: {image: text_file, access_token: access_token}
|
|
)
|
|
expect(response.status).to eq(422)
|
|
expect(response.body).to eq(I18n.t("api.endpoint_errors.photos.failed_create"))
|
|
end
|
|
|
|
it "with impromperly identified file" do
|
|
text_file = Rack::Test::UploadedFile.new(
|
|
Rails.root.join("README.md").to_s,
|
|
"image/png"
|
|
)
|
|
post(
|
|
api_v1_photos_path,
|
|
params: {image: text_file, access_token: access_token}
|
|
)
|
|
expect(response.status).to eq(422)
|
|
expect(response.body).to eq(I18n.t("api.endpoint_errors.photos.failed_create"))
|
|
end
|
|
|
|
it "with invalid access token" do
|
|
post(
|
|
api_v1_photos_path,
|
|
params: {image: @encoded_photo, access_token: invalid_token}
|
|
)
|
|
expect(response.status).to eq(401)
|
|
end
|
|
|
|
it "with read only access token" do
|
|
post(
|
|
api_v1_photos_path,
|
|
params: {image: @encoded_photo, access_token: access_token_read_only}
|
|
)
|
|
expect(response.status).to eq(403)
|
|
end
|
|
|
|
it "with private photo and no private:modify access token" do
|
|
post(
|
|
api_v1_photos_path,
|
|
params: {image: @encoded_photo, access_token: access_token_public_only_read_only}
|
|
)
|
|
expect(response.status).to eq(403)
|
|
end
|
|
end
|
|
end
|
|
|
|
describe "#destroy" do
|
|
context "succeeds" do
|
|
it "with correct GUID and access token" do
|
|
expect(auth.user.photos.find_by(id: @user_photo1.id)).to eq(@user_photo1)
|
|
delete(
|
|
api_v1_photo_path(@user_photo1.guid),
|
|
params: {access_token: access_token}
|
|
)
|
|
expect(response.status).to eq(204)
|
|
expect(auth.user.photos.find_by(id: @user_photo1.id)).to be_nil
|
|
end
|
|
end
|
|
|
|
context "fails" do
|
|
it "with other user's photo GUID and access token" do
|
|
delete(
|
|
api_v1_photo_path(@alice_public_photo.guid),
|
|
params: {access_token: access_token}
|
|
)
|
|
expect(response.status).to eq(404)
|
|
expect(response.body).to eq(I18n.t("api.endpoint_errors.photos.not_found"))
|
|
end
|
|
|
|
it "with other invalid GUID" do
|
|
delete(
|
|
api_v1_photo_path("999_999_999"),
|
|
params: {access_token: access_token}
|
|
)
|
|
expect(response.status).to eq(404)
|
|
expect(response.body).to eq(I18n.t("api.endpoint_errors.photos.not_found"))
|
|
end
|
|
|
|
it "with invalid access token" do
|
|
delete(
|
|
api_v1_photo_path(@user_photo1.guid),
|
|
params: {access_token: invalid_token}
|
|
)
|
|
expect(response.status).to eq(401)
|
|
end
|
|
|
|
it "with read only access token" do
|
|
delete(
|
|
api_v1_photo_path(@user_photo1.guid),
|
|
params: {access_token: access_token_read_only}
|
|
)
|
|
expect(response.status).to eq(403)
|
|
end
|
|
|
|
it "with private photo and no private:modify token" do
|
|
delete(
|
|
api_v1_photo_path(@shared_photo1.guid),
|
|
params: {access_token: access_token_public_only_read_only}
|
|
)
|
|
expect(response.status).to eq(403)
|
|
end
|
|
end
|
|
end
|
|
|
|
def response_body(response)
|
|
JSON.parse(response.body)
|
|
end
|
|
|
|
def response_body_data(response)
|
|
response_body(response)["data"]
|
|
end
|
|
|
|
# rubocop:disable Metrics/AbcSize
|
|
def confirm_photo_format(photo, ref_photo, ref_user)
|
|
expect(photo["guid"]).to eq(ref_photo.guid)
|
|
if ref_photo.status_message_guid
|
|
expect(photo["post"]).to eq(ref_photo.status_message_guid)
|
|
else
|
|
expect(photo.has_key?("post")).to be_falsey
|
|
end
|
|
expect(photo["dimensions"].has_key?("height")).to be_truthy
|
|
expect(photo["dimensions"].has_key?("width")).to be_truthy
|
|
expect(photo["sizes"]["small"]).to be_truthy
|
|
expect(photo["sizes"]["medium"]).to be_truthy
|
|
expect(photo["sizes"]["large"]).to be_truthy
|
|
confirm_person_format(photo["author"], ref_user)
|
|
end
|
|
|
|
def confirm_person_format(post_person, user)
|
|
expect(post_person["guid"]).to eq(user.guid)
|
|
expect(post_person["diaspora_id"]).to eq(user.diaspora_handle)
|
|
expect(post_person["name"]).to eq(user.name)
|
|
expect(post_person["avatar"]).to eq(user.profile.image_url)
|
|
end
|
|
# rubocop:enable Metrics/AbcSize
|
|
end
|