mirror of
				https://github.com/lingble/chatwoot.git
				synced 2025-10-31 19:17:48 +00:00 
			
		
		
		
	 9145658597
			
		
	
	9145658597
	
	
	
		
			
			We were using UTM params on various branding urls which weren't compliant to standard utm params and hence were ignored by analytics tooling. this PR ensures that the params stays compliant with defined standard ref: https://en.wikipedia.org/wiki/UTM_parameters ## Changes - updated utm tags on widget and survey urls - added utm on helpcenter branding --------- Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
		
			
				
	
	
		
			331 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
			
		
		
	
	
			331 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
| require 'rails_helper'
 | |
| 
 | |
| describe PortalHelper do
 | |
|   describe '#generate_portal_bg_color' do
 | |
|     context 'when theme is dark' do
 | |
|       it 'returns the correct color mix with black' do
 | |
|         expect(helper.generate_portal_bg_color('#ff0000', 'dark')).to eq(
 | |
|           'color-mix(in srgb, #ff0000 20%, black)'
 | |
|         )
 | |
|       end
 | |
|     end
 | |
| 
 | |
|     context 'when theme is not dark' do
 | |
|       it 'returns the correct color mix with white' do
 | |
|         expect(helper.generate_portal_bg_color('#ff0000', 'light')).to eq(
 | |
|           'color-mix(in srgb, #ff0000 20%, white)'
 | |
|         )
 | |
|       end
 | |
|     end
 | |
| 
 | |
|     context 'when provided with various colors' do
 | |
|       it 'adjusts the color mix appropriately' do
 | |
|         expect(helper.generate_portal_bg_color('#00ff00', 'dark')).to eq(
 | |
|           'color-mix(in srgb, #00ff00 20%, black)'
 | |
|         )
 | |
|         expect(helper.generate_portal_bg_color('#0000ff', 'light')).to eq(
 | |
|           'color-mix(in srgb, #0000ff 20%, white)'
 | |
|         )
 | |
|       end
 | |
|     end
 | |
|   end
 | |
| 
 | |
|   describe '#generate_portal_bg' do
 | |
|     context 'when theme is dark' do
 | |
|       it 'returns the correct background with dark grid image and color mix with black' do
 | |
|         expected_bg = 'color-mix(in srgb, #ff0000 20%, black)'
 | |
|         expect(helper.generate_portal_bg('#ff0000', 'dark')).to eq(expected_bg)
 | |
|       end
 | |
|     end
 | |
| 
 | |
|     context 'when theme is not dark' do
 | |
|       it 'returns the correct background with light grid image and color mix with white' do
 | |
|         expected_bg = 'color-mix(in srgb, #ff0000 20%, white)'
 | |
|         expect(helper.generate_portal_bg('#ff0000', 'light')).to eq(expected_bg)
 | |
|       end
 | |
|     end
 | |
| 
 | |
|     context 'when provided with various colors' do
 | |
|       it 'adjusts the background appropriately for dark theme' do
 | |
|         expected_bg = 'color-mix(in srgb, #00ff00 20%, black)'
 | |
|         expect(helper.generate_portal_bg('#00ff00', 'dark')).to eq(expected_bg)
 | |
|       end
 | |
| 
 | |
|       it 'adjusts the background appropriately for light theme' do
 | |
|         expected_bg = 'color-mix(in srgb, #0000ff 20%, white)'
 | |
|         expect(helper.generate_portal_bg('#0000ff', 'light')).to eq(expected_bg)
 | |
|       end
 | |
|     end
 | |
|   end
 | |
| 
 | |
|   describe '#generate_gradient_to_bottom' do
 | |
|     context 'when theme is dark' do
 | |
|       it 'returns the correct gradient' do
 | |
|         expect(helper.generate_gradient_to_bottom('dark')).to eq(
 | |
|           'linear-gradient(to bottom, transparent, #151718)'
 | |
|         )
 | |
|       end
 | |
|     end
 | |
| 
 | |
|     context 'when theme is not dark' do
 | |
|       it 'returns the correct gradient' do
 | |
|         expect(helper.generate_gradient_to_bottom('light')).to eq(
 | |
|           'linear-gradient(to bottom, transparent, white)'
 | |
|         )
 | |
