Files
clientsflow/research/chatwoot/spec/controllers/tiktok/callbacks_controller_spec.rb

140 lines
4.8 KiB
Ruby

require 'rails_helper'
RSpec.describe 'TikTok Callbacks', type: :request do
let(:account) { create(:account) }
let(:client_secret) { 'tiktok-app-secret' }
let(:client_id) { 'tiktok-app-id' }
let(:token_endpoint) { 'https://business-api.tiktok.com/open_api/v1.3/tt_user/oauth2/token/' }
let(:business_endpoint) { 'https://business-api.tiktok.com/open_api/v1.3/business/get/' }
let(:tiktok_access_token) { 'access-token-1' }
let(:tiktok_refresh_token) { 'refresh-token-1' }
let(:tiktok_business_id) { 'biz-123' }
let(:token_response) do
{
code: 0,
message: 'ok',
data: {
open_id: tiktok_business_id,
scope: Tiktok::AuthClient::REQUIRED_SCOPES.join(','),
access_token: tiktok_access_token,
refresh_token: tiktok_refresh_token,
expires_in: 86_400,
refresh_token_expires_in: 2_592_000
}
}.to_json
end
let(:business_response) do
{
code: 0,
message: 'ok',
data: {
username: 'tiktok_user',
display_name: 'TikTok Display Name',
profile_image: 'https://www.example.com/avatar.png'
}
}.to_json
end
let(:state) do
JWT.encode({ sub: account.id, iat: Time.current.to_i }, client_secret, 'HS256')
end
before do
InstallationConfig.where(name: %w[TIKTOK_APP_ID TIKTOK_APP_SECRET]).delete_all
GlobalConfig.clear_cache
stub_request(:post, token_endpoint).to_return(status: 200, body: token_response, headers: { 'Content-Type' => 'application/json' })
stub_request(:get, business_endpoint)
.with(query: hash_including('business_id' => tiktok_business_id))
.to_return(status: 200, body: business_response, headers: { 'Content-Type' => 'application/json' })
end
it 'creates channel and inbox and redirects to agents step for new connections' do
expect(Avatar::AvatarFromUrlJob).to receive(:perform_later).with(instance_of(Inbox), 'https://www.example.com/avatar.png')
with_modified_env TIKTOK_APP_ID: client_id, TIKTOK_APP_SECRET: client_secret do
expect do
get '/tiktok/callback', params: { code: 'valid_code', state: state }
end.to change(Channel::Tiktok, :count).by(1).and change(Inbox, :count).by(1)
end
inbox = Inbox.last
channel = inbox.channel
expect(channel.business_id).to eq(tiktok_business_id)
expect(channel.access_token).to eq(tiktok_access_token)
expect(channel.refresh_token).to eq(tiktok_refresh_token)
expect(response).to redirect_to(app_tiktok_inbox_agents_url(account_id: account.id, inbox_id: inbox.id))
end
it 'updates an existing channel and redirects to settings' do
existing_channel = create(
:channel_tiktok,
account: account,
business_id: tiktok_business_id,
access_token: 'old-access-token',
refresh_token: 'old-refresh-token',
expires_at: 1.hour.ago,
refresh_token_expires_at: 1.day.from_now
)
existing_channel.inbox.update!(name: 'Old Name')
with_modified_env TIKTOK_APP_ID: client_id, TIKTOK_APP_SECRET: client_secret do
expect do
get '/tiktok/callback', params: { code: 'valid_code', state: state }
end.to not_change(Channel::Tiktok, :count).and not_change(Inbox, :count)
end
existing_channel.reload
inbox = existing_channel.inbox.reload
expect(existing_channel.access_token).to eq(tiktok_access_token)
expect(existing_channel.refresh_token).to eq(tiktok_refresh_token)
expect(inbox.name).to eq('TikTok Display Name')
expect(response).to redirect_to(app_tiktok_inbox_settings_url(account_id: account.id, inbox_id: inbox.id))
end
it 'redirects to error page when user denies authorization' do
with_modified_env TIKTOK_APP_ID: client_id, TIKTOK_APP_SECRET: client_secret do
get '/tiktok/callback', params: { error: 'access_denied', error_description: 'User cancelled', error_code: '400', state: state }
end
expect(response).to redirect_to(
app_new_tiktok_inbox_url(
account_id: account.id,
error_type: 'access_denied',
code: '400',
error_message: 'User cancelled'
)
)
end
it 'redirects to error page when required scopes are not granted' do
stub_request(:post, token_endpoint).to_return(
status: 200,
body: JSON.parse(token_response).deep_merge('data' => { 'scope' => 'user.info.basic' }).to_json,
headers: { 'Content-Type' => 'application/json' }
)
with_modified_env TIKTOK_APP_ID: client_id, TIKTOK_APP_SECRET: client_secret do
get '/tiktok/callback', params: { code: 'valid_code', state: state }
end
expect(response).to redirect_to(
app_new_tiktok_inbox_url(
account_id: account.id,
error_type: 'ungranted_scopes',
code: 400,
error_message: 'User did not grant all the required scopes'
)
)
end
end