diff --git a/app/models/attachment.rb b/app/models/attachment.rb new file mode 100644 index 00000000..cfa87f2b --- /dev/null +++ b/app/models/attachment.rb @@ -0,0 +1,22 @@ +require 'attachable' + +class Attachment + include Mongoid::Document + include Mongoid::Timestamps + include Attachable + + field :title + field :filename + attaches :file + + validates_with SafeHtml + + def url + file.file_url + end + + # TODO: Move this to a domain object in specialist publisher + def snippet + "[InlineAttachment:#{filename}]" + end +end diff --git a/app/models/specialist_document_edition.rb b/app/models/specialist_document_edition.rb index b3656db6..b825ebd5 100644 --- a/app/models/specialist_document_edition.rb +++ b/app/models/specialist_document_edition.rb @@ -22,6 +22,8 @@ class SpecialistDocumentEdition field :state, type: String + embeds_many :attachments, cascade_callbacks: true + state_machine initial: :draft do event :publish do transition draft: :published @@ -75,4 +77,10 @@ def subsequent_siblings def latest_edition? subsequent_siblings.empty? end + + def build_attachment(attributes) + attachments.build(attributes.merge( + filename: attributes.fetch(:file).original_filename + )) + end end diff --git a/app/validators/safe_html.rb b/app/validators/safe_html.rb index af0b256a..22235d75 100644 --- a/app/validators/safe_html.rb +++ b/app/validators/safe_html.rb @@ -18,7 +18,7 @@ def check_struct(record, field_name, value) end def check_string(record, field_name, string) - if record.class::GOVSPEAK_FIELDS.include?(field_name) + if govspeak_fields(record).include?(field_name) unless Govspeak::Document.new(string).valid? error = "cannot include invalid Govspeak or JavaScript" record.errors.add(field_name, error) @@ -30,4 +30,13 @@ def check_string(record, field_name, string) end end end + +private + def govspeak_fields(record) + if record.class.const_defined?(:GOVSPEAK_FIELDS) + record.class.const_get(:GOVSPEAK_FIELDS) + else + [] + end + end end diff --git a/test/models/attachment_test.rb b/test/models/attachment_test.rb new file mode 100644 index 00000000..f92c4619 --- /dev/null +++ b/test/models/attachment_test.rb @@ -0,0 +1,43 @@ +require "test_helper" +require "ostruct" +require 'gds_api/test_helpers/asset_manager' + +class AttachmentTest < ActiveSupport::TestCase + include GdsApi::TestHelpers::AssetManager + + setup do + @original_asset_api_client = Attachable.asset_api_client + Attachable.asset_api_client = stub("asset_api_client") + end + + teardown do + Attachable.asset_api_client = @original_asset_api_client + end + + should "generate a snippet" do + attachment = Attachment.new( + title: "Supporting attachment", + filename: "document.pdf" + ) + expected_snippet = "[InlineAttachment:document.pdf]" + + assert_equal expected_snippet, attachment.snippet + end + + should "return the url via #url" do + attachment = Attachment.new( + title: "Photo of me", + filename: "photo.jpg", + file_id: "test-id" + ) + + asset_url = stub("asset url") + asset_response = stub("asset response", file_url: asset_url) + Attachable.asset_api_client + .stubs(:asset) + .with(attachment.file_id) + .returns(asset_response) + + assert_equal asset_url, attachment.url + end +end diff --git a/test/models/specialist_document_edition_test.rb b/test/models/specialist_document_edition_test.rb index 8ecc264f..8c4d932a 100644 --- a/test/models/specialist_document_edition_test.rb +++ b/test/models/specialist_document_edition_test.rb @@ -3,35 +3,81 @@ require "test_helper" class SpecialistDocumentEditionTest < ActiveSupport::TestCase - should "have correct fields" do - fields = { + def basic_edition_fields + { slug: 'cma-cases/merger-investigation-2014', title: "Merger Investigation 2014", summary: "This is the summary of stuff going on in the Merger Investigation 2014", - state: "published" + state: "published", + body: "A body", + opened_date: '2012-04-21', + document_id: 'a-document-id', + market_sector: 'oil-and-gas', + case_type: 'some-case-type', + case_state: 'open' } + end + + setup do + @original_asset_api_client = Attachable.asset_api_client + Attachable.asset_api_client = stub("asset_api_client") + end + + teardown do + Attachable.asset_api_client = @original_asset_api_client + end - edition = SpecialistDocumentEdition.new(fields) + should "have correct fields" do + edition = SpecialistDocumentEdition.new(basic_edition_fields) - assert_equal fields[:title], edition.title + assert_equal basic_edition_fields[:title], edition.title end should "be persistable" do - edition = SpecialistDocumentEdition.create!( - slug: 'cma-cases/merger-investigation-2014', - title: "Merger Investigation 2014", - summary: "This is the summary of stuff going on in the Merger Investigation 2014", - body: "A body", - opened_date: '2012-04-21', - market_sector: 'oil-and-gas', - case_type: 'some-case-type', - case_state: 'open', - state: "published", - document_id: 'a-document-id' - ) + edition = SpecialistDocumentEdition.create!(basic_edition_fields) found = SpecialistDocumentEdition.where(slug: edition.slug).first assert_equal found.attributes, edition.attributes end + + context "building attachments" do + should "build an attachment" do + edition = SpecialistDocumentEdition.new + file = OpenStruct.new(original_filename: "document.pdf") + + edition.build_attachment(title: "baz", file: file) + + attachment = edition.attachments.first + assert_equal "baz", attachment.title + assert_equal "document.pdf", attachment.filename + assert_equal file, attachment.instance_variable_get(:@file_file) + end + + should "persist attachment record when document saved" do + Attachable.asset_api_client.stubs(:create_asset) + + edition = SpecialistDocumentEdition.new(basic_edition_fields) + file = OpenStruct.new(original_filename: "document.pdf") + + edition.build_attachment(title: "baz", file: file) + edition.save! + + found = SpecialistDocumentEdition.where(slug: edition.slug).first + + assert_equal 1, found.attachments.count + assert_equal "baz", found.attachments.first.title + end + + should "transmit attached file to asset manager when document saved" do + edition = SpecialistDocumentEdition.new(basic_edition_fields) + file = OpenStruct.new(original_filename: "document.pdf") + + success_response = stub("asset manager response", id: "/test-id") + Attachable.asset_api_client.expects(:create_asset).with(file: file).returns(success_response) + + edition.build_attachment(title: "baz", file: file) + edition.save! + end + end end diff --git a/test/validators/safe_html_validator_test.rb b/test/validators/safe_html_validator_test.rb index 9bbd80c4..4298abbc 100644 --- a/test/validators/safe_html_validator_test.rb +++ b/test/validators/safe_html_validator_test.rb @@ -73,14 +73,16 @@ class DummyEmbeddedSingle should "all models should use this validator" do models_dir = File.expand_path("../../app/models/*", File.dirname(__FILE__)) - classes = Dir[models_dir].map do |file| - klass = File.basename(file, ".rb").camelize.constantize - klass.included_modules.include?(Mongoid::Document) ? klass : nil - end.compact - - classes.each do |klass| - assert_includes klass.validators.map(&:class), SafeHtml, "#{klass} must be validated with SafeHtml" - end + classes = Dir[models_dir] + .map { |file| + File.basename(file, ".rb").camelize.constantize + } + .select { |klass| + klass.included_modules.include?(Mongoid::Document) + } + .each { |klass| + assert_includes klass.validators.map(&:class), SafeHtml, "#{klass} must be validated with SafeHtml" + } end end end