|       end
 | |
|     end
 | |
| 
 | |
|     context 'when provided with various colors' do
 | |
|       it 'adjusts the gradient appropriately' do
 | |
|         expect(helper.generate_gradient_to_bottom('dark')).to eq(
 | |
|           'linear-gradient(to bottom, transparent, #151718)'
 | |
|         )
 | |
|         expect(helper.generate_gradient_to_bottom('light')).to eq(
 | |
|           'linear-gradient(to bottom, transparent, white)'
 | |
|         )
 | |
|       end
 | |
|     end
 | |
|   end
 | |
| 
 | |
|   describe '#generate_portal_hover_color' do
 | |
|     context 'when theme is dark' do
 | |
|       it 'returns the correct color mix with #1B1B1B' do
 | |
|         expect(helper.generate_portal_hover_color('#ff0000', 'dark')).to eq(
 | |
|           'color-mix(in srgb, #ff0000 5%, #1B1B1B)'
 | |
|         )
 | |
|       end
 | |
|     end
 | |
| 
 | |
|     context 'when theme is not dark' do
 | |
|       it 'returns the correct color mix with #F9F9F9' do
 | |
|         expect(helper.generate_portal_hover_color('#ff0000', 'light')).to eq(
 | |
|           'color-mix(in srgb, #ff0000 5%, #F9F9F9)'
 | |
|         )
 | |
|       end
 | |
|     end
 | |
| 
 | |
|     context 'when provided with various colors' do
 | |
|       it 'adjusts the color mix appropriately' do
 | |
|         expect(helper.generate_portal_hover_color('#00ff00', 'dark')).to eq(
 | |
|           'color-mix(in srgb, #00ff00 5%, #1B1B1B)'
 | |
|         )
 | |
|         expect(helper.generate_portal_hover_color('#0000ff', 'light')).to eq(
 | |
|           'color-mix(in srgb, #0000ff 5%, #F9F9F9)'
 | |
|         )
 | |
|       end
 | |
|     end
 | |
|   end
 | |
| 
 | |
|   describe '#theme_query_string' do
 | |
|     context 'when theme is present and not system' do
 | |
|       it 'returns the correct query string' do
 | |
|         expect(helper.theme_query_string('dark')).to eq('?theme=dark')
 | |
|       end
 | |
|     end
 | |
| 
 | |
|     context 'when theme is not present' do
 | |
|       it 'returns the correct query string' do
 | |
|         expect(helper.theme_query_string(nil)).to eq('')
 | |
|       end
 | |
|     end
 | |
| 
 | |
|     context 'when theme is system' do
 | |
|       it 'returns the correct query string' do
 | |
|         expect(helper.theme_query_string('system')).to eq('')
 | |
|       end
 | |
|     end
 | |
|   end
 | |
| 
 | |
|   describe '#generate_home_link' do
 | |
|     context 'when theme is not present' do
 | |
|       it 'returns the correct link' do
 | |
|         expect(helper.generate_home_link('portal_slug', 'en', nil, true)).to eq(
 | |
|           '/hc/portal_slug/en'
 | |
|         )
 | |
|       end
 | |
|     end
 | |
| 
 | |
|     context 'when theme is present and plain layout is enabled' do
 | |
|       it 'returns the correct link' do
 | |
|         expect(helper.generate_home_link('portal_slug', 'en', 'dark', true)).to eq(
 | |
|           '/hc/portal_slug/en?theme=dark'
 | |
|         )
 | |
|       end
 | |
|     end
 | |
| 
 | |
|     context 'when plain layout is not enabled' do
 | |
|       it 'returns the correct link' do
 | |
|         expect(helper.generate_home_link('portal_slug', 'en', 'dark', false)).to eq(
 | |
|           '/hc/portal_slug/en'
 | |
|         )
 | |
|       end
 | |
|     end
 | |
|   end
 | |
| 
 | |
|   describe '#generate_category_link' do
 | |
|     context 'when theme is not present' do
 | |
|       it 'returns the correct link' do
 | |
