# frozen_string_literal: true require 'spec_helper' if defined?(Rails) RSpec.describe UsersController, type: :controller do # rubocop:disable Metrics/BlockLength describe 'rails setup' do it 'should capture the CSV renderer provided by Rails' do mock_users = [mock_model(User), mock_model(User)] allow(User).to receive(:all).and_return(mock_users) expect(mock_users).to receive(:to_comma).once get :index, format: :csv end end describe 'controller' do # rubocop:disable Metrics/BlockLength before(:all) do @user_1 = User.create!(first_name: 'Fred', last_name: 'Flintstone') @user_2 = User.create!(first_name: 'Wilma', last_name: 'Flintstone') end it 'should not affect html requested' do get :index expect(response.status).to eq 200 expect(response.media_type).to eq 'text/html' expect(response.body).to eq 'Users!' end it 'should return a csv when requested' do get :index, format: :csv expect(response.status).to eq 200 expect(response.media_type).to eq 'text/csv' expect(response.header['Content-Disposition']).to include('filename="data.csv"') expected_content = <<-CSV.gsub(/^\s+/, '') First name,Last name,Name Fred,Flintstone,Fred Flintstone Wilma,Flintstone,Wilma Flintstone CSV expect(response.body).to eq expected_content end describe 'with comma options' do it 'should allow the style to be chosen from the renderer' do # Must be passed in same format (string/symbol) eg: # format.csv { render User.all, :style => :shortened } get :with_custom_style, format: :csv expected_content = <<-CSV.gsub(/^\s+/, '') First name,Last name Fred,Flintstone Wilma,Flintstone CSV expect(response.body).to eq expected_content end end describe 'with custom options' do # rubocop:disable Metrics/BlockLength def is_rails_4? Rails::VERSION::STRING =~ /^4.*/ end def get_(name, **args) if is_rails_4? && args[:params] args.merge!(args[:params]) args.delete(:params) end get name, **args end it 'should allow a filename to be set' do get_ :with_custom_options, format: :csv, params: { custom_options: { filename: 'my_custom_name' } } expect(response.status).to eq 200 expect(response.media_type).to eq 'text/csv' expect(response.header['Content-Disposition']).to include('filename="my_custom_name.csv"') end it 'should allow a custom filename with spaces' do require 'shellwords' params = { custom_options: { filename: 'filename with a lot of spaces' } } get_ :with_custom_options, format: :csv, params: params expect(response.status).to eq 200 expect(response.media_type).to eq 'text/csv' expect(response.header['Content-Disposition']).to include('filename="filename with a lot of spaces.csv"') filename_string = response.header['Content-Disposition'].split('=').last # shellsplit honors quoted strings expect(filename_string.shellsplit.length).to eq 1 end it 'should allow a file extension to be set' do get_ :with_custom_options, format: :csv, params: { custom_options: { extension: :txt } } expect(response.status).to eq 200 expect(response.media_type).to eq 'text/csv' expect(response.header['Content-Disposition']).to include('filename="data.txt"') end it 'should allow mime type to be set' do get_ :with_custom_options, format: :csv, params: { custom_options: { mime_type: 'text/plain' } } expect(response.status).to eq 200 expect(response.media_type).to eq 'text/plain' end it 'should allow bom to be set' do get_ :with_custom_options, format: :csv, params: { custom_options: { with_bom: true } } expected_content = <<-CSV.gsub(/^\s+/, '') \xEF\xBB\xBFFirst name,Last name,Name Fred,Flintstone,Fred Flintstone Wilma,Flintstone,Wilma Flintstone CSV expect(response.body). to eq expected_content end describe 'headers' do it 'should allow toggling on' do get_ :with_custom_options, format: :csv, params: { custom_options: { write_headers: 'true' } } expect(response.status).to eq 200 expect(response.media_type).to eq 'text/csv' expected_content = <<-CSV.gsub(/^\s+/, '') First name,Last name,Name Fred,Flintstone,Fred Flintstone Wilma,Flintstone,Wilma Flintstone CSV expect(response.body).to eq expected_content end it 'should allow toggling off' do get_ :with_custom_options, format: :csv, params: { custom_options: { write_headers: false } } expect(response.status).to eq 200 expect(response.media_type).to eq 'text/csv' expected_content = <<-CSV.gsub(/^\s+/, '') Fred,Flintstone,Fred Flintstone Wilma,Flintstone,Wilma Flintstone CSV expect(response.body).to eq expected_content end end it 'should allow forcing of quotes' do get_ :with_custom_options, format: :csv, params: { custom_options: { force_quotes: true } } expect(response.status).to eq 200 expect(response.media_type).to eq 'text/csv' expected_content = <<-CSV.gsub(/^\s+/, '') "First name","Last name","Name" "Fred","Flintstone","Fred Flintstone" "Wilma","Flintstone","Wilma Flintstone" CSV expect(response.body).to eq expected_content end it 'should allow combinations of options' do params = { custom_options: { write_headers: false, force_quotes: true, col_sep: '||', row_sep: "ENDOFLINE\n" } } get_ :with_custom_options, format: :csv, params: params expect(response.status).to eq 200 expect(response.media_type).to eq 'text/csv' expected_content = <<-CSV.gsub(/^\s+/, '') "Fred"||"Flintstone"||"Fred Flintstone"ENDOFLINE "Wilma"||"Flintstone"||"Wilma Flintstone"ENDOFLINE CSV expect(response.body).to eq expected_content end end end end end