mirror of
https://github.com/Growstuff/growstuff.git
synced 2026-01-18 06:17:49 -05:00
390 lines
12 KiB
Ruby
390 lines
12 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require 'rails_helper'
|
|
|
|
describe Member do
|
|
context 'valid member' do
|
|
let!(:member) { FactoryBot.create(:member, login_name: 'hinemoa') }
|
|
|
|
describe 'should be fetchable from the database' do
|
|
subject { Member.find(member.id) }
|
|
|
|
it { is_expected.to be_an_instance_of Member }
|
|
it { expect(subject.encrypted_password).not_to be_nil }
|
|
end
|
|
|
|
describe 'should have a friendly slug' do
|
|
it { expect(member.slug).to eq('hinemoa') }
|
|
end
|
|
|
|
it 'has a bio' do
|
|
member.bio = 'I love seeds'
|
|
expect(member.bio).to eq 'I love seeds'
|
|
end
|
|
|
|
it 'has a default garden' do
|
|
expect(member.gardens.count).to eq 1
|
|
end
|
|
|
|
it "doesn't show email by default" do
|
|
expect(member.show_email).to be false
|
|
end
|
|
|
|
it 'stringifies as the login_name' do
|
|
expect(member.to_s).to eq 'hinemoa'
|
|
end
|
|
|
|
it 'is able to fetch posts' do
|
|
post = FactoryBot.create(:post, author: member)
|
|
expect(member.posts).to eq [post]
|
|
end
|
|
|
|
it 'is able to fetch gardens' do
|
|
expect(member.gardens.first.name).to eq "Garden"
|
|
end
|
|
|
|
it 'has many plantings' do
|
|
FactoryBot.create(:planting, owner: member)
|
|
member.plantings.size.should eq 1
|
|
end
|
|
|
|
it "has many comments" do
|
|
FactoryBot.create(:comment, author: member)
|
|
FactoryBot.create(:comment, author: member)
|
|
member.comments.size.should == 2
|
|
end
|
|
|
|
it "has many forums" do
|
|
FactoryBot.create(:forum, owner: member)
|
|
FactoryBot.create(:forum, owner: member)
|
|
member.forums.size.should == 2
|
|
end
|
|
|
|
it "has many likes" do
|
|
@post1 = FactoryBot.create(:post, author: member)
|
|
@post2 = FactoryBot.create(:post, author: member)
|
|
@like1 = FactoryBot.create(:like, member:, likeable: @post1)
|
|
@like2 = FactoryBot.create(:like, member:, likeable: @post2)
|
|
|
|
expect(member.likes.length).to eq 2
|
|
end
|
|
|
|
it 'has location and lat/long fields' do
|
|
member.update(location: 'Greenwich, UK')
|
|
member.location.should eq 'Greenwich, UK'
|
|
member.latitude.round(2).should eq 51.48
|
|
member.longitude.round(2).should eq 0.00
|
|
end
|
|
|
|
it 'empties the lat/long if location removed' do
|
|
member.update(location: 'Greenwich, UK')
|
|
member.update(location: '')
|
|
member.location.should eq ''
|
|
member.latitude.should be_nil
|
|
member.longitude.should be_nil
|
|
end
|
|
|
|
it 'fails gracefully for unfound locations' do
|
|
member.update(location: 'Tatooine')
|
|
member.location.should eq 'Tatooine'
|
|
member.latitude.should be_nil
|
|
member.longitude.should be_nil
|
|
end
|
|
end
|
|
|
|
context 'no TOS agreement' do
|
|
let(:member) { FactoryBot.build(:no_tos_member) }
|
|
|
|
it "refuses to save a member who hasn't agreed to the TOS" do
|
|
member.save.should_not be(true)
|
|
end
|
|
end
|
|
|
|
context 'newsletter scope' do
|
|
it 'finds newsletter recipients' do
|
|
member1 = FactoryBot.create(:member)
|
|
member2 = FactoryBot.create(:newsletter_recipient_member)
|
|
Member.wants_newsletter.should include member2
|
|
Member.wants_newsletter.should_not include member1
|
|
end
|
|
end
|
|
|
|
context 'same :login_name' do
|
|
it "does not allow two members with the same login_name" do
|
|
FactoryBot.create(:member, login_name: "bob")
|
|
member = FactoryBot.build(:member, login_name: "bob")
|
|
member.should_not be_valid
|
|
member.errors[:login_name].should include("has already been taken")
|
|
end
|
|
|
|
it "tests uniqueness case-insensitively" do
|
|
FactoryBot.create(:member, login_name: "bob")
|
|
member = FactoryBot.build(:member, login_name: "BoB")
|
|
member.should_not be_valid
|
|
member.errors[:login_name].should include("has already been taken")
|
|
end
|
|
end
|
|
|
|
context 'case sensitivity' do
|
|
it 'preserves case of login name' do
|
|
FactoryBot.create(:member, login_name: "BOB")
|
|
Member.find('bob').login_name.should eq 'BOB'
|
|
end
|
|
end
|
|
|
|
context 'invalid login names' do
|
|
it "doesn't allow short names" do
|
|
member = FactoryBot.build(:invalid_member_shortname)
|
|
member.should_not be_valid
|
|
member.errors[:login_name].should include("should be between 2 and 25 characters long")
|
|
end
|
|
|
|
it "doesn't allow really long names" do
|
|
member = FactoryBot.build(:invalid_member_longname)
|
|
member.should_not be_valid
|
|
member.errors[:login_name].should include("should be between 2 and 25 characters long")
|
|
end
|
|
|
|
it "doesn't allow spaces in names" do
|
|
member = FactoryBot.build(:invalid_member_spaces)
|
|
member.should_not be_valid
|
|
member.errors[:login_name].should include("may only include letters, numbers, or underscores")
|
|
end
|
|
|
|
it "doesn't allow other chars in names" do
|
|
member = FactoryBot.build(:invalid_member_badchars)
|
|
member.should_not be_valid
|
|
member.errors[:login_name].should include("may only include letters, numbers, or underscores")
|
|
end
|
|
|
|
it "doesn't allow reserved names" do
|
|
member = FactoryBot.build(:invalid_member_badname)
|
|
member.should_not be_valid
|
|
member.errors[:login_name].should include("name is reserved")
|
|
end
|
|
end
|
|
|
|
context 'valid login names' do
|
|
it "allows plain alphanumeric chars in names" do
|
|
member = FactoryBot.build(:valid_member_alphanumeric)
|
|
member.should be_valid
|
|
end
|
|
|
|
it "allows uppercase chars in names" do
|
|
member = FactoryBot.build(:valid_member_uppercase)
|
|
member.should be_valid
|
|
end
|
|
|
|
it "allows underscores in names" do
|
|
member = FactoryBot.build(:valid_member_underscore)
|
|
member.should be_valid
|
|
end
|
|
end
|
|
|
|
context 'roles' do
|
|
let(:member) { FactoryBot.create(:member) }
|
|
let(:role) { FactoryBot.create(:role) }
|
|
|
|
before do
|
|
member.roles << role
|
|
end
|
|
|
|
it 'has a role' do
|
|
member.roles.first.should eq role
|
|
member.role?(:moderator).should be true
|
|
end
|
|
|
|
it 'sets up roles in factories' do
|
|
admin = FactoryBot.create(:admin_member)
|
|
admin.role?(:admin).should be true
|
|
end
|
|
|
|
it 'converts role names properly' do
|
|
# need to make sure spaces get turned to underscores
|
|
role = FactoryBot.create(:role, name: "a b c")
|
|
member.roles << role
|
|
member.role?(:a_b_c).should be true
|
|
end
|
|
end
|
|
|
|
context 'confirmed scope' do
|
|
before do
|
|
FactoryBot.create(:member)
|
|
FactoryBot.create(:member)
|
|
end
|
|
|
|
it 'sees confirmed members' do
|
|
Member.confirmed.size.should == 2
|
|
end
|
|
|
|
it 'ignores unconfirmed members' do
|
|
FactoryBot.create(:unconfirmed_member)
|
|
Member.confirmed.size.should == 2
|
|
end
|
|
end
|
|
|
|
context 'located scope' do
|
|
# located members must have location, lat, long
|
|
it 'finds members who have locations' do
|
|
london_member = FactoryBot.create(:london_member)
|
|
Member.located.should include london_member
|
|
end
|
|
|
|
it 'ignores members with blank locations' do
|
|
nowhere_member = FactoryBot.create(:member)
|
|
Member.located.should_not include nowhere_member
|
|
end
|
|
|
|
it 'ignores members with blank lat/long' do
|
|
london_member = FactoryBot.create(:london_member)
|
|
london_member.latitude = nil
|
|
london_member.longitude = nil
|
|
london_member.save(validate: false)
|
|
Member.located.should_not include london_member
|
|
end
|
|
end
|
|
|
|
context 'near location' do
|
|
it 'finds nearby members and sorts them' do
|
|
edinburgh_member = FactoryBot.create(:edinburgh_member)
|
|
london_member = FactoryBot.create(:london_member)
|
|
Member.nearest_to('Greenwich, UK').should eq [london_member, edinburgh_member]
|
|
end
|
|
end
|
|
|
|
describe 'interesting scope' do
|
|
# interesting members are defined as:
|
|
# 1) confirmed
|
|
# 2) have a location
|
|
# 3) have at least one planting
|
|
# 4) ordered by the most recent sign in
|
|
|
|
context 'with a few members and plantings' do
|
|
before do
|
|
@members = [
|
|
:london_member, :london_member, :london_member,
|
|
:unconfirmed_member, # !1
|
|
:london_member, # 1, 2, !3
|
|
:member # 1, !2, 3
|
|
].collect { |m| FactoryBot.create(m) }
|
|
|
|
[0, 1, 2, 3, 5].each do |i|
|
|
FactoryBot.create(:planting, owner: @members[i])
|
|
end
|
|
|
|
@members[0].updated_at = 3.days.ago
|
|
@members[1].updated_at = 2.days.ago
|
|
@members[2].updated_at = 1.day.ago
|
|
|
|
# TODO: Shouldn't this save?
|
|
|
|
@result = Member.interesting
|
|
|
|
# Some members have multiple plantings, but should only appear once
|
|
FactoryBot.create_list(:planting, 3, owner: @members[2])
|
|
end
|
|
|
|
it 'finds interesting members without duplicates in the correct order' do
|
|
@result.should eq [@members[2], @members[1], @members[0]]
|
|
end
|
|
end
|
|
end
|
|
|
|
context 'harvests' do
|
|
it 'has harvests' do
|
|
member = FactoryBot.create(:member)
|
|
harvest = FactoryBot.create(:harvest, owner: member)
|
|
member.harvests.should eq [harvest]
|
|
end
|
|
end
|
|
|
|
context 'member who followed another member' do
|
|
let(:member1) { FactoryBot.create(:member) }
|
|
let(:member2) { FactoryBot.create(:member) }
|
|
let(:member3) { FactoryBot.create(:member) }
|
|
|
|
before do
|
|
@follow = member1.follows.create(follower_id: member1.id, followed_id: member2.id)
|
|
end
|
|
|
|
context 'already_following' do
|
|
it 'detects that member is already following a member' do
|
|
expect(member1.already_following?(member2)).to be true
|
|
end
|
|
|
|
it 'detects that member is not already following a member' do
|
|
expect(member1.already_following?(member3)).to be false
|
|
end
|
|
end
|
|
|
|
context 'get_follow' do
|
|
it 'gets the correct follow for a followed member' do
|
|
expect(member1.get_follow(member2).id).to eq @follow.id
|
|
end
|
|
|
|
it 'returns nil for a member that is not followed' do
|
|
expect(member1.get_follow(member3)).to be_nil
|
|
end
|
|
end
|
|
end
|
|
|
|
context 'subscriptions' do
|
|
let(:member) { FactoryBot.create(:member) }
|
|
let(:gb) { instance_double("Gibbon::API.new") }
|
|
|
|
it 'subscribes to the newsletter' do
|
|
expect(gb).to receive_message_chain('lists.subscribe')
|
|
member.newsletter_subscribe(gb, true)
|
|
end
|
|
|
|
it 'unsubscribes from the newsletter' do
|
|
expect(gb).to receive_message_chain('lists.unsubscribe')
|
|
member.newsletter_unsubscribe(gb, true)
|
|
end
|
|
end
|
|
|
|
context 'member deleted' do
|
|
let(:member) { FactoryBot.create(:member) }
|
|
|
|
context 'queries a scope' do
|
|
before { member.destroy }
|
|
|
|
it { expect(Member.all).not_to include(member) }
|
|
it { expect(Member.confirmed).not_to include(member) }
|
|
it { expect(Member.located).not_to include(member) }
|
|
it { expect(Member.recently_signed_in).not_to include(member) }
|
|
it { expect(Member.recently_joined).not_to include(member) }
|
|
it { expect(Member.wants_newsletter).not_to include(member) }
|
|
it { expect(Member.interesting).not_to include(member) }
|
|
it { expect(Member.has_plantings).not_to include(member) }
|
|
end
|
|
|
|
it "unsubscribes from mailing list" do
|
|
expect(member).to receive(:newsletter_unsubscribe).and_return(true)
|
|
member.destroy
|
|
end
|
|
|
|
context "deleted admin member" do
|
|
let(:member) { FactoryBot.create(:admin_member) }
|
|
|
|
before { member.discard }
|
|
|
|
context 'crop creator' do
|
|
let!(:crop) { FactoryBot.create(:crop, creator: member) }
|
|
|
|
it "leaves crops behind, reassigned to cropbot" do
|
|
expect(Crop.all).to include(crop)
|
|
end
|
|
end
|
|
|
|
context 'forum owners' do
|
|
let!(:forum) { FactoryBot.create(:forum, owner: member) }
|
|
|
|
it "leaves forums behind, reassigned to ex_admin" do
|
|
expect(forum.owner).to eq(member)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|