|         expect(helper.generate_category_link(
 | |
|                  portal_slug: 'portal_slug',
 | |
|                  category_locale: 'en',
 | |
|                  category_slug: 'category_slug',
 | |
|                  theme: nil,
 | |
|                  is_plain_layout_enabled: true
 | |
|                )).to eq(
 | |
|                  '/hc/portal_slug/en/categories/category_slug'
 | |
|                )
 | |
|       end
 | |
|     end
 | |
| 
 | |
|     context 'when theme is present and plain layout is enabled' do
 | |
|       it 'returns the correct link' do
 | |
|         expect(helper.generate_category_link(
 | |
|                  portal_slug: 'portal_slug',
 | |
|                  category_locale: 'en',
 | |
|                  category_slug: 'category_slug',
 | |
|                  theme: 'dark',
 | |
|                  is_plain_layout_enabled: true
 | |
|                )).to eq(
 | |
|                  '/hc/portal_slug/en/categories/category_slug?theme=dark'
 | |
|                )
 | |
|       end
 | |
|     end
 | |
| 
 | |
|     context 'when plain layout is not enabled' do
 | |
|       it 'returns the correct link' do
 | |
|         expect(helper.generate_category_link(
 | |
|                  portal_slug: 'portal_slug',
 | |
|                  category_locale: 'en',
 | |
|                  category_slug: 'category_slug',
 | |
|                  theme: 'dark',
 | |
|                  is_plain_layout_enabled: false
 | |
|                )).to eq(
 | |
|                  '/hc/portal_slug/en/categories/category_slug'
 | |
|                )
 | |
|       end
 | |
|     end
 | |
|   end
 | |
| 
 | |
|   describe '#generate_article_link' do
 | |
|     context 'when theme is not present' do
 | |
|       it 'returns the correct link' do
 | |
|         expect(helper.generate_article_link('portal_slug', 'article_slug', nil, true)).to eq(
 | |
|           '/hc/portal_slug/articles/article_slug'
 | |
|         )
 | |
|       end
 | |
|     end
 | |
| 
 | |
|     context 'when theme is present and plain layout is enabled' do
 | |
|       it 'returns the correct link' do
 | |
|         expect(helper.generate_article_link('portal_slug', 'article_slug', 'dark', true)).to eq(
 | |
|           '/hc/portal_slug/articles/article_slug?theme=dark'
 | |
|         )
 | |
|       end
 | |
|     end
 | |
| 
 | |
|     context 'when plain layout is not enabled' do
 | |
|       it 'returns the correct link' do
 | |
|         expect(helper.generate_article_link('portal_slug', 'article_slug', 'dark', false)).to eq(
 | |
|           '/hc/portal_slug/articles/article_slug'
 | |
|         )
 | |
|       end
 | |
|     end
 | |
|   end
 | |
| 
 | |
|   describe '#render_category_content' do
 | |
|     let(:markdown_content) { 'This is a *test* markdown content' }
 | |
|     let(:plain_text_content) { 'This is a test markdown content' }
 | |
|     let(:renderer) { instance_double(ChatwootMarkdownRenderer) }
 | |
| 
 | |
|     before do
 | |
|       allow(ChatwootMarkdownRenderer).to receive(:new).with(markdown_content).and_return(renderer)
 | |
|       allow(renderer).to receive(:render_markdown_to_plain_text).and_return(plain_text_content)
 | |
|     end
 | |
| 
 | |
|     it 'converts markdown to plain text' do
 | |
|       expect(helper.render_category_content(markdown_content)).to eq(plain_text_content)
 | |
|     end
 | |
|   end
 | |
| 
 | |
|   describe '#thumbnail_bg_color' do
 | |
|     it 'returns the correct color based on username length' do
 | |
|       expect(helper.thumbnail_bg_color('')).to be_in(['#6D95BA', '#A4C3C3', '#E19191'])
 | |
|       expect(helper.thumbnail_bg_color('Joe')).to eq('#6D95BA')
 | |
|       expect(helper.thumbnail_bg_color('John')).to eq('#A4C3C3')
 | |
|       expect(helper.thumbnail_bg_color('Jane james')).to eq('#A4C3C3')
 | |
|       expect(helper.thumbnail_bg_color('Jane_123')).to eq('#E19191')
 | |
