mirror of
https://github.com/Freika/dawarich.git
synced 2026-01-09 08:47:11 -05:00
Add missing specs
This commit is contained in:
parent
c99f6597f0
commit
50bfece971
2 changed files with 290 additions and 0 deletions
196
spec/models/concerns/taggable_spec.rb
Normal file
196
spec/models/concerns/taggable_spec.rb
Normal file
|
|
@ -0,0 +1,196 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Taggable do
|
||||
# Use Place as the test model since it includes Taggable
|
||||
let(:user) { create(:user) }
|
||||
let(:tag1) { create(:tag, user: user, name: 'Home') }
|
||||
let(:tag2) { create(:tag, user: user, name: 'Work') }
|
||||
let(:tag3) { create(:tag, user: user, name: 'Gym') }
|
||||
|
||||
describe 'associations' do
|
||||
it { expect(Place.new).to have_many(:taggings).dependent(:destroy) }
|
||||
it { expect(Place.new).to have_many(:tags).through(:taggings) }
|
||||
end
|
||||
|
||||
describe 'scopes' do
|
||||
let!(:place1) { create(:place, user: user) }
|
||||
let!(:place2) { create(:place, user: user) }
|
||||
let!(:place3) { create(:place, user: user) }
|
||||
|
||||
before do
|
||||
place1.tags << [tag1, tag2]
|
||||
place2.tags << tag1
|
||||
# place3 has no tags
|
||||
end
|
||||
|
||||
describe '.with_tags' do
|
||||
it 'returns places with any of the specified tag IDs' do
|
||||
results = Place.with_tags([tag1.id])
|
||||
expect(results).to contain_exactly(place1, place2)
|
||||
end
|
||||
|
||||
it 'returns places with multiple tag IDs' do
|
||||
results = Place.with_tags([tag1.id, tag2.id])
|
||||
expect(results).to contain_exactly(place1, place2)
|
||||
end
|
||||
|
||||
it 'returns distinct results when place has multiple matching tags' do
|
||||
results = Place.with_tags([tag1.id, tag2.id])
|
||||
expect(results.count).to eq(2)
|
||||
expect(results).to contain_exactly(place1, place2)
|
||||
end
|
||||
|
||||
it 'returns empty when no places have the specified tags' do
|
||||
results = Place.with_tags([tag3.id])
|
||||
expect(results).to be_empty
|
||||
end
|
||||
|
||||
it 'accepts a single tag ID' do
|
||||
results = Place.with_tags(tag1.id)
|
||||
expect(results).to contain_exactly(place1, place2)
|
||||
end
|
||||
end
|
||||
|
||||
describe '.without_tags' do
|
||||
it 'returns only places without any tags' do
|
||||
results = Place.without_tags
|
||||
expect(results).to contain_exactly(place3)
|
||||
end
|
||||
|
||||
it 'returns empty when all places have tags' do
|
||||
place3.tags << tag3
|
||||
results = Place.without_tags
|
||||
expect(results).to be_empty
|
||||
end
|
||||
|
||||
it 'returns all places when none have tags' do
|
||||
place1.tags.clear
|
||||
place2.tags.clear
|
||||
results = Place.without_tags
|
||||
expect(results).to contain_exactly(place1, place2, place3)
|
||||
end
|
||||
end
|
||||
|
||||
describe '.tagged_with' do
|
||||
it 'returns places tagged with the specified tag name' do
|
||||
results = Place.tagged_with('Home', user)
|
||||
expect(results).to contain_exactly(place1, place2)
|
||||
end
|
||||
|
||||
it 'returns distinct results' do
|
||||
results = Place.tagged_with('Home', user)
|
||||
expect(results.count).to eq(2)
|
||||
end
|
||||
|
||||
it 'returns empty when no places have the tag name' do
|
||||
results = Place.tagged_with('NonExistent', user)
|
||||
expect(results).to be_empty
|
||||
end
|
||||
|
||||
it 'filters by user' do
|
||||
other_user = create(:user)
|
||||
other_tag = create(:tag, user: other_user, name: 'Home')
|
||||
other_place = create(:place, user: other_user)
|
||||
other_place.tags << other_tag
|
||||
|
||||
results = Place.tagged_with('Home', user)
|
||||
expect(results).to contain_exactly(place1, place2)
|
||||
expect(results).not_to include(other_place)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'instance methods' do
|
||||
let(:place) { create(:place, user: user) }
|
||||
|
||||
describe '#add_tag' do
|
||||
it 'adds a tag to the record' do
|
||||
expect {
|
||||
place.add_tag(tag1)
|
||||
}.to change { place.tags.count }.by(1)
|
||||
end
|
||||
|
||||
it 'does not add duplicate tags' do
|
||||
place.add_tag(tag1)
|
||||
expect {
|
||||
place.add_tag(tag1)
|
||||
}.not_to change { place.tags.count }
|
||||
end
|
||||
|
||||
it 'adds the correct tag' do
|
||||
place.add_tag(tag1)
|
||||
expect(place.tags).to include(tag1)
|
||||
end
|
||||
|
||||
it 'can add multiple different tags' do
|
||||
place.add_tag(tag1)
|
||||
place.add_tag(tag2)
|
||||
expect(place.tags).to contain_exactly(tag1, tag2)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#remove_tag' do
|
||||
before do
|
||||
place.tags << [tag1, tag2]
|
||||
end
|
||||
|
||||
it 'removes a tag from the record' do
|
||||
expect {
|
||||
place.remove_tag(tag1)
|
||||
}.to change { place.tags.count }.by(-1)
|
||||
end
|
||||
|
||||
it 'removes the correct tag' do
|
||||
place.remove_tag(tag1)
|
||||
expect(place.tags).not_to include(tag1)
|
||||
expect(place.tags).to include(tag2)
|
||||
end
|
||||
|
||||
it 'does nothing when tag is not present' do
|
||||
expect {
|
||||
place.remove_tag(tag3)
|
||||
}.not_to change { place.tags.count }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#tag_names' do
|
||||
it 'returns an empty array when no tags' do
|
||||
expect(place.tag_names).to eq([])
|
||||
end
|
||||
|
||||
it 'returns array of tag names' do
|
||||
place.tags << [tag1, tag2]
|
||||
expect(place.tag_names).to contain_exactly('Home', 'Work')
|
||||
end
|
||||
|
||||
it 'returns tag names in database order' do
|
||||
place.tags << tag2
|
||||
place.tags << tag1
|
||||
# Order depends on taggings created_at
|
||||
expect(place.tag_names).to be_an(Array)
|
||||
expect(place.tag_names.size).to eq(2)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#tagged_with?' do
|
||||
before do
|
||||
place.tags << tag1
|
||||
end
|
||||
|
||||
it 'returns true when tagged with the specified tag' do
|
||||
expect(place.tagged_with?(tag1)).to be true
|
||||
end
|
||||
|
||||
it 'returns false when not tagged with the specified tag' do
|
||||
expect(place.tagged_with?(tag2)).to be false
|
||||
end
|
||||
|
||||
it 'returns false when place has no tags' do
|
||||
place.tags.clear
|
||||
expect(place.tagged_with?(tag1)).to be false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -18,6 +18,100 @@ RSpec.describe Place, type: :model do
|
|||
it { is_expected.to define_enum_for(:source).with_values(%i[manual photon]) }
|
||||
end
|
||||
|
||||
describe 'scopes' do
|
||||
let(:user1) { create(:user) }
|
||||
let(:user2) { create(:user) }
|
||||
let!(:place1) { create(:place, user: user1, name: 'Zoo') }
|
||||
let!(:place2) { create(:place, user: user1, name: 'Airport') }
|
||||
let!(:place3) { create(:place, user: user2, name: 'Museum') }
|
||||
|
||||
describe '.for_user' do
|
||||
it 'returns places for the specified user' do
|
||||
expect(Place.for_user(user1)).to contain_exactly(place1, place2)
|
||||
end
|
||||
|
||||
it 'does not return places for other users' do
|
||||
expect(Place.for_user(user1)).not_to include(place3)
|
||||
end
|
||||
|
||||
it 'returns empty when user has no places' do
|
||||
new_user = create(:user)
|
||||
expect(Place.for_user(new_user)).to be_empty
|
||||
end
|
||||
end
|
||||
|
||||
describe '.ordered' do
|
||||
it 'orders places by name alphabetically' do
|
||||
expect(Place.for_user(user1).ordered).to eq([place2, place1])
|
||||
end
|
||||
|
||||
it 'handles case-insensitive ordering' do
|
||||
place_lower = create(:place, user: user1, name: 'airport')
|
||||
place_upper = create(:place, user: user1, name: 'BEACH')
|
||||
|
||||
ordered = Place.for_user(user1).ordered
|
||||
# The ordered scope orders by name alphabetically (case-sensitive in most DBs)
|
||||
expect(ordered.map(&:name)).to include('airport', 'BEACH')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'Taggable concern integration' do
|
||||
let(:user) { create(:user) }
|
||||
let(:place) { create(:place, user: user) }
|
||||
let(:tag1) { create(:tag, user: user, name: 'Restaurant') }
|
||||
let(:tag2) { create(:tag, user: user, name: 'Favorite') }
|
||||
|
||||
it 'can add tags to a place' do
|
||||
place.add_tag(tag1)
|
||||
expect(place.tags).to include(tag1)
|
||||
end
|
||||
|
||||
it 'can remove tags from a place' do
|
||||
place.tags << tag1
|
||||
place.remove_tag(tag1)
|
||||
expect(place.tags).not_to include(tag1)
|
||||
end
|
||||
|
||||
it 'returns tag names' do
|
||||
place.tags << [tag1, tag2]
|
||||
expect(place.tag_names).to contain_exactly('Restaurant', 'Favorite')
|
||||
end
|
||||
|
||||
it 'checks if tagged with a specific tag' do
|
||||
place.tags << tag1
|
||||
expect(place.tagged_with?(tag1)).to be true
|
||||
expect(place.tagged_with?(tag2)).to be false
|
||||
end
|
||||
|
||||
describe 'scopes' do
|
||||
let!(:tagged_place) { create(:place, user: user) }
|
||||
let!(:untagged_place) { create(:place, user: user) }
|
||||
|
||||
before do
|
||||
tagged_place.tags << tag1
|
||||
end
|
||||
|
||||
it 'filters places with specific tags' do
|
||||
results = Place.with_tags([tag1.id])
|
||||
expect(results).to include(tagged_place)
|
||||
expect(results).not_to include(untagged_place)
|
||||
end
|
||||
|
||||
it 'filters places without tags' do
|
||||
results = Place.without_tags
|
||||
expect(results).to include(untagged_place)
|
||||
expect(results).not_to include(tagged_place)
|
||||
end
|
||||
|
||||
it 'filters places by tag name and user' do
|
||||
results = Place.tagged_with('Restaurant', user)
|
||||
expect(results).to include(tagged_place)
|
||||
expect(results).not_to include(untagged_place)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'methods' do
|
||||
let(:place) { create(:place, :with_geodata) }
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue