Merge branch 'develop' into feat/new-auth-screens

This commit is contained in:
Sivin Varghese 2022-10-03 10:19:31 +05:30 committed by GitHub
commit 100f0b07ce
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 284 additions and 96 deletions

View file

@ -31,7 +31,7 @@ class ContactInboxBuilder
return unless @contact.phone_number
# whatsapp doesn't want the + in e164 format
"#{@contact.phone_number}.delete('+')"
@contact.phone_number.delete('+').to_s
end
def twilio_source_id

View file

@ -51,6 +51,6 @@ class Platform::Api::V1::UsersController < PlatformController
end
def user_params
params.permit(:name, :email, :password, custom_attributes: {})
params.permit(:name, :display_name, :email, :password, custom_attributes: {})
end
end

View file

@ -28,7 +28,7 @@ import {
suggestionsPlugin,
triggerCharacters,
} from '@chatwoot/prosemirror-schema/src/mentions/plugin';
import { EditorState } from 'prosemirror-state';
import { EditorState, Selection } from 'prosemirror-state';
import { defaultMarkdownParser } from 'prosemirror-markdown';
import { wootWriterSetup } from '@chatwoot/prosemirror-schema';
@ -61,23 +61,28 @@ export default {
mixins: [eventListenerMixins],
props: {
value: { type: String, default: '' },
editorId: { type: String, default: '' },
placeholder: { type: String, default: '' },
isPrivate: { type: Boolean, default: false },
isFormatMode: { type: Boolean, default: false },
enableSuggestions: { type: Boolean, default: true },
},
data() {
return {
lastValue: null,
showUserMentions: false,
showCannedMenu: false,
mentionSearchKey: '',
cannedSearchTerm: '',
editorView: null,
range: null,
state: undefined,
};
},
computed: {
contentFromEditor() {
return addMentionsToMarkdownSerializer(
defaultMarkdownSerializer
).serialize(this.editorView.state.doc);
},
plugins() {
if (!this.enableSuggestions) {
return [];
@ -102,7 +107,6 @@ export default {
onExit: () => {
this.mentionSearchKey = '';
this.showUserMentions = false;
this.editorView = null;
return false;
},
onKeyDown: ({ event }) => {
@ -131,7 +135,6 @@ export default {
onExit: () => {
this.cannedSearchTerm = '';
this.showCannedMenu = false;
this.editorView = null;
return false;
},
onKeyDown: ({ event }) => {
@ -149,54 +152,57 @@ export default {
this.$emit('toggle-canned-menu', !this.isPrivate && updatedValue);
},
value(newValue = '') {
if (newValue !== this.lastValue) {
const { tr } = this.state;
if (this.isFormatMode) {
this.state = createState(
newValue,
this.placeholder,
this.plugins,
this.isFormatMode
);
} else {
tr.insertText(newValue, 0, tr.doc.content.size);
this.state = this.view.state.apply(tr);
}
this.view.updateState(this.state);
if (newValue !== this.contentFromEditor) {
this.reloadState();
}
},
editorId() {
this.reloadState();
},
isPrivate() {
this.reloadState();
},
},
created() {
this.state = createState(this.value, this.placeholder, this.plugins);
},
mounted() {
this.view = new EditorView(this.$refs.editor, {
state: this.state,
dispatchTransaction: tx => {
this.state = this.state.apply(tx);
this.emitOnChange();
},
handleDOMEvents: {
keyup: () => {
this.onKeyup();
},
focus: () => {
this.onFocus();
},
blur: () => {
this.onBlur();
},
paste: (view, event) => {
const data = event.clipboardData.files;
if (data.length > 0) {
event.preventDefault();
}
},
},
});
this.createEditorView();
this.editorView.updateState(this.state);
this.focusEditorInputField();
},
methods: {
reloadState() {
this.state = createState(this.value, this.placeholder, this.plugins);
this.editorView.updateState(this.state);
this.focusEditorInputField();
},
createEditorView() {
this.editorView = new EditorView(this.$refs.editor, {
state: this.state,
dispatchTransaction: tx => {
this.state = this.state.apply(tx);
this.emitOnChange();
},
handleDOMEvents: {
keyup: () => {
this.onKeyup();
},
focus: () => {
this.onFocus();
},
blur: () => {
this.onBlur();
},
paste: (view, event) => {
const data = event.clipboardData.files;
if (data.length > 0) {
event.preventDefault();
}
},
},
});
},
handleKeyEvents(e) {
if (hasPressedAltAndPKey(e)) {
this.focusEditorInputField();
@ -206,47 +212,59 @@ export default {
}
},
focusEditorInputField() {
this.$refs.editor.querySelector('div.ProseMirror-woot-style').focus();
const { tr } = this.editorView.state;
const selection = Selection.atEnd(tr.doc);
this.editorView.dispatch(tr.setSelection(selection));
this.editorView.focus();
},
insertMentionNode(mentionItem) {
if (!this.view) {
if (!this.editorView) {
return null;
}
const node = this.view.state.schema.nodes.mention.create({
const node = this.editorView.state.schema.nodes.mention.create({
userId: mentionItem.key,
userFullName: mentionItem.label,
});
const tr = this.view.state.tr.replaceWith(
const tr = this.editorView.state.tr.replaceWith(
this.range.from,
this.range.to,
node
);
this.state = this.view.state.apply(tr);
this.state = this.editorView.state.apply(tr);
return this.emitOnChange();
},
insertCannedResponse(cannedItem) {
if (!this.view) {
if (!this.editorView) {
return null;
}
const tr = this.view.state.tr.insertText(
const tr = this.editorView.state.tr.insertText(
cannedItem,
this.range.from,
this.range.to
);
this.state = this.view.state.apply(tr);
return this.emitOnChange();
this.state = this.editorView.state.apply(tr);
this.emitOnChange();
// Hacky fix for #5501
this.state = createState(
this.contentFromEditor,
this.placeholder,
this.plugins
);
this.editorView.updateState(this.state);
return false;
},
emitOnChange() {
this.view.updateState(this.state);
this.lastValue = addMentionsToMarkdownSerializer(
defaultMarkdownSerializer
).serialize(this.state.doc);
this.$emit('input', this.lastValue);
this.editorView.updateState(this.state);
this.$emit('input', this.contentFromEditor);
},
hideMentions() {
this.showUserMentions = false;
},

View file

@ -56,6 +56,7 @@
<woot-message-editor
v-else
v-model="message"
:editor-id="editorStateId"
class="input"
:is-private="isOnPrivateNote"
:placeholder="messagePlaceHolder"
@ -429,6 +430,13 @@ export default {
profilePath() {
return frontendURL(`accounts/${this.accountId}/profile/settings`);
},
conversationId() {
return this.currentChat.id;
},
editorStateId() {
const key = `draft-${this.conversationIdByRoute}-${this.replyType}`;
return key;
},
},
watch: {
currentChat(conversation) {

View file

@ -1,6 +1,7 @@
export const LOCAL_STORAGE_KEYS = {
DISMISSED_UPDATES: 'dismissedUpdates',
WIDGET_BUILDER: 'widgetBubble_',
DRAFT_MESSAGES: 'draftMessages',
};
export const LocalStorage = {

View file

@ -46,6 +46,7 @@ export default {
return {
articleTitle: '',
articleContent: '',
saveArticle: () => {},
};
},
mounted() {

View file

@ -23,7 +23,7 @@
#
# index_articles_on_associated_article_id (associated_article_id)
# index_articles_on_author_id (author_id)
# index_articles_on_slug (slug)
# index_articles_on_slug (slug) UNIQUE
#
class Article < ApplicationRecord
include PgSearch::Model
@ -45,6 +45,8 @@ class Article < ApplicationRecord
belongs_to :author, class_name: 'User'
before_validation :ensure_account_id
before_validation :ensure_article_slug
validates :account_id, presence: true
validates :category_id, presence: true
validates :author_id, presence: true
@ -112,4 +114,8 @@ class Article < ApplicationRecord
def ensure_account_id
self.account_id = portal&.account_id
end
def ensure_article_slug
self.slug ||= "#{Time.now.utc.to_i}-#{title.underscore.parameterize(separator: '-')}" if title.present?
end
end

View file

@ -22,6 +22,7 @@
class ContactInbox < ApplicationRecord
include Pubsubable
include RegexHelper
validates :inbox_id, presence: true
validates :contact_id, presence: true
validates :source_id, presence: true
@ -51,10 +52,10 @@ class ContactInbox < ApplicationRecord
def validate_twilio_source_id
# https://www.twilio.com/docs/glossary/what-e164#regex-matching-for-e164
if inbox.channel.medium == 'sms' && !/\+[1-9]\d{1,14}\z/.match?(source_id)
errors.add(:source_id, 'invalid source id for twilio sms inbox. valid Regex /\+[1-9]\d{1,14}\z/')
elsif inbox.channel.medium == 'whatsapp' && !/whatsapp:\+[1-9]\d{1,14}\z/.match?(source_id)
errors.add(:source_id, 'invalid source id for twilio whatsapp inbox. valid Regex /whatsapp:\+[1-9]\d{1,14}\z/')
if inbox.channel.medium == 'sms' && !TWILIO_CHANNEL_SMS_REGEX.match?(source_id)
errors.add(:source_id, "invalid source id for twilio sms inbox. valid Regex #{TWILIO_CHANNEL_SMS_REGEX}")
elsif inbox.channel.medium == 'whatsapp' && !TWILIO_CHANNEL_WHATSAPP_REGEX.match?(source_id)
errors.add(:source_id, "invalid source id for twilio whatsapp inbox. valid Regex #{TWILIO_CHANNEL_WHATSAPP_REGEX}")
end
end
@ -62,8 +63,15 @@ class ContactInbox < ApplicationRecord
errors.add(:source_id, "invalid source id for Email inbox. valid Regex #{Devise.email_regexp}") unless Devise.email_regexp.match?(source_id)
end
def validate_whatsapp_source_id
return if WHATSAPP_CHANNEL_REGEX.match?(source_id)
errors.add(:source_id, "invalid source id for whatsapp inbox. valid Regex #{WHATSAPP_CHANNEL_REGEX}")
end
def valid_source_id_format?
validate_twilio_source_id if inbox.channel_type == 'Channel::TwilioSms'
validate_email_source_id if inbox.channel_type == 'Channel::Email'
validate_whatsapp_source_id if inbox.channel_type == 'Channel::Whatsapp'
end
end

View file

@ -241,7 +241,7 @@ class Message < ApplicationRecord
end
def validate_attachments_limit(_attachment)
errors.add(attachments: 'exceeded maximum allowed') if attachments.size >= NUMBER_OF_PERMITTED_ATTACHMENTS
errors.add(:attachments, message: 'exceeded maximum allowed') if attachments.size >= NUMBER_OF_PERMITTED_ATTACHMENTS
end
def set_conversation_activity

View file

@ -0,0 +1,6 @@
class AddUniqueIndexToSlug < ActiveRecord::Migration[6.1]
def change
remove_index :articles, :slug
add_index :articles, :slug, unique: true
end
end

View file

@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 2022_09_26_164441) do
ActiveRecord::Schema.define(version: 2022_09_30_025317) do
# These are extensions that must be enabled in order to support this database
enable_extension "pg_stat_statements"
@ -134,7 +134,7 @@ ActiveRecord::Schema.define(version: 2022_09_26_164441) do
t.string "slug", null: false
t.index ["associated_article_id"], name: "index_articles_on_associated_article_id"
t.index ["author_id"], name: "index_articles_on_author_id"
t.index ["slug"], name: "index_articles_on_slug"
t.index ["slug"], name: "index_articles_on_slug", unique: true
end
create_table "attachments", id: :serial, force: :cascade do |t|

View file

@ -6,4 +6,8 @@ module RegexHelper
# shouldn't start with a underscore or hyphen
UNICODE_CHARACTER_NUMBER_HYPHEN_UNDERSCORE = Regexp.new('\A[\p{L}\p{N}]+[\p{L}\p{N}_-]+\Z')
MENTION_REGEX = Regexp.new('\[(@[\w_. ]+)\]\(mention://(?:user|team)/\d+/(.*?)+\)')
TWILIO_CHANNEL_SMS_REGEX = Regexp.new('^\+\d{1,14}\z')
TWILIO_CHANNEL_WHATSAPP_REGEX = Regexp.new('^whatsapp:\+\d{1,14}\z')
WHATSAPP_CHANNEL_REGEX = Regexp.new('^\d{1,14}\z')
end

View file

@ -17,7 +17,7 @@ describe ::ContactInboxBuilder do
source_id: contact.phone_number
).perform
expect(contact_inbox.id).to be(existing_contact_inbox.id)
expect(contact_inbox.id).to eq(existing_contact_inbox.id)
end
it 'does not create contact inbox when contact inbox already exists with phone number and source id is not provided' do
@ -27,7 +27,7 @@ describe ::ContactInboxBuilder do
inbox_id: twilio_inbox.id
).perform
expect(contact_inbox.id).to be(existing_contact_inbox.id)
expect(contact_inbox.id).to eq(existing_contact_inbox.id)
end
it 'creates a new contact inbox when different source id is provided' do
@ -38,8 +38,8 @@ describe ::ContactInboxBuilder do
source_id: '+224213223422'
).perform
expect(contact_inbox.id).not_to be(existing_contact_inbox.id)
expect(contact_inbox.source_id).not_to be('+224213223422')
expect(contact_inbox.id).not_to eq(existing_contact_inbox.id)
expect(contact_inbox.source_id).to eq('+224213223422')
end
it 'creates a contact inbox with contact phone number when source id not provided and no contact inbox exists' do
@ -48,7 +48,7 @@ describe ::ContactInboxBuilder do
inbox_id: twilio_inbox.id
).perform
expect(contact_inbox.source_id).not_to be(contact.phone_number)
expect(contact_inbox.source_id).to eq(contact.phone_number)
end
end
@ -64,7 +64,7 @@ describe ::ContactInboxBuilder do
source_id: "whatsapp:#{contact.phone_number}"
).perform
expect(contact_inbox.id).to be(existing_contact_inbox.id)
expect(contact_inbox.id).to eq(existing_contact_inbox.id)
end
it 'does not create contact inbox when contact inbox already exists with phone number and source id is not provided' do
@ -74,7 +74,7 @@ describe ::ContactInboxBuilder do
inbox_id: twilio_inbox.id
).perform
expect(contact_inbox.id).to be(existing_contact_inbox.id)
expect(contact_inbox.id).to eq(existing_contact_inbox.id)
end
it 'creates a new contact inbox when different source id is provided' do
@ -85,8 +85,8 @@ describe ::ContactInboxBuilder do
source_id: 'whatsapp:+555555'
).perform
expect(contact_inbox.id).not_to be(existing_contact_inbox.id)
expect(contact_inbox.source_id).not_to be('whatsapp:+55555')
expect(contact_inbox.id).not_to eq(existing_contact_inbox.id)
expect(contact_inbox.source_id).to eq('whatsapp:+555555')
end
it 'creates a contact inbox with contact phone number when source id not provided and no contact inbox exists' do
@ -95,7 +95,53 @@ describe ::ContactInboxBuilder do
inbox_id: twilio_inbox.id
).perform
expect(contact_inbox.source_id).not_to be("whatsapp:#{contact.phone_number}")
expect(contact_inbox.source_id).to eq("whatsapp:#{contact.phone_number}")
end
end
describe 'whatsapp inbox' do
let(:whatsapp_inbox) { create(:channel_whatsapp, account: account, sync_templates: false, validate_provider_config: false).inbox }
it 'does not create contact inbox when contact inbox already exists with the source id provided' do
existing_contact_inbox = create(:contact_inbox, contact: contact, inbox: whatsapp_inbox, source_id: contact.phone_number&.delete('+'))
contact_inbox = described_class.new(
contact_id: contact.id,
inbox_id: whatsapp_inbox.id,
source_id: contact.phone_number&.delete('+')
).perform
expect(contact_inbox.id).to be(existing_contact_inbox.id)
end
it 'does not create contact inbox when contact inbox already exists with phone number and source id is not provided' do
existing_contact_inbox = create(:contact_inbox, contact: contact, inbox: whatsapp_inbox, source_id: contact.phone_number&.delete('+'))
contact_inbox = described_class.new(
contact_id: contact.id,
inbox_id: whatsapp_inbox.id
).perform
expect(contact_inbox.id).to be(existing_contact_inbox.id)
end
it 'creates a new contact inbox when different source id is provided' do
existing_contact_inbox = create(:contact_inbox, contact: contact, inbox: whatsapp_inbox, source_id: contact.phone_number&.delete('+'))
contact_inbox = described_class.new(
contact_id: contact.id,
inbox_id: whatsapp_inbox.id,
source_id: '555555'
).perform
expect(contact_inbox.id).not_to be(existing_contact_inbox.id)
expect(contact_inbox.source_id).not_to be('555555')
end
it 'creates a contact inbox with contact phone number when source id not provided and no contact inbox exists' do
contact_inbox = described_class.new(
contact_id: contact.id,
inbox_id: whatsapp_inbox.id
).perform
expect(contact_inbox.source_id).to eq(contact.phone_number&.delete('+'))
end
end
@ -111,7 +157,7 @@ describe ::ContactInboxBuilder do
source_id: contact.phone_number
).perform
expect(contact_inbox.id).to be(existing_contact_inbox.id)
expect(contact_inbox.id).to eq(existing_contact_inbox.id)
end
it 'does not create contact inbox when contact inbox already exists with phone number and source id is not provided' do
@ -121,7 +167,7 @@ describe ::ContactInboxBuilder do
inbox_id: sms_inbox.id
).perform
expect(contact_inbox.id).to be(existing_contact_inbox.id)
expect(contact_inbox.id).to eq(existing_contact_inbox.id)
end
it 'creates a new contact inbox when different source id is provided' do
@ -132,8 +178,8 @@ describe ::ContactInboxBuilder do
source_id: '+224213223422'
).perform
expect(contact_inbox.id).not_to be(existing_contact_inbox.id)
expect(contact_inbox.source_id).not_to be('+224213223422')
expect(contact_inbox.id).not_to eq(existing_contact_inbox.id)
expect(contact_inbox.source_id).to eq('+224213223422')
end
it 'creates a contact inbox with contact phone number when source id not provided and no contact inbox exists' do
@ -142,7 +188,7 @@ describe ::ContactInboxBuilder do
inbox_id: sms_inbox.id
).perform
expect(contact_inbox.source_id).not_to be(contact.phone_number)
expect(contact_inbox.source_id).to eq(contact.phone_number)
end
end
@ -158,7 +204,7 @@ describe ::ContactInboxBuilder do
source_id: contact.email
).perform
expect(contact_inbox.id).to be(existing_contact_inbox.id)
expect(contact_inbox.id).to eq(existing_contact_inbox.id)
end
it 'does not create contact inbox when contact inbox already exists with email and source id is not provided' do
@ -168,7 +214,7 @@ describe ::ContactInboxBuilder do
inbox_id: email_inbox.id
).perform
expect(contact_inbox.id).to be(existing_contact_inbox.id)
expect(contact_inbox.id).to eq(existing_contact_inbox.id)
end
it 'creates a new contact inbox when different source id is provided' do
@ -179,8 +225,8 @@ describe ::ContactInboxBuilder do
source_id: 'xyc@xyc.com'
).perform
expect(contact_inbox.id).not_to be(existing_contact_inbox.id)
expect(contact_inbox.source_id).not_to be('xyc@xyc.com')
expect(contact_inbox.id).not_to eq(existing_contact_inbox.id)
expect(contact_inbox.source_id).to eq('xyc@xyc.com')
end
it 'creates a contact inbox with contact email when source id not provided and no contact inbox exists' do
@ -189,7 +235,7 @@ describe ::ContactInboxBuilder do
inbox_id: email_inbox.id
).perform
expect(contact_inbox.source_id).not_to be(contact.email)
expect(contact_inbox.source_id).to eq(contact.email)
end
end
@ -205,7 +251,7 @@ describe ::ContactInboxBuilder do
source_id: 'test'
).perform
expect(contact_inbox.id).to be(existing_contact_inbox.id)
expect(contact_inbox.id).to eq(existing_contact_inbox.id)
end
it 'creates a new contact inbox when different source id is provided' do
@ -216,8 +262,8 @@ describe ::ContactInboxBuilder do
source_id: 'test'
).perform
expect(contact_inbox.id).not_to be(existing_contact_inbox.id)
expect(contact_inbox.source_id).not_to be('test')
expect(contact_inbox.id).not_to eq(existing_contact_inbox.id)
expect(contact_inbox.source_id).to eq('test')
end
it 'creates a contact inbox with SecureRandom.uuid when source id not provided and no contact inbox exists' do

View file

@ -96,15 +96,24 @@ RSpec.describe 'Platform Users API', type: :request do
it 'creates a new user and permissible for the user' do
expect do
post '/platform/api/v1/users/', params: { name: 'test', email: 'test@test.com', password: 'Password1!',
post '/platform/api/v1/users/', params: { name: 'test', display_name: 'displaytest',
email: 'test@test.com', password: 'Password1!',
custom_attributes: { test: 'test_create' } },
headers: { api_access_token: platform_app.access_token.token }, as: :json
end.not_to enqueue_mail
expect(response).to have_http_status(:success)
data = JSON.parse(response.body)
expect(data['email']).to eq('test@test.com')
expect(data['custom_attributes']['test']).to eq('test_create')
expect(data).to match(
hash_including(
'name' => 'test',
'display_name' => 'displaytest',
'email' => 'test@test.com',
'custom_attributes' => {
'test' => 'test_create'
}
)
)
expect(platform_app.platform_app_permissibles.first.permissible_id).to eq data['id']
end

View file

@ -3,8 +3,7 @@ FactoryBot.define do
account_id { 1 }
category_id { 1 }
author_id { 1 }
title { 'MyString' }
slug { 'MyString' }
title { Faker::Movie.title }
content { 'MyText' }
description { 'MyDescrption' }
status { 1 }

View file

@ -15,6 +15,8 @@ def generate_source_id(contact_inbox)
contact_inbox.inbox.channel.medium == 'sms' ? Faker::PhoneNumber.cell_phone_in_e164 : "whatsapp:#{Faker::PhoneNumber.cell_phone_in_e164}"
when 'Channel::Email'
"#{SecureRandom.uuid}@acme.inc"
when 'Channel::Whatsapp'
Faker::PhoneNumber.cell_phone_in_e164.delete('+')
else
SecureRandom.uuid
end

View file

@ -119,11 +119,23 @@ RSpec.describe Article, type: :model do
records = portal_1.articles.search(params)
expect(records.count).to eq(2)
end
it 'auto saves article slug' do
article = create(:article, category_id: category_1.id, title: 'the awesome article 1', content: 'This is the content', portal_id: portal_1.id,
author_id: user.id)
expect(article.slug).to include('the-awesome-article-1')
end
end
context 'with pagination' do
it 'returns paginated articles' do
create_list(:article, 30, category_id: category_2.id, slug: 'title-1', title: 'title 1', portal_id: portal_2.id, author_id: user.id)
build_list(:article, 30) do |record, i|
record.category_id = category_2.id
record.title = "title #{i}"
record.portal_id = portal_2.id
record.author_id = user.id
record.save!
end
params = { category_slug: 'category_2' }
records = portal_2.articles.search(params)
expect(records.count).to eq(25)

View file

@ -37,4 +37,59 @@ RSpec.describe ContactInbox do
expect(obj.pubsub_token).to eq(new_token)
end
end
describe 'validations' do
context 'when source_id' do
it 'validates whatsapp channel source_id' do
whatsapp_inbox = create(:channel_whatsapp, sync_templates: false, validate_provider_config: false).inbox
contact = create(:contact)
valid_source_id = build(:contact_inbox, contact: contact, inbox: whatsapp_inbox, source_id: '1234567890')
ci_character_in_source_id = build(:contact_inbox, contact: contact, inbox: whatsapp_inbox, source_id: '1234567890aaa')
ci_plus_in_source_id = build(:contact_inbox, contact: contact, inbox: whatsapp_inbox, source_id: '+1234567890')
expect(valid_source_id.valid?).to be(true)
expect(ci_character_in_source_id.valid?).to be(false)
expect(ci_character_in_source_id.errors.full_messages).to eq(
['Source invalid source id for whatsapp inbox. valid Regex (?-mix:^\\d{1,14}\\z)']
)
expect(ci_plus_in_source_id.valid?).to be(false)
expect(ci_plus_in_source_id.errors.full_messages).to eq(
['Source invalid source id for whatsapp inbox. valid Regex (?-mix:^\\d{1,14}\\z)']
)
end
it 'validates twilio sms channel source_id' do
twilio_sms_inbox = create(:channel_twilio_sms).inbox
contact = create(:contact)
valid_source_id = build(:contact_inbox, contact: contact, inbox: twilio_sms_inbox, source_id: '+1234567890')
ci_character_in_source_id = build(:contact_inbox, contact: contact, inbox: twilio_sms_inbox, source_id: '+1234567890aaa')
ci_without_plus_in_source_id = build(:contact_inbox, contact: contact, inbox: twilio_sms_inbox, source_id: '1234567890')
expect(valid_source_id.valid?).to be(true)
expect(ci_character_in_source_id.valid?).to be(false)
expect(ci_character_in_source_id.errors.full_messages).to eq(
['Source invalid source id for twilio sms inbox. valid Regex (?-mix:^\\+\\d{1,14}\\z)']
)
expect(ci_without_plus_in_source_id.valid?).to be(false)
expect(ci_without_plus_in_source_id.errors.full_messages).to eq(
['Source invalid source id for twilio sms inbox. valid Regex (?-mix:^\\+\\d{1,14}\\z)']
)
end
it 'validates twilio whatsapp channel source_id' do
twilio_whatsapp_inbox = create(:channel_twilio_sms, medium: :whatsapp).inbox
contact = create(:contact)
valid_source_id = build(:contact_inbox, contact: contact, inbox: twilio_whatsapp_inbox, source_id: 'whatsapp:+1234567890')
ci_character_in_source_id = build(:contact_inbox, contact: contact, inbox: twilio_whatsapp_inbox, source_id: 'whatsapp:+1234567890aaa')
ci_without_plus_in_source_id = build(:contact_inbox, contact: contact, inbox: twilio_whatsapp_inbox, source_id: 'whatsapp:1234567890')
expect(valid_source_id.valid?).to be(true)
expect(ci_character_in_source_id.valid?).to be(false)
expect(ci_character_in_source_id.errors.full_messages).to eq(
['Source invalid source id for twilio whatsapp inbox. valid Regex (?-mix:^whatsapp:\\+\\d{1,14}\\z)']
)
expect(ci_without_plus_in_source_id.valid?).to be(false)
expect(ci_without_plus_in_source_id.errors.full_messages).to eq(
['Source invalid source id for twilio whatsapp inbox. valid Regex (?-mix:^whatsapp:\\+\\d{1,14}\\z)']
)
end
end
end
end

View file

@ -106,6 +106,19 @@ RSpec.describe Message, type: :model do
end
end
context 'when attachments size maximum' do
let(:message) { build(:message, content_type: nil, account: create(:account)) }
it 'add errors to message for attachment size is more than allowed limit' do
16.times.each do
attachment = message.attachments.new(account_id: message.account_id, file_type: :image)
attachment.file.attach(io: File.open(Rails.root.join('spec/assets/avatar.png')), filename: 'avatar.png', content_type: 'image/png')
end
expect(message.errors.messages).to eq({ attachments: ['exceeded maximum allowed'] })
end
end
context 'when email notifiable message' do
let(:message) { build(:message, content_type: nil, account: create(:account)) }