mirror of
https://github.com/Freika/dawarich.git
synced 2026-01-10 17:21:38 -05:00
179 lines
5.5 KiB
Ruby
179 lines
5.5 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require 'rails_helper'
|
|
|
|
RSpec.describe Import, type: :model do
|
|
let(:user) { create(:user) }
|
|
subject(:import) { create(:import, user:) }
|
|
|
|
describe 'associations' do
|
|
it { is_expected.to have_many(:points).dependent(:destroy) }
|
|
it 'belongs to a user' do
|
|
expect(user).to be_present
|
|
expect(import.user).to eq(user)
|
|
end
|
|
end
|
|
|
|
describe 'validations' do
|
|
it { is_expected.to validate_presence_of(:name) }
|
|
|
|
it 'validates uniqueness of name scoped to user_id' do
|
|
create(:import, name: 'test_name', user: user)
|
|
|
|
duplicate_import = build(:import, name: 'test_name', user: user)
|
|
expect(duplicate_import).not_to be_valid
|
|
expect(duplicate_import.errors[:name]).to include('has already been taken')
|
|
|
|
other_user = create(:user)
|
|
different_user_import = build(:import, name: 'test_name', user: other_user)
|
|
expect(different_user_import).to be_valid
|
|
end
|
|
|
|
describe 'file size validation' do
|
|
context 'when user is a trial user' do
|
|
let(:user) do
|
|
user = create(:user)
|
|
user.update!(status: :trial)
|
|
user
|
|
end
|
|
|
|
it 'validates file size limit for large files' do
|
|
import = build(:import, user: user)
|
|
mock_file = double(attached?: true, blob: double(byte_size: 12.megabytes))
|
|
allow(import).to receive(:file).and_return(mock_file)
|
|
|
|
expect(import).not_to be_valid
|
|
expect(import.errors[:file]).to include('is too large. Trial users can only upload files up to 10MB.')
|
|
end
|
|
|
|
it 'allows files under the size limit' do
|
|
import = build(:import, user: user)
|
|
mock_file = double(attached?: true, blob: double(byte_size: 5.megabytes))
|
|
allow(import).to receive(:file).and_return(mock_file)
|
|
|
|
expect(import).to be_valid
|
|
end
|
|
end
|
|
|
|
context 'when user is a paid user' do
|
|
let(:user) { create(:user, status: :active) }
|
|
let(:import) { build(:import, user: user) }
|
|
|
|
it 'does not validate file size limit' do
|
|
allow(import).to receive(:file).and_return(double(attached?: true, blob: double(byte_size: 12.megabytes)))
|
|
|
|
expect(import).to be_valid
|
|
end
|
|
end
|
|
end
|
|
|
|
describe 'import count validation' do
|
|
context 'when user is a trial user' do
|
|
let(:user) do
|
|
user = create(:user)
|
|
user.update!(status: :trial)
|
|
user
|
|
end
|
|
|
|
it 'allows imports when under the limit' do
|
|
3.times { |i| create(:import, user: user, name: "import_#{i}") }
|
|
new_import = build(:import, user: user, name: 'new_import')
|
|
|
|
expect(new_import).to be_valid
|
|
end
|
|
|
|
it 'prevents creating more than 5 imports' do
|
|
5.times { |i| create(:import, user: user, name: "import_#{i}") }
|
|
new_import = build(:import, user: user, name: 'import_6')
|
|
|
|
expect(new_import).not_to be_valid
|
|
expect(new_import.errors[:base]).to include('Trial users can only create up to 5 imports. Please subscribe to import more files.')
|
|
end
|
|
end
|
|
|
|
context 'when user is an active user' do
|
|
let(:user) { create(:user, status: :active) }
|
|
|
|
it 'does not validate import count limit' do
|
|
7.times { |i| create(:import, user: user, name: "import_#{i}") }
|
|
new_import = build(:import, user: user, name: 'import_8')
|
|
|
|
expect(new_import).to be_valid
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
describe 'enums' do
|
|
it do
|
|
is_expected.to define_enum_for(:source).with_values(
|
|
google_semantic_history: 0,
|
|
owntracks: 1,
|
|
google_records: 2,
|
|
google_phone_takeout: 3,
|
|
gpx: 4,
|
|
immich_api: 5,
|
|
geojson: 6,
|
|
photoprism_api: 7,
|
|
user_data_archive: 8
|
|
)
|
|
end
|
|
end
|
|
|
|
describe '#years_and_months_tracked' do
|
|
let(:import) { create(:import) }
|
|
let(:timestamp) { Time.zone.local(2024, 11, 1) }
|
|
let!(:points) do
|
|
(1..3).map do |i|
|
|
create(:point, import:, timestamp: timestamp + i.minutes)
|
|
end
|
|
end
|
|
|
|
it 'returns years and months tracked' do
|
|
expect(import.years_and_months_tracked).to eq([[2024, 11]])
|
|
end
|
|
end
|
|
|
|
describe '#migrate_to_new_storage' do
|
|
let(:raw_data) { Rails.root.join('spec/fixtures/files/geojson/export.json') }
|
|
let(:import) { create(:import, source: 'geojson', raw_data:) }
|
|
|
|
it 'attaches the file to the import' do
|
|
import.migrate_to_new_storage
|
|
|
|
expect(import.file.attached?).to be_truthy
|
|
end
|
|
|
|
context 'when file is attached' do
|
|
it 'is a importable file' do
|
|
import.migrate_to_new_storage
|
|
|
|
expect { import.process! }.to change(Point, :count).by(10)
|
|
end
|
|
end
|
|
end
|
|
|
|
describe '#recalculate_stats' do
|
|
let(:import) { create(:import, user:) }
|
|
let!(:point1) { create(:point, import:, user:, timestamp: Time.zone.local(2024, 11, 15).to_i) }
|
|
let!(:point2) { create(:point, import:, user:, timestamp: Time.zone.local(2024, 12, 5).to_i) }
|
|
|
|
it 'enqueues stats calculation jobs for each tracked month' do
|
|
expect do
|
|
import.send(:recalculate_stats)
|
|
end.to have_enqueued_job(Stats::CalculatingJob)
|
|
.with(user.id, 2024, 11)
|
|
.and have_enqueued_job(Stats::CalculatingJob).with(user.id, 2024, 12)
|
|
end
|
|
|
|
context 'when import has no points' do
|
|
let(:empty_import) { create(:import, user:) }
|
|
|
|
it 'does not enqueue any jobs' do
|
|
expect do
|
|
empty_import.send(:recalculate_stats)
|
|
end.not_to have_enqueued_job(Stats::CalculatingJob)
|
|
end
|
|
end
|
|
end
|
|
end
|