|       expect(helper.thumbnail_bg_color('AlexanderTheGreat')).to eq('#E19191')
 | |
|       expect(helper.thumbnail_bg_color('Reginald John Sans')).to eq('#6D95BA')
 | |
|     end
 | |
|   end
 | |
| 
 | |
|   describe '#set_og_image_url' do
 | |
|     let(:portal_name) { 'Chatwoot Portal' }
 | |
|     let(:title) { 'Welcome to Chatwoot' }
 | |
| 
 | |
|     context 'when CDN URL is present' do
 | |
|       before do
 | |
|         InstallationConfig.create!(name: 'OG_IMAGE_CDN_URL', value: 'https://cdn.example.com')
 | |
|         InstallationConfig.create!(name: 'OG_IMAGE_CLIENT_REF', value: 'client-123')
 | |
|       end
 | |
| 
 | |
|       it 'returns the composed OG image URL with correct params' do
 | |
|         result = helper.set_og_image_url(portal_name, title)
 | |
|         uri = URI.parse(result)
 | |
|         expect(uri.path).to eq('/og')
 | |
|         params = Rack::Utils.parse_query(uri.query)
 | |
|         expect(params['clientRef']).to eq('client-123')
 | |
|         expect(params['title']).to eq(title)
 | |
|         expect(params['portalName']).to eq(portal_name)
 | |
|       end
 | |
|     end
 | |
| 
 | |
|     context 'when CDN URL is blank' do
 | |
|       before do
 | |
|         InstallationConfig.create!(name: 'OG_IMAGE_CDN_URL', value: '')
 | |
|         InstallationConfig.create!(name: 'OG_IMAGE_CLIENT_REF', value: 'client-123')
 | |
|       end
 | |
| 
 | |
|       it 'returns nil' do
 | |
|         expect(helper.set_og_image_url(portal_name, title)).to be_nil
 | |
|       end
 | |
|     end
 | |
|   end
 | |
| 
 | |
|   describe '#generate_portal_brand_url' do
 | |
|     it 'builds URL with UTM params and referer host as source (happy path)' do
 | |
|       result = helper.generate_portal_brand_url('https://brand.example.com', 'https://app.chatwoot.com/some/page')
 | |
|       uri = URI.parse(result)
 | |
|       params = Rack::Utils.parse_query(uri.query)
 | |
|       expect(uri.scheme).to eq('https')
 | |
|       expect(uri.host).to eq('brand.example.com')
 | |
|       expect(params['utm_medium']).to eq('helpcenter')
 | |
|       expect(params['utm_campaign']).to eq('branding')
 | |
|       expect(params['utm_source']).to eq('app.chatwoot.com')
 | |
|     end
 | |
| 
 | |
|     it 'returns utm string when brand_url is nil or empty' do
 | |
|       expect(helper.generate_portal_brand_url(nil,
 | |
|                                               'https://app.chatwoot.com')).to eq(
 | |
|                                                 '?utm_campaign=branding&utm_medium=helpcenter&utm_source=app.chatwoot.com'
 | |
|                                               )
 | |
|       expect(helper.generate_portal_brand_url('',
 | |
|                                               'https://app.chatwoot.com')).to eq(
 | |
|                                                 '?utm_campaign=branding&utm_medium=helpcenter&utm_source=app.chatwoot.com'
 | |
|                                               )
 | |
|     end
 | |
| 
 | |
|     it 'omits utm_source when referer is nil or invalid' do
 | |
|       r1 = helper.generate_portal_brand_url('https://brand.example.com', nil)
 | |
|       p1 = Rack::Utils.parse_query(URI.parse(r1).query)
 | |
|       expect(p1.key?('utm_source')).to be(false)
 | |
| 
 | |
|       r2 = helper.generate_portal_brand_url('https://brand.example.com', '::not-a-valid-url')
 | |
|       p2 = Rack::Utils.parse_query(URI.parse(r2).query)
 | |
|       expect(p2.key?('utm_source')).to be(false)
 | |
|       expect(p2['utm_medium']).to eq('helpcenter')
 | |
|       expect(p2['utm_campaign']).to eq('branding')
 | |
|     end
 | |
|   end
 | |
| end
 |