From 3e5ca9bca95df2c7ea5d1dc86e04f8a79724281f Mon Sep 17 00:00:00 2001 From: Sivin Varghese <64252451+iamsivin@users.noreply.github.com> Date: Wed, 9 Jul 2025 09:23:20 +0530 Subject: [PATCH 1/6] fix: Widget message input resize issue (#11896) --- app/javascript/shared/components/ResizableTextArea.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/javascript/shared/components/ResizableTextArea.vue b/app/javascript/shared/components/ResizableTextArea.vue index 088753a23..4dda62cf9 100644 --- a/app/javascript/shared/components/ResizableTextArea.vue +++ b/app/javascript/shared/components/ResizableTextArea.vue @@ -69,7 +69,7 @@ export default { }, }, watch: { - value() { + modelValue() { this.resizeTextarea(); // 🚨 watch triggers every time the value is changed, we cannot set this to focus then // when this runs, it sets the cursor to the end of the body, ignoring the signature From 5140deb6f682026594f1be847a643466829bbb96 Mon Sep 17 00:00:00 2001 From: Sivin Varghese <64252451+iamsivin@users.noreply.github.com> Date: Wed, 9 Jul 2025 22:21:25 +0530 Subject: [PATCH 2/6] feat: Captain settings header component (#11912) --- .../settings/SettingsHeader.story.vue | 28 +++++++++++++++++++ .../settings/SettingsHeader.vue | 19 +++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 app/javascript/dashboard/components-next/captain/pageComponents/settings/SettingsHeader.story.vue create mode 100644 app/javascript/dashboard/components-next/captain/pageComponents/settings/SettingsHeader.vue diff --git a/app/javascript/dashboard/components-next/captain/pageComponents/settings/SettingsHeader.story.vue b/app/javascript/dashboard/components-next/captain/pageComponents/settings/SettingsHeader.story.vue new file mode 100644 index 000000000..654e5ab16 --- /dev/null +++ b/app/javascript/dashboard/components-next/captain/pageComponents/settings/SettingsHeader.story.vue @@ -0,0 +1,28 @@ + + + diff --git a/app/javascript/dashboard/components-next/captain/pageComponents/settings/SettingsHeader.vue b/app/javascript/dashboard/components-next/captain/pageComponents/settings/SettingsHeader.vue new file mode 100644 index 000000000..dc6b7dda9 --- /dev/null +++ b/app/javascript/dashboard/components-next/captain/pageComponents/settings/SettingsHeader.vue @@ -0,0 +1,19 @@ + + + From 17500cc62d3fdf23c5ff1c8c238e866289de7dab Mon Sep 17 00:00:00 2001 From: Muhsin Keloth Date: Thu, 10 Jul 2025 11:36:37 +0530 Subject: [PATCH 3/6] chore: Auto assign PR to author when PR opened (#11890) - gh action to auto-assign PR to author when PR opened --- .github/workflows/auto-assign-pr.yml | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 .github/workflows/auto-assign-pr.yml diff --git a/.github/workflows/auto-assign-pr.yml b/.github/workflows/auto-assign-pr.yml new file mode 100644 index 000000000..98df89707 --- /dev/null +++ b/.github/workflows/auto-assign-pr.yml @@ -0,0 +1,28 @@ +name: Auto-assign PR to Author + +on: + pull_request: + types: [opened] + +jobs: + auto-assign: + runs-on: ubuntu-latest + permissions: + pull-requests: write + steps: + - name: Auto-assign PR to author + uses: actions/github-script@v7 + with: + script: | + const { owner, repo } = context.repo; + const pull_number = context.payload.pull_request.number; + const author = context.payload.pull_request.user.login; + + await github.rest.issues.addAssignees({ + owner, + repo, + issue_number: pull_number, + assignees: [author] + }); + + console.log(`Assigned PR #${pull_number} to ${author}`); \ No newline at end of file From dd888f2cf016451d47ea7d7d9fb7845ab5e531e6 Mon Sep 17 00:00:00 2001 From: Tanmay Deep Sharma <32020192+tds-1@users.noreply.github.com> Date: Thu, 10 Jul 2025 15:50:31 +0700 Subject: [PATCH 4/6] fix review changes --- app/controllers/whatsapp/embedded_controller.rb | 3 +-- .../captain/pageComponents/document/DocumentForm.vue | 2 +- app/services/whatsapp/embedded_signup_service.rb | 5 ++++- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/app/controllers/whatsapp/embedded_controller.rb b/app/controllers/whatsapp/embedded_controller.rb index 625a11f3e..5589285d8 100644 --- a/app/controllers/whatsapp/embedded_controller.rb +++ b/app/controllers/whatsapp/embedded_controller.rb @@ -10,8 +10,7 @@ class Whatsapp::EmbeddedController < ApplicationController render json: { status: 'ready', app_id: GlobalConfigService.load('WHATSAPP_APP_ID', ''), - config_id: GlobalConfigService.load('WHATSAPP_CONFIGURATION_ID', ''), - app_secret: GlobalConfigService.load('WHATSAPP_APP_SECRET', '') + config_id: GlobalConfigService.load('WHATSAPP_CONFIGURATION_ID', '') } end diff --git a/app/javascript/dashboard/components-next/captain/pageComponents/document/DocumentForm.vue b/app/javascript/dashboard/components-next/captain/pageComponents/document/DocumentForm.vue index d85ba8a06..dd0ff7962 100644 --- a/app/javascript/dashboard/components-next/captain/pageComponents/document/DocumentForm.vue +++ b/app/javascript/dashboard/components-next/captain/pageComponents/document/DocumentForm.vue @@ -19,7 +19,7 @@ const formState = { }; const initialState = { - name: '', + url: '', assistantId: null, }; diff --git a/app/services/whatsapp/embedded_signup_service.rb b/app/services/whatsapp/embedded_signup_service.rb index 95ecfac2b..e7aa6a797 100644 --- a/app/services/whatsapp/embedded_signup_service.rb +++ b/app/services/whatsapp/embedded_signup_service.rb @@ -97,11 +97,14 @@ class Whatsapp::EmbeddedSignupService end def register_phone_number(phone_number_id, access_token) + # Generate a random 6-digit PIN + pin = SecureRandom.random_number(900_000) + 100_000 + HTTParty.post( "https://graph.facebook.com/#{whatsapp_api_version}/#{phone_number_id}/register", { headers: { 'Authorization' => "Bearer #{access_token}", 'Content-Type' => 'application/json' }, - body: { messaging_product: 'whatsapp', pin: '212834' }.to_json + body: { messaging_product: 'whatsapp', pin: pin.to_s }.to_json } ) end From 07b1fc202e3d8ed4d1b73e9655053f9745271414 Mon Sep 17 00:00:00 2001 From: Tanmay Deep Sharma <32020192+tds-1@users.noreply.github.com> Date: Thu, 10 Jul 2025 15:54:08 +0700 Subject: [PATCH 5/6] revert extra changes --- .../captain/pageComponents/document/DocumentForm.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/javascript/dashboard/components-next/captain/pageComponents/document/DocumentForm.vue b/app/javascript/dashboard/components-next/captain/pageComponents/document/DocumentForm.vue index dd0ff7962..d85ba8a06 100644 --- a/app/javascript/dashboard/components-next/captain/pageComponents/document/DocumentForm.vue +++ b/app/javascript/dashboard/components-next/captain/pageComponents/document/DocumentForm.vue @@ -19,7 +19,7 @@ const formState = { }; const initialState = { - url: '', + name: '', assistantId: null, }; From f8ad34a0b0af1a9b2647bc2fbc975b23e26af747 Mon Sep 17 00:00:00 2001 From: Tanmay Deep Sharma <32020192+tds-1@users.noreply.github.com> Date: Thu, 10 Jul 2025 16:43:21 +0700 Subject: [PATCH 6/6] update test cases --- .../whatsapp/embedded_controller_spec.rb | 3 +- .../whatsapp/embedded_signup_service_spec.rb | 45 ++++++++++--------- 2 files changed, 25 insertions(+), 23 deletions(-) diff --git a/spec/controllers/whatsapp/embedded_controller_spec.rb b/spec/controllers/whatsapp/embedded_controller_spec.rb index 9d91a6488..fde3a1838 100644 --- a/spec/controllers/whatsapp/embedded_controller_spec.rb +++ b/spec/controllers/whatsapp/embedded_controller_spec.rb @@ -23,8 +23,7 @@ RSpec.describe 'WhatsApp Embedded API', type: :request do expect(json_response).to include( 'status' => 'ready', 'app_id' => 'test_app_id', - 'config_id' => 'test_config_id', - 'app_secret' => 'test_app_secret' + 'config_id' => 'test_config_id' ) end end diff --git a/spec/services/whatsapp/embedded_signup_service_spec.rb b/spec/services/whatsapp/embedded_signup_service_spec.rb index 37269e5e1..7534407c9 100644 --- a/spec/services/whatsapp/embedded_signup_service_spec.rb +++ b/spec/services/whatsapp/embedded_signup_service_spec.rb @@ -2,15 +2,6 @@ require 'rails_helper' describe Whatsapp::EmbeddedSignupService do let(:account) { create(:account) } - let(:code) { 'test_authorization_code' } - let(:business_id) { 'test_business_id' } - let(:waba_id) { 'test_waba_id' } - let(:phone_number_id) { 'test_phone_number_id' } - let(:access_token) { 'test_access_token' } - let(:app_id) { 'test_app_id' } - let(:app_secret) { 'test_app_secret' } - let(:api_version) { 'v22.0' } - let(:service) do described_class.new( account: account, @@ -20,9 +11,19 @@ describe Whatsapp::EmbeddedSignupService do phone_number_id: phone_number_id ) end + let(:code) { 'test_authorization_code' } + let(:business_id) { 'test_business_id' } + let(:waba_id) { 'test_waba_id' } + let(:phone_number_id) { 'test_phone_number_id' } + let(:access_token) { 'test_access_token' } + let(:app_id) { 'test_app_id' } + let(:app_secret) { 'test_app_secret' } + let(:api_version) { 'v22.0' } + let(:unique_phone_number) { "+123456789#{SecureRandom.hex(4)}" } before do - # Mock global configuration + # Clean up any existing WhatsApp channels before each test + Channel::Whatsapp.destroy_all allow(GlobalConfigService).to receive(:load).with('WHATSAPP_APP_ID', '').and_return(app_id) allow(GlobalConfigService).to receive(:load).with('WHATSAPP_APP_SECRET', '').and_return(app_secret) allow(GlobalConfigService).to receive(:load).with('WHATSAPP_API_VERSION', 'v22.0').and_return(api_version) @@ -64,7 +65,7 @@ describe Whatsapp::EmbeddedSignupService do data: [ { id: phone_number_id, - display_phone_number: '1234567890', + display_phone_number: unique_phone_number.delete('+'), verified_name: 'Test Business', code_verification_status: 'VERIFIED' } @@ -123,7 +124,7 @@ describe Whatsapp::EmbeddedSignupService do it 'successfully creates a new WhatsApp channel' do expect { service.perform }.not_to raise_error - channel = Channel::Whatsapp.find_by(account: account, phone_number: '+1234567890') + channel = Channel::Whatsapp.find_by(account: account, phone_number: unique_phone_number) expect(channel).not_to be_nil expect(channel.provider).to eq('whatsapp_cloud') expect(channel.provider_config['api_key']).to eq(access_token) @@ -135,20 +136,22 @@ describe Whatsapp::EmbeddedSignupService do it 'creates an inbox for the channel' do service.perform - channel = Channel::Whatsapp.find_by(account: account, phone_number: '+1234567890') + channel = Channel::Whatsapp.find_by(account: account, phone_number: unique_phone_number) inbox = Inbox.find_by(account: account, channel: channel) expect(inbox).not_to be_nil expect(inbox.name).to eq('Test Business WhatsApp') end it 'registers the phone number' do + # Mock SecureRandom to return a predictable value + allow(SecureRandom).to receive(:random_number).with(900_000).and_return(140_214) service.perform expect(WebMock).to have_requested(:post, "https://graph.facebook.com/#{api_version}/#{phone_number_id}/register") .with( body: { messaging_product: 'whatsapp', - pin: '212834' + pin: '240214' }.to_json ) end @@ -156,7 +159,7 @@ describe Whatsapp::EmbeddedSignupService do it 'sets up webhook subscription' do service.perform - channel = Channel::Whatsapp.find_by(account: account, phone_number: '+1234567890') + channel = Channel::Whatsapp.find_by(account: account, phone_number: unique_phone_number) callback_url = "https://app.chatwoot.com/webhooks/whatsapp/#{channel.phone_number}" expect(WebMock).to have_requested(:post, "https://graph.facebook.com/#{api_version}/#{waba_id}/subscribed_apps") @@ -242,7 +245,7 @@ describe Whatsapp::EmbeddedSignupService do data: [ { id: phone_number_id, - display_phone_number: '1234567890', + display_phone_number: unique_phone_number.delete('+'), verified_name: 'Test Business', code_verification_status: 'VERIFIED' } @@ -287,7 +290,7 @@ describe Whatsapp::EmbeddedSignupService do ) # Create existing channel - create(:channel_whatsapp, account: account, phone_number: '+1234567890') + create(:channel_whatsapp, account: account, phone_number: unique_phone_number) end it 'raises an error' do @@ -333,7 +336,7 @@ describe Whatsapp::EmbeddedSignupService do data: [ { id: phone_number_id, - display_phone_number: '1234567890', + display_phone_number: unique_phone_number.delete('+'), verified_name: 'Test Business', code_verification_status: 'VERIFIED' } @@ -415,7 +418,7 @@ describe Whatsapp::EmbeddedSignupService do data: [ { id: phone_number_id, - display_phone_number: '1234567890', + display_phone_number: unique_phone_number.delete('+'), verified_name: 'Test Business', code_verification_status: 'VERIFIED' } @@ -524,7 +527,7 @@ describe Whatsapp::EmbeddedSignupService do data: [ { id: phone_number_id, - display_phone_number: '1234567890', + display_phone_number: unique_phone_number.delete('+'), verified_name: 'Test Business', code_verification_status: 'VERIFIED' } @@ -538,7 +541,7 @@ describe Whatsapp::EmbeddedSignupService do result = service.send(:fetch_phone_info_via_waba, waba_id, phone_number_id, access_token) expect(result).to eq({ phone_number_id: phone_number_id, - phone_number: '+1234567890', + phone_number: unique_phone_number, verified: true, business_name: 'Test Business' })