From 17c57c46e7f54f32ad7b17b86c7b936c789ca799 Mon Sep 17 00:00:00 2001
From: Matt Jankowski <matt@jankowski.online>
Date: Thu, 12 Sep 2024 09:25:23 -0400
Subject: [PATCH] Add coverage for title/limit validations in `List` model
 (#31869)

---
 app/models/list.rb       | 10 ++++++----
 spec/models/list_spec.rb | 27 +++++++++++++++++++++++++++
 2 files changed, 33 insertions(+), 4 deletions(-)
 create mode 100644 spec/models/list_spec.rb

diff --git a/app/models/list.rb b/app/models/list.rb
index b45bd057bc..d4915f56fa 100644
--- a/app/models/list.rb
+++ b/app/models/list.rb
@@ -20,21 +20,23 @@ class List < ApplicationRecord
 
   enum :replies_policy, { list: 0, followed: 1, none: 2 }, prefix: :show
 
-  belongs_to :account, optional: true
+  belongs_to :account
 
   has_many :list_accounts, inverse_of: :list, dependent: :destroy
   has_many :accounts, through: :list_accounts
 
   validates :title, presence: true
 
-  validates_each :account_id, on: :create do |record, _attr, value|
-    record.errors.add(:base, I18n.t('lists.errors.limit')) if List.where(account_id: value).count >= PER_ACCOUNT_LIMIT
-  end
+  validate :validate_account_lists_limit, on: :create
 
   before_destroy :clean_feed_manager
 
   private
 
+  def validate_account_lists_limit
+    errors.add(:base, I18n.t('lists.errors.limit')) if account.lists.count >= PER_ACCOUNT_LIMIT
+  end
+
   def clean_feed_manager
     FeedManager.instance.clean_feeds!(:list, [id])
   end
diff --git a/spec/models/list_spec.rb b/spec/models/list_spec.rb
new file mode 100644
index 0000000000..62a84dfebf
--- /dev/null
+++ b/spec/models/list_spec.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+require 'rails_helper'
+
+RSpec.describe List do
+  describe 'Validations' do
+    subject { Fabricate.build :list }
+
+    it { is_expected.to validate_presence_of(:title) }
+
+    context 'when account has hit max list limit' do
+      let(:account) { Fabricate :account }
+
+      before { stub_const 'List::PER_ACCOUNT_LIMIT', 0 }
+
+      context 'when creating a new list' do
+        it { is_expected.to_not allow_value(account).for(:account).against(:base).with_message(I18n.t('lists.errors.limit')) }
+      end
+
+      context 'when updating an existing list' do
+        before { subject.save(validate: false) }
+
+        it { is_expected.to allow_value(account).for(:account).against(:base) }
+      end
+    end
+  end
+end