iachat/spec/models/user_spec.rb
Cayo P. R. Oliveira c6f9e814c2
feat: add customizable signature position and separator options (#78)
* feat: add customizable signature position and separator options

* fix: correct default value note for signatureSeparator and ensure reactivity

* fix: correct watcher boolean conversion and add immediate ui_settings updates

- Fix watchers to convert string props to boolean values for reactive refs
- Add immediate event handlers for switch changes to update ui_settings in real-time
- Ensure proper synchronization between switch states and user.ui_settings

Co-Authored-By: cayo@fazer.ai <cayoproliveira@gmail.com>

* fix: split signature content and ui_settings updates to resolve persistence bug

- Use updateUISettings store action for signature_position and signature_separator
- Keep updateProfile for message_signature content only
- Fixes FormData serialization issue that corrupted nested ui_settings object
- Add diagnostic logging to verify data flow

Co-Authored-By: cayo@fazer.ai <cayoproliveira@gmail.com>

* clean: remove diagnostic console logging from updateSignature method

- Remove temporary console.log statements added for verification
- Keep core implementation that splits signature content and ui_settings updates
- Keep console.error for proper error handling with eslint-disable comment
- Implementation now ready for production use

Co-Authored-By: cayo@fazer.ai <cayoproliveira@gmail.com>

* fix: updateUISettings call in updateSignature method

* chore: move signature application to send-time and add button highlighting (#79)

* fix: move signature application from editor manipulation to send-time

- Remove addSignature/removeSignature/toggleSignatureInEditor from WootWriter
- Remove signature logic from draft handling and canned response insertion
- Apply signatures only in getMessagePayload during message sending
- Add button highlighting for signature toggle when activated
- Prevents signature duplication and persistence in editor content
- Fixes signature position toggle bug

Co-Authored-By: cayo@fazer.ai <cayoproliveira@gmail.com>

* fix: escape signature separator to prevent markdown setext heading interpretation

- Escape '--' separator as '\--' in appendSignature to prevent H2 heading creation
- Update removeSignature to handle escaped separators correctly
- Fixes signature separator being rendered as markdown instead of plain text
- Refactor nested ternary to fix ESLint error

Co-Authored-By: cayo@fazer.ai <cayoproliveira@gmail.com>

* fix: prevent signature separator markdown interpretation in message processing

- Add fix_signature_separator_markdown method to escape '--' separators
- Update ensure_processed_message_content to fix separators before saving
- Prevents signature separators from being interpreted as setext headings
- Ensures correct message display in channels and email notifications

Co-Authored-By: cayo@fazer.ai <cayoproliveira@gmail.com>

* fix: update separator format to use \n--\n instead of escaping

- Change separator delimiter from '\--' to '\n--\n' format
- Update removeSignature function to handle new separator format correctly
- Simplify message processing since separators are already properly formatted
- Ensures consistent separator handling across frontend and backend

Co-Authored-By: cayo@fazer.ai <cayoproliveira@gmail.com>

* fix: update signature delimiter format to include extra new lines

* chore: remove comment about signature application logic

* refactor: remove unused method and comments related to signature separator markdown processing

* chore: simplify slash command detection by using updatedMessage directly

* refactor: remove signature logic from draft message handling

* refactor: simplify body empty check by removing signature manipulation logic

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: cayo@fazer.ai <cayoproliveira@gmail.com>

* refactor: extract signature settings logic into a separate method

* fix: handle nil ui_settings in signature position and separator methods

* fix: update return value of findSignatureInBody to include position information

* fix: update signature handling in findSignatureInBody and related methods

* fix: adjust delimiter length handling in removeSignature function

* test: add cases for appending, removing, and replacing signatures with various separators

* test: add cases for signature position and separator handling

* test: add cases for updating signature position and separator in ui_settings

* fix: correct typo in comment for findSignatureInBody function

* refactor: simplify translation function calls in MessageSignature component

* chore: refactoring

* chore: refactor

* feat: switch -> select

* chore: refactor and undo changes

* chore: refactor and undo changes

* chore: refactor

* fix: remove old select component usage

* chore: remove useless style

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: gabrieljablonski <contact@gabrieljablonski.com>
2025-08-17 23:01:41 -03:00

142 lines
4.5 KiB
Ruby

# frozen_string_literal: true
require 'rails_helper'
require Rails.root.join 'spec/models/concerns/access_tokenable_shared.rb'
require Rails.root.join 'spec/models/concerns/avatarable_shared.rb'
RSpec.describe User do
let!(:user) { create(:user) }
context 'with validations' do
it { is_expected.to validate_presence_of(:email) }
end
context 'with associations' do
it { is_expected.to have_many(:accounts).through(:account_users) }
it { is_expected.to have_many(:account_users) }
it { is_expected.to have_many(:assigned_conversations).class_name('Conversation').dependent(:nullify) }
it { is_expected.to have_many(:inbox_members).dependent(:destroy_async) }
it { is_expected.to have_many(:notification_settings).dependent(:destroy_async) }
it { is_expected.to have_many(:messages) }
it { is_expected.to have_many(:reporting_events) }
it { is_expected.to have_many(:teams) }
end
describe 'concerns' do
it_behaves_like 'access_tokenable'
it_behaves_like 'avatarable'
end
describe 'pubsub_token' do
before { user.update(name: Faker::Name.name) }
it { expect(user.pubsub_token).not_to be_nil }
it { expect(user.saved_changes.keys).not_to eq('pubsub_token') }
context 'with rotate the pubsub_token' do
it 'changes the pubsub_token when password changes' do
pubsub_token = user.pubsub_token
user.password = Faker::Internet.password(special_characters: true)
user.save!
expect(user.pubsub_token).not_to eq(pubsub_token)
end
it 'will not change pubsub_token when other attributes change' do
pubsub_token = user.pubsub_token
user.name = Faker::Name.name
user.save!
expect(user.pubsub_token).to eq(pubsub_token)
end
end
end
describe 'hmac_identifier' do
it 'return nil if CHATWOOT_INBOX_HMAC_KEY is not set' do
expect(user.hmac_identifier).to eq('')
end
it 'return value if CHATWOOT_INBOX_HMAC_KEY is set' do
ConfigLoader.new.process
i = InstallationConfig.find_by(name: 'CHATWOOT_INBOX_HMAC_KEY')
i.value = 'random_secret_key'
i.save!
GlobalConfig.clear_cache
expected_hmac_identifier = OpenSSL::HMAC.hexdigest('sha256', 'random_secret_key', user.email)
expect(user.hmac_identifier).to eq expected_hmac_identifier
end
end
context 'with sso_auth_token' do
it 'can generate multiple sso tokens which can be validated' do
sso_auth_token1 = user.generate_sso_auth_token
sso_auth_token2 = user.generate_sso_auth_token
expect(sso_auth_token1).present?
expect(sso_auth_token2).present?
expect(user.valid_sso_auth_token?(sso_auth_token1)).to be true
expect(user.valid_sso_auth_token?(sso_auth_token2)).to be true
end
it 'wont validate an invalid token' do
expect(user.valid_sso_auth_token?(SecureRandom.hex(32))).to be false
end
it 'wont validate an invalidated token' do
sso_auth_token = user.generate_sso_auth_token
user.invalidate_sso_auth_token(sso_auth_token)
expect(user.valid_sso_auth_token?(sso_auth_token)).to be false
end
end
describe 'access token' do
it 'creates a single access token upon user creation' do
new_user = create(:user)
token_count = AccessToken.where(owner: new_user).count
expect(token_count).to eq(1)
end
end
context 'when user changes the email' do
it 'mutates the value' do
user.email = 'user@example.com'
expect(user.will_save_change_to_email?).to be true
end
end
context 'when the supplied email is uppercase' do
it 'downcases the email on save' do
new_user = create(:user, email: 'Test123@test.com')
expect(new_user.email).to eq('test123@test.com')
end
end
context 'when the user does not have signature position set' do
it 'returns the default signature position' do
expect(user.signature_position).to eq('top')
end
end
context 'when the user has signature position set' do
it 'returns the user signature position' do
user.update!(ui_settings: { signature_position: 'bottom' })
expect(user.signature_position).to eq('bottom')
end
end
context 'when the user does not have signature separator set' do
it 'returns the default signature separator' do
expect(user.signature_separator).to eq('blank')
end
end
context 'when the user has signature separator set' do
it 'returns the user signature separator' do
user.update!(ui_settings: { signature_separator: '--' })
expect(user.signature_separator).to eq('--')
end
end
end