diff --git a/app/controllers/repositories_controller.rb b/app/controllers/repositories_controller.rb index 53b84ccd0..d1d30322b 100644 --- a/app/controllers/repositories_controller.rb +++ b/app/controllers/repositories_controller.rb @@ -261,7 +261,7 @@ class RepositoriesController < ApplicationController def export_repository if params[:row_ids] && params[:header_ids] - generate_zip + RepositoryZipExport.generate_zip(params, @repository, current_user) else flash[:alert] = t('zip_export.export_error') end @@ -333,66 +333,4 @@ class RepositoriesController < ApplicationController end end end - - def generate_zip - # Fetch rows in the same order as in the currently viewed datatable - ordered_row_ids = params[:row_ids] - id_row_map = RepositoryRow.where(id: ordered_row_ids, - repository: @repository) - .index_by(&:id) - ordered_rows = ordered_row_ids.collect { |id| id_row_map[id.to_i] } - - zip = ZipExport.create(user: current_user) - zip.generate_exportable_zip( - current_user, - to_csv(ordered_rows, params[:header_ids]), - :repositories - ) - end - - def to_csv(rows, column_ids) - require 'csv' - - # Parse column names - csv_header = [] - column_ids.each do |c_id| - csv_header << case c_id.to_i - when -1, -2 - next - when -3 - I18n.t('repositories.table.row_name') - when -4 - I18n.t('repositories.table.added_by') - when -5 - I18n.t('repositories.table.added_on') - else - column = RepositoryColumn.find_by_id(c_id) - column ? column.name : nil - end - end - - CSV.generate do |csv| - csv << csv_header - rows.each do |row| - csv_row = [] - column_ids.each do |c_id| - csv_row << case c_id.to_i - when -1, -2 - next - when -3 - row.name - when -4 - row.created_by.full_name - when -5 - I18n.l(row.created_at, format: :full) - else - cell = row.repository_cells - .find_by(repository_column_id: c_id) - cell ? cell.value.formatted : nil - end - end - csv << csv_row - end - end - end end diff --git a/app/models/repository_list_value.rb b/app/models/repository_list_value.rb index ae92b068b..c53856809 100644 --- a/app/models/repository_list_value.rb +++ b/app/models/repository_list_value.rb @@ -13,7 +13,11 @@ class RepositoryListValue < ApplicationRecord validates :repository_cell, presence: true def formatted - return '' unless repository_list_item + data.to_s + end + + def data + return nil unless repository_list_item repository_list_item.data end end diff --git a/app/services/repository_zip_export.rb b/app/services/repository_zip_export.rb new file mode 100644 index 000000000..e192540fc --- /dev/null +++ b/app/services/repository_zip_export.rb @@ -0,0 +1,62 @@ +require 'csv' +module RepositoryZipExport + def self.generate_zip(params, repository, current_user) + # Fetch rows in the same order as in the currently viewed datatable + ordered_row_ids = params[:row_ids] + id_row_map = RepositoryRow.where(id: ordered_row_ids, + repository: repository) + .index_by(&:id) + ordered_rows = ordered_row_ids.collect { |id| id_row_map[id.to_i] } + + zip = ZipExport.create(user: current_user) + zip.generate_exportable_zip( + current_user, + to_csv(ordered_rows, params[:header_ids]), + :repositories + ) + end + + def self.to_csv(rows, column_ids) + # Parse column names + csv_header = [] + column_ids.each do |c_id| + csv_header << case c_id.to_i + when -1, -2 + next + when -3 + I18n.t('repositories.table.row_name') + when -4 + I18n.t('repositories.table.added_by') + when -5 + I18n.t('repositories.table.added_on') + else + column = RepositoryColumn.find_by_id(c_id) + column ? column.name : nil + end + end + + CSV.generate do |csv| + csv << csv_header + rows.each do |row| + csv_row = [] + column_ids.each do |c_id| + csv_row << case c_id.to_i + when -1, -2 + next + when -3 + row.name + when -4 + row.created_by.full_name + when -5 + I18n.l(row.created_at, format: :full) + else + cell = row.repository_cells + .find_by(repository_column_id: c_id) + cell ? cell.value.formatted : nil + end + end + csv << csv_row + end + end + end +end diff --git a/spec/factories/repository_text_value.rb b/spec/factories/repository_text_value.rb new file mode 100644 index 000000000..53aed680c --- /dev/null +++ b/spec/factories/repository_text_value.rb @@ -0,0 +1,6 @@ +FactoryBot.define do + factory :repository_text_value do + created_by { User.first || association(:project_user) } + last_modified_by { User.first || association(:project_user) } + end +end diff --git a/spec/lib/tasks/samples_to_repository_migration_spec.rb b/spec/lib/tasks/samples_to_repository_migration_spec.rb index dd751779d..0845739b8 100644 --- a/spec/lib/tasks/samples_to_repository_migration_spec.rb +++ b/spec/lib/tasks/samples_to_repository_migration_spec.rb @@ -6,7 +6,6 @@ describe 'samples_to_repository_migration:run' do let!(:team) { create :team, created_by: user } let!(:user_team) { create :user_team, user: user, team: team } let!(:my_module) { create :my_module } - let!(:samples_table) { create :samples_table, user: user, team: team } let(:sample_types_names) { %w(type_one type_two type_three) } let(:sample_group_names) { %w(group_one group_two group_three) } diff --git a/spec/models/repository_list_value_spec.rb b/spec/models/repository_list_value_spec.rb index dcae9396c..2e37af411 100644 --- a/spec/models/repository_list_value_spec.rb +++ b/spec/models/repository_list_value_spec.rb @@ -18,7 +18,7 @@ RSpec.describe RepositoryListValue, type: :model do it { should accept_nested_attributes_for(:repository_cell) } end - describe '#data' do + describe '#formatted' do let!(:repository) { create :repository } let!(:repository_column) { create :repository_column, name: 'My column' } let!(:repository_column) do @@ -32,7 +32,7 @@ RSpec.describe RepositoryListValue, type: :model do } end - it 'returns the data of a selected item' do + it 'returns the formatted data of a selected item' do list_item = create :repository_list_item, data: 'my item', repository: repository, @@ -71,4 +71,58 @@ RSpec.describe RepositoryListValue, type: :model do expect(repository_list_value.reload.formatted).to eq '' end end + + describe '#data' do + let!(:repository) { create :repository } + let!(:repository_column) { create :repository_column, name: 'My column' } + let!(:repository_column) do + create :repository_column, data_type: :RepositoryListValue + end + let!(:repository_row) { create :repository_row, name: 'My row' } + let!(:repository_list_value) do + create :repository_list_value, repository_cell_attributes: { + repository_column: repository_column, + repository_row: repository_row + } + end + + it 'returns the data of a selected item' do + list_item = create :repository_list_item, + data: 'my item', + repository: repository, + repository_column: repository_column + repository_list_value.repository_list_item = list_item + repository_list_value.save + expect(repository_list_value.reload.data).to eq 'my item' + end + + it 'retuns only the the item related to the list' do + repository_row_two = create :repository_row, name: 'New row' + repository_list_value_two = + create :repository_list_value, repository_cell_attributes: { + repository_column: repository_column, + repository_row: repository_row_two + } + list_item = create :repository_list_item, + data: 'new item', + repository: repository, + repository_column: repository_column + repository_list_value.repository_list_item = list_item + expect(repository_list_value.reload.data).to_not eq 'my item' + expect(repository_list_value.data).to be_nil + end + + it 'returns an empty string if no item selected' do + list_item = create :repository_list_item, + data: 'my item', + repository: repository, + repository_column: repository_column + expect(repository_list_value.reload.data).to eq nil + end + + it 'returns an empty string if item does not exists' do + repository_list_value.repository_list_item = nil + expect(repository_list_value.reload.data).to eq nil + end + end end diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index 9285d22ac..518501f4c 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -58,6 +58,14 @@ RSpec.configure do |config| config.after(:each) do DatabaseCleaner.clean end + + config.around(:each, type: :background_job) do |example| + run_background_jobs_immediately do + example.run + end + end + + config.include BackgroundJobs # RSpec Rails can automatically mix in different behaviours to your tests # based on their file location, for example enabling you to call `get` and # `post` in specs under `spec/controllers`. diff --git a/spec/services/repository_zip_export_spec.rb b/spec/services/repository_zip_export_spec.rb new file mode 100644 index 000000000..145e6b2a5 --- /dev/null +++ b/spec/services/repository_zip_export_spec.rb @@ -0,0 +1,82 @@ +require 'rails_helper' +require 'zip' + +describe RepositoryZipExport, type: :background_job do + let(:user) { create :user } + let(:team) { create :team, created_by: user } + let(:user_team) { create :user_team, user: user, team: team } + let(:repository) { create :repository, team: team, created_by: user } + let!(:sample_group_column) do + create :repository_column, repository: repository, + created_by: user, + name: 'Sample group', + data_type: 'RepositoryListValue' + end + let!(:repository_list_item) do + create :repository_list_item, data: 'item one', + repository: repository, + repository_column: sample_group_column + end + let!(:custom_column) do + create :repository_column, repository: repository, + created_by: user, + name: 'Custom items', + data_type: 'RepositoryTextValue' + end + + before do + @row_ids = [] + 10.times do |index| + row = create :repository_row, name: "row #{index}", + repository: repository, + created_by: user, + last_modified_by: user + create :repository_list_value, repository_list_item: repository_list_item, + repository_cell_attributes: { + repository_row: row, + repository_column: sample_group_column + } + create :repository_text_value, data: 'custum column value', + repository_cell_attributes: { + repository_row: row, + repository_column: custom_column + } + + @row_ids << row.id.to_s + end + end + + describe '#generate_zip/2' do + let(:params) do + { header_ids: ['-1', + '-2', + sample_group_column.id.to_s, + custom_column.id.to_s, + '-3', + '-5', + '-4'], + row_ids: @row_ids } + end + + it 'generates a new zip export object' do + RepositoryZipExport.generate_zip(params, repository, user) + expect(ZipExport.count).to eq 1 + end + + it 'generates a zip with csv file with exported rows' do + RepositoryZipExport.generate_zip(params, repository, user) + zip = ZipExport.first.zip_file_file_name + .gsub('export-', '') + .gsub('.zip', '') + csv_path = Rails.root.join('tmp', "temp-zip-#{zip}", 'export.csv').to_s + index = 0 + CSV.foreach(csv_path, headers: true) do |row| + row_hash = row.to_h + expect(row_hash.fetch('Sample group')).to eq 'item one' + expect(row_hash.fetch('Custom items')).to eq 'custum column value' + expect(row_hash.fetch('Name')).to eq "row #{index}" + index += 1 + end + end + end +end diff --git a/spec/support/background_job.rb b/spec/support/background_job.rb new file mode 100644 index 000000000..7cd13c2f7 --- /dev/null +++ b/spec/support/background_job.rb @@ -0,0 +1,8 @@ +module BackgroundJobs + def run_background_jobs_immediately + delay_jobs = Delayed::Worker.delay_jobs + Delayed::Worker.delay_jobs = false + yield + Delayed::Worker.delay_jobs = delay_jobs + end +end