alchemy_cms 5.2.0 → 6.0.0.b3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +6 -14
- data/.gitignore +0 -1
- data/.hound.yml +1 -1
- data/.rubocop.yml +46 -4
- data/CHANGELOG.md +114 -5
- data/Gemfile +8 -1
- data/README.md +5 -2
- data/alchemy_cms.gemspec +78 -65
- data/app/assets/javascripts/alchemy/admin.js +0 -2
- data/app/assets/javascripts/alchemy/alchemy.base.js.coffee +0 -27
- data/app/assets/javascripts/alchemy/alchemy.confirm_dialog.js.coffee +2 -1
- data/app/assets/javascripts/alchemy/alchemy.dialog.js.coffee +1 -1
- data/app/assets/javascripts/alchemy/alchemy.dragndrop.js.coffee +0 -25
- data/app/assets/javascripts/alchemy/alchemy.element_editors.js.coffee +1 -1
- data/app/assets/javascripts/alchemy/alchemy.elements_window.js.coffee +2 -0
- data/app/assets/javascripts/alchemy/alchemy.fixed_elements.js +1 -1
- data/app/assets/javascripts/alchemy/alchemy.gui.js.coffee +3 -1
- data/app/assets/javascripts/alchemy/alchemy.image_overlay.coffee +1 -1
- data/app/assets/javascripts/alchemy/alchemy.link_dialog.js.coffee +40 -27
- data/app/assets/javascripts/alchemy/templates/node_folder.hbs +1 -1
- data/app/assets/stylesheets/alchemy/_extends.scss +15 -2
- data/app/assets/stylesheets/alchemy/admin.scss +1 -1
- data/app/assets/stylesheets/alchemy/archive.scss +20 -5
- data/app/assets/stylesheets/alchemy/buttons.scss +0 -4
- data/app/assets/stylesheets/alchemy/elements.scss +73 -61
- data/app/assets/stylesheets/alchemy/images.scss +8 -0
- data/app/assets/stylesheets/alchemy/node-select.scss +4 -3
- data/app/assets/stylesheets/alchemy/page-select.scss +1 -0
- data/app/controllers/alchemy/admin/attachments_controller.rb +8 -4
- data/app/controllers/alchemy/admin/base_controller.rb +5 -7
- data/app/controllers/alchemy/admin/elements_controller.rb +59 -34
- data/app/controllers/alchemy/admin/essence_audios_controller.rb +30 -0
- data/app/controllers/alchemy/admin/essence_files_controller.rb +0 -14
- data/app/controllers/alchemy/admin/essence_pictures_controller.rb +8 -79
- data/app/controllers/alchemy/admin/essence_videos_controller.rb +33 -0
- data/app/controllers/alchemy/admin/ingredients_controller.rb +30 -0
- data/app/controllers/alchemy/admin/layoutpages_controller.rb +0 -1
- data/app/controllers/alchemy/admin/pages_controller.rb +7 -22
- data/app/controllers/alchemy/admin/pictures_controller.rb +56 -17
- data/app/controllers/alchemy/admin/resources_controller.rb +84 -10
- data/app/controllers/alchemy/api/elements_controller.rb +13 -4
- data/app/controllers/alchemy/api/pages_controller.rb +4 -3
- data/app/controllers/concerns/alchemy/admin/archive_overlay.rb +13 -3
- data/app/controllers/concerns/alchemy/admin/crop_action.rb +26 -0
- data/app/decorators/alchemy/element_editor.rb +26 -1
- data/app/decorators/alchemy/ingredient_editor.rb +158 -0
- data/app/helpers/alchemy/admin/elements_helper.rb +1 -0
- data/app/helpers/alchemy/admin/essences_helper.rb +1 -1
- data/app/helpers/alchemy/admin/ingredients_helper.rb +42 -0
- data/app/helpers/alchemy/elements_block_helper.rb +23 -6
- data/app/helpers/alchemy/elements_helper.rb +12 -5
- data/app/helpers/alchemy/pages_helper.rb +3 -11
- data/app/jobs/alchemy/base_job.rb +11 -0
- data/app/jobs/alchemy/publish_page_job.rb +11 -0
- data/app/models/alchemy/attachment.rb +24 -7
- data/app/models/alchemy/content.rb +1 -6
- data/app/models/alchemy/content/factory.rb +23 -27
- data/app/models/alchemy/element.rb +39 -72
- data/app/models/alchemy/element/definitions.rb +29 -27
- data/app/models/alchemy/element/element_contents.rb +131 -122
- data/app/models/alchemy/element/element_essences.rb +111 -98
- data/app/models/alchemy/element/element_ingredients.rb +184 -0
- data/app/models/alchemy/element/presenters.rb +104 -85
- data/app/models/alchemy/elements_repository.rb +126 -0
- data/app/models/alchemy/essence_audio.rb +12 -0
- data/app/models/alchemy/essence_headline.rb +40 -0
- data/app/models/alchemy/essence_picture.rb +4 -116
- data/app/models/alchemy/essence_richtext.rb +12 -0
- data/app/models/alchemy/essence_video.rb +12 -0
- data/app/models/alchemy/image_cropper_settings.rb +87 -0
- data/app/models/alchemy/ingredient.rb +183 -0
- data/app/models/alchemy/ingredient_validator.rb +97 -0
- data/app/models/alchemy/ingredients/audio.rb +29 -0
- data/app/models/alchemy/ingredients/boolean.rb +21 -0
- data/app/models/alchemy/ingredients/datetime.rb +20 -0
- data/app/models/alchemy/ingredients/file.rb +30 -0
- data/app/models/alchemy/ingredients/headline.rb +42 -0
- data/app/models/alchemy/ingredients/html.rb +19 -0
- data/app/models/alchemy/ingredients/link.rb +16 -0
- data/app/models/alchemy/ingredients/node.rb +23 -0
- data/app/models/alchemy/ingredients/page.rb +23 -0
- data/app/models/alchemy/ingredients/picture.rb +41 -0
- data/app/models/alchemy/ingredients/richtext.rb +57 -0
- data/app/models/alchemy/ingredients/select.rb +10 -0
- data/app/models/alchemy/ingredients/text.rb +17 -0
- data/app/models/alchemy/ingredients/video.rb +33 -0
- data/app/models/alchemy/language.rb +0 -11
- data/app/models/alchemy/page.rb +76 -33
- data/app/models/alchemy/page/fixed_attributes.rb +53 -51
- data/app/models/alchemy/page/page_elements.rb +186 -205
- data/app/models/alchemy/page/page_naming.rb +66 -64
- data/app/models/alchemy/page/page_natures.rb +139 -142
- data/app/models/alchemy/page/page_scopes.rb +117 -102
- data/app/models/alchemy/page/publisher.rb +50 -0
- data/app/models/alchemy/page/url_path.rb +1 -1
- data/app/models/alchemy/page_version.rb +58 -0
- data/app/models/alchemy/picture.rb +18 -40
- data/app/models/alchemy/picture/calculations.rb +2 -8
- data/app/models/alchemy/picture/preprocessor.rb +2 -0
- data/app/models/alchemy/picture/transformations.rb +24 -96
- data/app/models/concerns/alchemy/picture_thumbnails.rb +181 -0
- data/app/models/concerns/alchemy/touch_elements.rb +2 -2
- data/app/presenters/alchemy/picture_view.rb +88 -0
- data/app/serializers/alchemy/element_serializer.rb +5 -0
- data/app/serializers/alchemy/page_tree_serializer.rb +3 -2
- data/app/services/alchemy/delete_elements.rb +44 -0
- data/app/services/alchemy/duplicate_element.rb +56 -0
- data/app/views/alchemy/admin/attachments/_archive_overlay.html.erb +2 -3
- data/app/views/alchemy/admin/attachments/_file_to_assign.html.erb +3 -3
- data/app/views/alchemy/admin/attachments/assign.js.erb +11 -0
- data/app/views/alchemy/admin/attachments/index.html.erb +2 -3
- data/app/views/alchemy/admin/crop.html.erb +36 -0
- data/app/views/alchemy/admin/elements/_element.html.erb +14 -10
- data/app/views/alchemy/admin/elements/{_element_footer.html.erb → _footer.html.erb} +0 -0
- data/app/views/alchemy/admin/elements/{_new_element_form.html.erb → _form.html.erb} +1 -1
- data/app/views/alchemy/admin/elements/{_element_header.html.erb → _header.html.erb} +1 -1
- data/app/views/alchemy/admin/elements/{_element_toolbar.html.erb → _toolbar.html.erb} +5 -6
- data/app/views/alchemy/admin/elements/create.js.erb +1 -1
- data/app/views/alchemy/admin/elements/{trash.js.erb → destroy.js.erb} +2 -6
- data/app/views/alchemy/admin/elements/fold.js.erb +2 -2
- data/app/views/alchemy/admin/elements/new.html.erb +3 -3
- data/app/views/alchemy/admin/elements/order.js.erb +0 -17
- data/app/views/alchemy/admin/elements/update.js.erb +3 -2
- data/app/views/alchemy/admin/essence_audios/edit.html.erb +7 -0
- data/app/views/alchemy/admin/essence_pictures/update.js.erb +0 -1
- data/app/views/alchemy/admin/essence_videos/edit.html.erb +11 -0
- data/app/views/alchemy/admin/ingredients/_audio_fields.html.erb +4 -0
- data/app/views/alchemy/admin/ingredients/_file_fields.html.erb +18 -0
- data/app/views/alchemy/admin/ingredients/_picture_fields.html.erb +25 -0
- data/app/views/alchemy/admin/ingredients/_video_fields.html.erb +8 -0
- data/app/views/alchemy/admin/ingredients/edit.html.erb +4 -0
- data/app/views/alchemy/admin/layoutpages/edit.html.erb +0 -5
- data/app/views/alchemy/admin/nodes/_node.html.erb +2 -2
- data/app/views/alchemy/admin/pages/_anchor_link.html.erb +1 -1
- data/app/views/alchemy/admin/pages/_external_link.html.erb +1 -1
- data/app/views/alchemy/admin/pages/_file_link.html.erb +1 -1
- data/app/views/alchemy/admin/pages/_form.html.erb +0 -6
- data/app/views/alchemy/admin/pages/_internal_link.html.erb +1 -1
- data/app/views/alchemy/admin/pages/_tinymce_custom_config.html.erb +5 -2
- data/app/views/alchemy/admin/pages/_toolbar.html.erb +1 -1
- data/app/views/alchemy/admin/pages/edit.html.erb +36 -24
- data/app/views/alchemy/admin/pages/index.html.erb +2 -9
- data/app/views/alchemy/admin/partials/_remote_search_form.html.erb +2 -4
- data/app/views/alchemy/admin/partials/_routes.html.erb +7 -11
- data/app/views/alchemy/admin/partials/_search_form.html.erb +9 -0
- data/app/views/alchemy/admin/pictures/_archive.html.erb +1 -1
- data/app/views/alchemy/admin/pictures/_archive_overlay.html.erb +1 -1
- data/app/views/alchemy/admin/pictures/_filter_and_size_bar.html.erb +5 -7
- data/app/views/alchemy/admin/pictures/_infos.html.erb +0 -1
- data/app/views/alchemy/admin/pictures/_picture_to_assign.html.erb +4 -4
- data/app/views/alchemy/admin/pictures/assign.js.erb +10 -0
- data/app/views/alchemy/admin/pictures/index.html.erb +8 -3
- data/app/views/alchemy/admin/resources/_filter.html.erb +12 -0
- data/app/views/alchemy/admin/resources/_filter_bar.html.erb +14 -17
- data/app/views/alchemy/admin/resources/_form.html.erb +3 -0
- data/app/views/alchemy/admin/resources/_table_header.html.erb +15 -0
- data/app/views/alchemy/admin/resources/index.html.erb +3 -11
- data/app/views/alchemy/essences/_essence_audio_editor.html.erb +4 -0
- data/app/views/alchemy/essences/_essence_audio_view.html.erb +15 -0
- data/app/views/alchemy/essences/_essence_file_editor.html.erb +15 -6
- data/app/views/alchemy/essences/_essence_headline_editor.html.erb +36 -0
- data/app/views/alchemy/essences/_essence_headline_view.html.erb +10 -0
- data/app/views/alchemy/essences/_essence_link_editor.html.erb +8 -4
- data/app/views/alchemy/essences/_essence_picture_editor.html.erb +27 -12
- data/app/views/alchemy/essences/_essence_picture_view.html.erb +3 -3
- data/app/views/alchemy/essences/_essence_text_editor.html.erb +12 -4
- data/app/views/alchemy/essences/_essence_video_editor.html.erb +4 -0
- data/app/views/alchemy/essences/_essence_video_view.html.erb +18 -0
- data/app/views/alchemy/essences/shared/_essence_picture_tools.html.erb +21 -16
- data/app/views/alchemy/essences/shared/_linkable_essence_tools.html.erb +2 -2
- data/app/views/alchemy/ingredients/_audio_editor.html.erb +5 -0
- data/app/views/alchemy/ingredients/_audio_view.html.erb +14 -0
- data/app/views/alchemy/ingredients/_boolean_editor.html.erb +11 -0
- data/app/views/alchemy/ingredients/_boolean_view.html.erb +1 -0
- data/app/views/alchemy/ingredients/_datetime_editor.html.erb +17 -0
- data/app/views/alchemy/ingredients/_datetime_view.html.erb +9 -0
- data/app/views/alchemy/ingredients/_file_editor.html.erb +52 -0
- data/app/views/alchemy/ingredients/_file_view.html.erb +17 -0
- data/app/views/alchemy/ingredients/_headline_editor.html.erb +30 -0
- data/app/views/alchemy/ingredients/_headline_view.html.erb +9 -0
- data/app/views/alchemy/ingredients/_html_editor.html.erb +8 -0
- data/app/views/alchemy/ingredients/_html_view.html.erb +1 -0
- data/app/views/alchemy/ingredients/_link_editor.html.erb +24 -0
- data/app/views/alchemy/ingredients/_link_view.html.erb +9 -0
- data/app/views/alchemy/ingredients/_node_editor.html.erb +26 -0
- data/app/views/alchemy/ingredients/_node_view.html.erb +1 -0
- data/app/views/alchemy/ingredients/_page_editor.html.erb +25 -0
- data/app/views/alchemy/ingredients/_page_view.html.erb +4 -0
- data/app/views/alchemy/ingredients/_picture_editor.html.erb +60 -0
- data/app/views/alchemy/ingredients/_picture_view.html.erb +5 -0
- data/app/views/alchemy/ingredients/_richtext_editor.html.erb +12 -0
- data/app/views/alchemy/ingredients/_richtext_view.html.erb +3 -0
- data/app/views/alchemy/ingredients/_select_editor.html.erb +30 -0
- data/app/views/alchemy/ingredients/_select_view.html.erb +1 -0
- data/app/views/alchemy/ingredients/_text_editor.html.erb +20 -0
- data/app/views/alchemy/ingredients/_text_view.html.erb +16 -0
- data/app/views/alchemy/ingredients/_video_editor.html.erb +5 -0
- data/app/views/alchemy/ingredients/_video_view.html.erb +17 -0
- data/app/views/alchemy/ingredients/shared/_link_tools.html.erb +20 -0
- data/app/views/alchemy/ingredients/shared/_picture_tools.html.erb +57 -0
- data/config/brakeman.ignore +66 -159
- data/config/initializers/dragonfly.rb +10 -0
- data/config/locales/alchemy.en.yml +108 -64
- data/config/routes.rb +17 -22
- data/db/migrate/20201207131309_create_page_versions.rb +19 -0
- data/db/migrate/20201207135820_add_page_version_id_to_alchemy_elements.rb +76 -0
- data/db/migrate/20210205143548_rename_public_on_and_public_until_on_alchemy_pages.rb +10 -0
- data/db/migrate/20210326105046_add_sanitized_body_to_alchemy_essence_richtexts.rb +7 -0
- data/db/migrate/20210406093436_add_alchemy_essence_headlines.rb +12 -0
- data/db/migrate/20210506135919_create_essence_audios.rb +19 -0
- data/db/migrate/20210506140258_create_essence_videos.rb +23 -0
- data/db/migrate/20210508091432_create_alchemy_ingredients.rb +22 -0
- data/lib/alchemy/admin/preview_url.rb +2 -0
- data/lib/alchemy/deprecation.rb +1 -1
- data/lib/alchemy/dragonfly/processors/auto_orient.rb +18 -0
- data/lib/alchemy/dragonfly/processors/crop_resize.rb +35 -0
- data/lib/alchemy/elements_finder.rb +14 -60
- data/lib/alchemy/essence.rb +1 -2
- data/lib/alchemy/forms/builder.rb +21 -1
- data/lib/alchemy/hints.rb +8 -4
- data/lib/alchemy/page_layout.rb +0 -13
- data/lib/alchemy/permissions.rb +30 -29
- data/lib/alchemy/resource.rb +13 -3
- data/lib/alchemy/resource_filter.rb +40 -0
- data/lib/alchemy/resources_helper.rb +1 -16
- data/lib/alchemy/tasks/tidy.rb +29 -0
- data/lib/alchemy/test_support.rb +2 -11
- data/lib/alchemy/test_support/essence_shared_examples.rb +0 -1
- data/lib/alchemy/test_support/factories/element_factory.rb +8 -8
- data/lib/alchemy/test_support/factories/essence_audio_factory.rb +7 -0
- data/lib/alchemy/test_support/factories/essence_video_factory.rb +7 -0
- data/lib/alchemy/test_support/factories/ingredient_factory.rb +25 -0
- data/lib/alchemy/test_support/factories/page_factory.rb +20 -1
- data/lib/alchemy/test_support/factories/page_version_factory.rb +23 -0
- data/lib/alchemy/test_support/having_crop_action_examples.rb +170 -0
- data/lib/alchemy/test_support/having_picture_thumbnails_examples.rb +646 -0
- data/lib/alchemy/test_support/shared_ingredient_editor_examples.rb +21 -0
- data/lib/alchemy/test_support/shared_ingredient_examples.rb +75 -0
- data/lib/alchemy/tinymce.rb +17 -0
- data/lib/alchemy/upgrader/six_point_zero.rb +21 -0
- data/lib/alchemy/upgrader/tasks/add_page_versions.rb +33 -0
- data/lib/alchemy/upgrader/tasks/ingredients_migrator.rb +62 -0
- data/lib/alchemy/version.rb +1 -1
- data/lib/alchemy_cms.rb +1 -0
- data/lib/generators/alchemy/elements/elements_generator.rb +1 -0
- data/lib/generators/alchemy/elements/templates/view.html.erb +9 -0
- data/lib/generators/alchemy/elements/templates/view.html.haml +9 -0
- data/lib/generators/alchemy/elements/templates/view.html.slim +9 -0
- data/lib/generators/alchemy/ingredient/ingredient_generator.rb +38 -0
- data/lib/generators/alchemy/ingredient/templates/editor.html.erb +14 -0
- data/lib/generators/alchemy/ingredient/templates/model.rb.tt +13 -0
- data/lib/generators/alchemy/ingredient/templates/view.html.erb +1 -0
- data/lib/generators/alchemy/install/templates/dragonfly.rb.tt +1 -1
- data/lib/generators/alchemy/menus/templates/node.html.erb +1 -1
- data/lib/generators/alchemy/menus/templates/node.html.haml +1 -1
- data/lib/generators/alchemy/menus/templates/node.html.slim +1 -1
- data/lib/generators/alchemy/menus/templates/wrapper.html.erb +1 -1
- data/lib/generators/alchemy/menus/templates/wrapper.html.haml +1 -1
- data/lib/generators/alchemy/menus/templates/wrapper.html.slim +1 -1
- data/lib/tasks/alchemy/thumbnails.rake +4 -2
- data/lib/tasks/alchemy/tidy.rake +12 -0
- data/lib/tasks/alchemy/upgrade.rake +26 -0
- data/package.json +3 -2
- data/package/admin.js +11 -1
- data/package/src/__tests__/i18n.spec.js +23 -0
- data/package/src/file_editors.js +28 -0
- data/package/src/i18n.js +1 -3
- data/package/src/image_cropper.js +103 -0
- data/package/src/image_loader.js +58 -0
- data/package/src/node_tree.js +5 -5
- data/package/src/picture_editors.js +169 -0
- data/package/src/utils/__tests__/ajax.spec.js +20 -12
- data/package/src/utils/ajax.js +8 -3
- data/vendor/assets/javascripts/jquery_plugins/jquery.Jcrop.min.js +3 -18
- data/vendor/assets/stylesheets/jquery.Jcrop.min.scss +2 -28
- metadata +292 -55
- data/app/assets/javascripts/alchemy/alchemy.image_cropper.js.coffee +0 -44
- data/app/assets/javascripts/alchemy/alchemy.trash_window.js.coffee +0 -30
- data/app/assets/stylesheets/alchemy/trash.scss +0 -8
- data/app/controllers/alchemy/admin/trash_controller.rb +0 -44
- data/app/views/alchemy/admin/attachments/_filter_bar.html.erb +0 -29
- data/app/views/alchemy/admin/essence_files/assign.js.erb +0 -3
- data/app/views/alchemy/admin/essence_pictures/assign.js.erb +0 -4
- data/app/views/alchemy/admin/essence_pictures/crop.html.erb +0 -48
- data/app/views/alchemy/admin/pictures/_filter_bar.html.erb +0 -30
- data/app/views/alchemy/admin/trash/clear.js.erb +0 -4
- data/app/views/alchemy/admin/trash/index.html.erb +0 -31
- data/lib/alchemy/test_support/factories.rb +0 -16
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
RSpec.shared_examples_for "having crop action" do |args|
|
|
4
|
+
describe "#crop" do
|
|
5
|
+
let(:picture) { Alchemy::Picture.new }
|
|
6
|
+
|
|
7
|
+
before do
|
|
8
|
+
expect(args[:model_class]).to receive(:find).and_return(croppable_resource)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
context "with no picture assigned" do
|
|
12
|
+
it "renders error message" do
|
|
13
|
+
get :crop, params: { id: 1 }
|
|
14
|
+
expect(assigns(:no_image_notice)).to eq(Alchemy.t(:no_image_for_cropper_found))
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
context "with picture assigned" do
|
|
19
|
+
subject { get :crop, params: { id: 1, picture_id: picture.id } }
|
|
20
|
+
|
|
21
|
+
let(:default_mask) do
|
|
22
|
+
[
|
|
23
|
+
0,
|
|
24
|
+
0,
|
|
25
|
+
300,
|
|
26
|
+
250,
|
|
27
|
+
]
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
let(:settings) { {} }
|
|
31
|
+
|
|
32
|
+
before do
|
|
33
|
+
picture.image_file_width = 300
|
|
34
|
+
picture.image_file_height = 250
|
|
35
|
+
allow(croppable_resource).to receive(:settings) { settings }
|
|
36
|
+
expect(Alchemy::Picture).to receive(:find_by) { picture }
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
context "with no render_size present in croppable_resource" do
|
|
40
|
+
before do
|
|
41
|
+
expect(croppable_resource).to receive(:render_size).at_least(:once).and_return(nil)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
context "with sizes in settings" do
|
|
45
|
+
let(:settings) do
|
|
46
|
+
{ size: "300x250" }
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it "sets sizes to given values" do
|
|
50
|
+
subject
|
|
51
|
+
expect(assigns(:settings)[:min_size]).to eq([300, 250])
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
context "with no sizes in settings" do
|
|
56
|
+
it "sets sizes to zero" do
|
|
57
|
+
subject
|
|
58
|
+
expect(assigns(:settings)[:min_size]).to eq([0, 0])
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
context "with render_size present in croppable_resource" do
|
|
64
|
+
it "sets sizes from these values" do
|
|
65
|
+
expect(croppable_resource).to receive(:render_size).at_least(:once).and_return("30x25")
|
|
66
|
+
|
|
67
|
+
subject
|
|
68
|
+
expect(assigns(:settings)[:min_size]).to eq([30, 25])
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
context "when width or height is not fixed" do
|
|
72
|
+
it "infers the height from the image file preserving the aspect ratio" do
|
|
73
|
+
expect(croppable_resource).to receive(:render_size).at_least(:once).and_return("30x")
|
|
74
|
+
|
|
75
|
+
subject
|
|
76
|
+
expect(assigns(:settings)[:min_size]).to eq([30, 25])
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
context "and aspect ratio set on the settings" do
|
|
80
|
+
let(:settings) do
|
|
81
|
+
{ fixed_ratio: "2" }
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
it "does not infer the height from the image file preserving the aspect ratio" do
|
|
85
|
+
expect(croppable_resource).to receive(:render_size).at_least(:once).and_return("x25")
|
|
86
|
+
|
|
87
|
+
subject
|
|
88
|
+
expect(assigns(:settings)[:min_size]).to eq([50, 25])
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
context "when width or height is not fixed and an aspect ratio is given" do
|
|
94
|
+
context "and aspect ratio set on the settings" do
|
|
95
|
+
let(:settings) do
|
|
96
|
+
{ fixed_ratio: "0.5" }
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
it "width is given, it infers the height from width and ratio" do
|
|
100
|
+
expect(croppable_resource).to receive(:render_size).at_least(:once).and_return("30x")
|
|
101
|
+
|
|
102
|
+
subject
|
|
103
|
+
expect(assigns(:settings)[:min_size]).to eq([30, 60])
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
it "infers the height from the image file preserving the aspect ratio" do
|
|
108
|
+
expect(croppable_resource).to receive(:render_size).at_least(:once).and_return("x25")
|
|
109
|
+
|
|
110
|
+
subject
|
|
111
|
+
expect(assigns(:settings)[:min_size]).to eq([30, 25])
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
context "no crop sizes present in croppable_resource" do
|
|
117
|
+
it "assigns default mask boxes" do
|
|
118
|
+
subject
|
|
119
|
+
expect(assigns(:settings)[:default_box]).to eq(default_mask)
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
context "crop sizes present in croppable_resource" do
|
|
124
|
+
let(:mask) { [0, 0, 120, 160] }
|
|
125
|
+
|
|
126
|
+
before do
|
|
127
|
+
allow(croppable_resource).to receive(:crop_from).and_return("0x0")
|
|
128
|
+
allow(croppable_resource).to receive(:crop_size).and_return("120x160")
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
it "assigns cropping boxes" do
|
|
132
|
+
subject
|
|
133
|
+
expect(assigns(:settings)[:default_box]).to eq(default_mask)
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
context "with fixed_ratio set to false" do
|
|
138
|
+
let(:settings) do
|
|
139
|
+
{ fixed_ratio: false }
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
it "sets ratio to false" do
|
|
143
|
+
subject
|
|
144
|
+
expect(assigns(:settings)[:ratio]).to eq(false)
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
context "with fixed_ratio set to a non float string" do
|
|
149
|
+
let(:settings) do
|
|
150
|
+
{ fixed_ratio: "123,45" }
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
it "raises error" do
|
|
154
|
+
expect { subject }.to raise_error(ArgumentError)
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
context "with no fixed_ratio set" do
|
|
159
|
+
let(:settings) do
|
|
160
|
+
{ size: "80x60" }
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
it "sets a fixed ratio from sizes" do
|
|
164
|
+
subject
|
|
165
|
+
expect(assigns(:settings)[:ratio]).to eq(80.0 / 60.0)
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
end
|
|
@@ -0,0 +1,646 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
RSpec.shared_examples_for "having picture thumbnails" do
|
|
4
|
+
it "should not store negative values for crop values" do
|
|
5
|
+
record.crop_from = "-1x100"
|
|
6
|
+
record.crop_size = "-20x30"
|
|
7
|
+
record.save
|
|
8
|
+
expect(record.crop_from).to eq("0x100")
|
|
9
|
+
expect(record.crop_size).to eq("0x30")
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it "should not store float values for crop values" do
|
|
13
|
+
record.crop_from = "0.05x104.5"
|
|
14
|
+
record.crop_size = "99.5x203.4"
|
|
15
|
+
record.save
|
|
16
|
+
expect(record.crop_from).to eq("0x105")
|
|
17
|
+
expect(record.crop_size).to eq("100x203")
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it "should not store empty strings for nil crop values" do
|
|
21
|
+
record.crop_from = nil
|
|
22
|
+
record.crop_size = nil
|
|
23
|
+
record.save
|
|
24
|
+
expect(record.crop_from).to eq(nil)
|
|
25
|
+
expect(record.crop_size).to eq(nil)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
describe "#picture_url" do
|
|
29
|
+
subject(:picture_url) { record.picture_url(options) }
|
|
30
|
+
|
|
31
|
+
let(:options) { {} }
|
|
32
|
+
let(:picture) { create(:alchemy_picture) }
|
|
33
|
+
|
|
34
|
+
context "with no format in the options" do
|
|
35
|
+
it "includes the image's default render format." do
|
|
36
|
+
expect(picture_url).to match(/\.png/)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
context "with format in the options" do
|
|
41
|
+
let(:options) { { format: "gif" } }
|
|
42
|
+
|
|
43
|
+
it "takes this as format." do
|
|
44
|
+
expect(picture_url).to match(/\.gif/)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
context "when crop values are present" do
|
|
49
|
+
before do
|
|
50
|
+
allow(record).to receive(:crop_from) { "10x10" }
|
|
51
|
+
allow(record).to receive(:crop_size) { "200x200" }
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
context "if cropping is enabled" do
|
|
55
|
+
before do
|
|
56
|
+
allow(record).to receive(:settings) { { crop: true } }
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
it "passes these crop values to the picture's url method." do
|
|
60
|
+
expect(picture).to receive(:url).with(
|
|
61
|
+
hash_including(crop_from: "10x10", crop_size: "200x200"),
|
|
62
|
+
)
|
|
63
|
+
picture_url
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
context "but with crop values in the options" do
|
|
67
|
+
let(:options) do
|
|
68
|
+
{ crop_from: "30x30", crop_size: "75x75" }
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
it "passes these crop values instead." do
|
|
72
|
+
expect(picture).to receive(:url).with(
|
|
73
|
+
hash_including(crop_from: "30x30", crop_size: "75x75"),
|
|
74
|
+
)
|
|
75
|
+
picture_url
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
context "with other options" do
|
|
82
|
+
let(:options) { { foo: "baz" } }
|
|
83
|
+
|
|
84
|
+
context "and the image does not need to be processed" do
|
|
85
|
+
before do
|
|
86
|
+
allow(record).to receive(:settings) { {} }
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
it "adds them to the url" do
|
|
90
|
+
expect(picture_url).to match(/\?foo=baz/)
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
context "without picture assigned" do
|
|
96
|
+
let(:picture) { nil }
|
|
97
|
+
|
|
98
|
+
it { is_expected.to be_nil }
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
context "if picture.url returns nil" do
|
|
102
|
+
before do
|
|
103
|
+
expect(picture).to receive(:url) { nil }
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
it "returns missing image url" do
|
|
107
|
+
is_expected.to eq "missing-image.png"
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
describe "#picture_url_options" do
|
|
113
|
+
subject(:picture_url_options) { record.picture_url_options }
|
|
114
|
+
|
|
115
|
+
let(:picture) { build_stubbed(:alchemy_picture) }
|
|
116
|
+
|
|
117
|
+
it { is_expected.to be_a(HashWithIndifferentAccess) }
|
|
118
|
+
|
|
119
|
+
it "includes the pictures default render format." do
|
|
120
|
+
expect(picture).to receive(:default_render_format) { "img" }
|
|
121
|
+
expect(picture_url_options[:format]).to eq("img")
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
context "with crop values present" do
|
|
125
|
+
before do
|
|
126
|
+
allow(record).to receive(:crop_from) { "10x10" }
|
|
127
|
+
allow(record).to receive(:crop_size) { "200x200" }
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
context "with cropping enabled" do
|
|
131
|
+
before do
|
|
132
|
+
allow(record).to receive(:settings) { { crop: true } }
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
it "includes these crop values.", :aggregate_failures do
|
|
136
|
+
expect(picture_url_options[:crop_from]).to eq "10x10"
|
|
137
|
+
expect(picture_url_options[:crop_size]).to eq "200x200"
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
context "with cropping disabled" do
|
|
142
|
+
before do
|
|
143
|
+
allow(record).to receive(:settings) { { crop: nil } }
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
it "does not include these crop values.", :aggregate_failures do
|
|
147
|
+
expect(picture_url_options[:crop_from]).to be_nil
|
|
148
|
+
expect(picture_url_options[:crop_size]).to be_nil
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
# Regression spec for issue #1279
|
|
153
|
+
context "with crop values being empty strings" do
|
|
154
|
+
before do
|
|
155
|
+
allow(record).to receive(:crop_from) { "" }
|
|
156
|
+
allow(record).to receive(:crop_size) { "" }
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
it "does not include these crop values.", :aggregate_failures do
|
|
160
|
+
expect(picture_url_options[:crop_from]).to be_nil
|
|
161
|
+
expect(picture_url_options[:crop_size]).to be_nil
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
context "having size setting" do
|
|
167
|
+
before do
|
|
168
|
+
allow(record).to receive(:settings) { { size: "30x70" } }
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
it "includes this size." do
|
|
172
|
+
expect(picture_url_options[:size]).to eq "30x70"
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
context "having crop setting" do
|
|
177
|
+
before do
|
|
178
|
+
allow(record).to receive(:settings) { { crop: true } }
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
it "includes this setting" do
|
|
182
|
+
expect(picture_url_options[:crop]).to be true
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
context "without picture assigned" do
|
|
187
|
+
let(:picture) { nil }
|
|
188
|
+
|
|
189
|
+
it { is_expected.to be_a(Hash) }
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
describe "#thumbnail_url" do
|
|
194
|
+
subject(:thumbnail_url) { record.thumbnail_url }
|
|
195
|
+
|
|
196
|
+
let(:settings) do
|
|
197
|
+
{}
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
let(:picture) { create(:alchemy_picture) }
|
|
201
|
+
|
|
202
|
+
before do
|
|
203
|
+
allow(record).to receive(:settings) { settings }
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
it "includes the image's original file format." do
|
|
207
|
+
expect(thumbnail_url).to match(/\.png/)
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
it "flattens the image." do
|
|
211
|
+
expect(picture).to receive(:url).with(hash_including(flatten: true))
|
|
212
|
+
thumbnail_url
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
context "when crop is enabled in the settings" do
|
|
216
|
+
let(:settings) do
|
|
217
|
+
{ crop: true }
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
context "and crop sizes are present" do
|
|
221
|
+
before do
|
|
222
|
+
allow(record).to receive(:crop_size).and_return("200x200")
|
|
223
|
+
allow(record).to receive(:crop_from).and_return("10x10")
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
it "passes these crop sizes to the picture's url method." do
|
|
227
|
+
expect(picture).to receive(:url).with(
|
|
228
|
+
hash_including(
|
|
229
|
+
crop_from: "10x10",
|
|
230
|
+
crop_size: "200x200",
|
|
231
|
+
crop: true,
|
|
232
|
+
),
|
|
233
|
+
)
|
|
234
|
+
thumbnail_url
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
context "when no crop sizes are present" do
|
|
239
|
+
it "it does not pass crop sizes to the picture's url method and enables center cropping." do
|
|
240
|
+
expect(picture).to receive(:url).with(
|
|
241
|
+
hash_including(
|
|
242
|
+
crop_from: nil,
|
|
243
|
+
crop_size: nil,
|
|
244
|
+
crop: true,
|
|
245
|
+
),
|
|
246
|
+
)
|
|
247
|
+
thumbnail_url
|
|
248
|
+
end
|
|
249
|
+
end
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
context "when cropping is disabled in the settings" do
|
|
253
|
+
let(:settings) do
|
|
254
|
+
{ crop: false }
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
context "but crop sizes are present" do
|
|
258
|
+
before do
|
|
259
|
+
allow(record).to receive(:crop_size).and_return("200x200")
|
|
260
|
+
allow(record).to receive(:crop_from).and_return("10x10")
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
it "it disables cropping." do
|
|
264
|
+
expect(picture).to receive(:url).with(
|
|
265
|
+
hash_including(
|
|
266
|
+
crop_size: nil,
|
|
267
|
+
crop_from: nil,
|
|
268
|
+
crop: false,
|
|
269
|
+
),
|
|
270
|
+
)
|
|
271
|
+
thumbnail_url
|
|
272
|
+
end
|
|
273
|
+
end
|
|
274
|
+
end
|
|
275
|
+
|
|
276
|
+
context "without picture assigned" do
|
|
277
|
+
let(:picture) { nil }
|
|
278
|
+
|
|
279
|
+
it { is_expected.to be_nil }
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
context "if picture.url returns nil" do
|
|
283
|
+
before do
|
|
284
|
+
expect(picture).to receive(:url) { nil }
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
it "returns missing image url" do
|
|
288
|
+
is_expected.to eq "alchemy/missing-image.svg"
|
|
289
|
+
end
|
|
290
|
+
end
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
describe "#thumbnail_url_options" do
|
|
294
|
+
subject(:thumbnail_url_options) { record.thumbnail_url_options }
|
|
295
|
+
|
|
296
|
+
let(:settings) { {} }
|
|
297
|
+
let(:picture) { nil }
|
|
298
|
+
|
|
299
|
+
before do
|
|
300
|
+
allow(record).to receive(:settings) { settings }
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
context "with picture assigned" do
|
|
304
|
+
let(:picture) do
|
|
305
|
+
create(:alchemy_picture)
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
it "includes the image's original file format." do
|
|
309
|
+
expect(thumbnail_url_options[:format]).to eq("png")
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
it "flattens the image." do
|
|
313
|
+
expect(thumbnail_url_options[:flatten]).to be(true)
|
|
314
|
+
end
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
context "when cropping is enabled in settings" do
|
|
318
|
+
let(:settings) do
|
|
319
|
+
{ crop: true }
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
context "and crop values are present" do
|
|
323
|
+
before do
|
|
324
|
+
expect(record).to receive(:crop_size).at_least(:once) { "200x200" }
|
|
325
|
+
expect(record).to receive(:crop_from).at_least(:once) { "10x10" }
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
it "includes these crop values" do
|
|
329
|
+
expect(thumbnail_url_options).to match(
|
|
330
|
+
hash_including(
|
|
331
|
+
crop_from: "10x10",
|
|
332
|
+
crop_size: "200x200",
|
|
333
|
+
crop: true,
|
|
334
|
+
)
|
|
335
|
+
)
|
|
336
|
+
end
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
context "and no crop values are present" do
|
|
340
|
+
it "does not include crop values but enables center cropping" do
|
|
341
|
+
expect(thumbnail_url_options).to match(
|
|
342
|
+
hash_including(
|
|
343
|
+
crop_from: nil,
|
|
344
|
+
crop_size: nil,
|
|
345
|
+
crop: true,
|
|
346
|
+
)
|
|
347
|
+
)
|
|
348
|
+
end
|
|
349
|
+
end
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
context "when cropping is disabled in settings" do
|
|
353
|
+
let(:settings) do
|
|
354
|
+
{ crop: false }
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
context "but crop values are present" do
|
|
358
|
+
before do
|
|
359
|
+
allow(record).to receive(:crop_size) { "200x200" }
|
|
360
|
+
allow(record).to receive(:crop_from) { "10x10" }
|
|
361
|
+
end
|
|
362
|
+
|
|
363
|
+
it "does not include crop values" do
|
|
364
|
+
expect(thumbnail_url_options).to match(
|
|
365
|
+
hash_including(
|
|
366
|
+
crop_from: nil,
|
|
367
|
+
crop_size: nil,
|
|
368
|
+
crop: false,
|
|
369
|
+
)
|
|
370
|
+
)
|
|
371
|
+
end
|
|
372
|
+
end
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
context "without picture assigned" do
|
|
376
|
+
let(:picture) { nil }
|
|
377
|
+
|
|
378
|
+
it "returns default thumbnail options" do
|
|
379
|
+
is_expected.to eq(
|
|
380
|
+
crop: false,
|
|
381
|
+
crop_from: nil,
|
|
382
|
+
crop_size: nil,
|
|
383
|
+
flatten: true,
|
|
384
|
+
format: "jpg",
|
|
385
|
+
size: "160x120",
|
|
386
|
+
)
|
|
387
|
+
end
|
|
388
|
+
end
|
|
389
|
+
end
|
|
390
|
+
|
|
391
|
+
describe "#image_cropper_settings" do
|
|
392
|
+
let(:picture) { nil }
|
|
393
|
+
|
|
394
|
+
subject { record.image_cropper_settings }
|
|
395
|
+
|
|
396
|
+
context "with no picture assigned" do
|
|
397
|
+
it { is_expected.to eq({}) }
|
|
398
|
+
end
|
|
399
|
+
|
|
400
|
+
context "with picture assigned" do
|
|
401
|
+
let(:picture) { build_stubbed(:alchemy_picture) }
|
|
402
|
+
|
|
403
|
+
let(:default_mask) do
|
|
404
|
+
[
|
|
405
|
+
0,
|
|
406
|
+
0,
|
|
407
|
+
300,
|
|
408
|
+
250,
|
|
409
|
+
]
|
|
410
|
+
end
|
|
411
|
+
|
|
412
|
+
let(:settings) { {} }
|
|
413
|
+
|
|
414
|
+
before do
|
|
415
|
+
picture.image_file_width = 300
|
|
416
|
+
picture.image_file_height = 250
|
|
417
|
+
allow(record).to receive(:settings) { settings }
|
|
418
|
+
end
|
|
419
|
+
|
|
420
|
+
context "with no render_size present" do
|
|
421
|
+
before do
|
|
422
|
+
expect(record).to receive(:render_size).at_least(:once).and_return(nil)
|
|
423
|
+
end
|
|
424
|
+
|
|
425
|
+
context "with sizes in settings" do
|
|
426
|
+
let(:settings) do
|
|
427
|
+
{ size: "300x250" }
|
|
428
|
+
end
|
|
429
|
+
|
|
430
|
+
it "sets sizes to given values" do
|
|
431
|
+
expect(subject[:min_size]).to eq([300, 250])
|
|
432
|
+
end
|
|
433
|
+
end
|
|
434
|
+
|
|
435
|
+
context "with no sizes in settings" do
|
|
436
|
+
it "sets sizes to zero" do
|
|
437
|
+
expect(subject[:min_size]).to eq([0, 0])
|
|
438
|
+
end
|
|
439
|
+
end
|
|
440
|
+
end
|
|
441
|
+
|
|
442
|
+
context "with render_size present in record" do
|
|
443
|
+
it "sets sizes from these values" do
|
|
444
|
+
expect(record).to receive(:render_size).at_least(:once).and_return("30x25")
|
|
445
|
+
expect(subject[:min_size]).to eq([30, 25])
|
|
446
|
+
end
|
|
447
|
+
|
|
448
|
+
context "when width or height is not fixed" do
|
|
449
|
+
it "infers the height from the image file preserving the aspect ratio" do
|
|
450
|
+
expect(record).to receive(:render_size).at_least(:once).and_return("30x")
|
|
451
|
+
expect(subject[:min_size]).to eq([30, 25])
|
|
452
|
+
end
|
|
453
|
+
|
|
454
|
+
context "and aspect ratio set" do
|
|
455
|
+
let(:settings) do
|
|
456
|
+
{ fixed_ratio: "2" }
|
|
457
|
+
end
|
|
458
|
+
|
|
459
|
+
it "does not infer the height from the image file preserving the aspect ratio" do
|
|
460
|
+
expect(record).to receive(:render_size).at_least(:once).and_return("x25")
|
|
461
|
+
expect(subject[:min_size]).to eq([50, 25])
|
|
462
|
+
end
|
|
463
|
+
end
|
|
464
|
+
end
|
|
465
|
+
|
|
466
|
+
context "when width or height is not fixed and an aspect ratio is given" do
|
|
467
|
+
context "and aspect ratio set" do
|
|
468
|
+
let(:settings) do
|
|
469
|
+
{ fixed_ratio: "0.5" }
|
|
470
|
+
end
|
|
471
|
+
|
|
472
|
+
it "width is given, it infers the height from width and ratio" do
|
|
473
|
+
expect(record).to receive(:render_size).at_least(:once).and_return("30x")
|
|
474
|
+
expect(subject[:min_size]).to eq([30, 60])
|
|
475
|
+
end
|
|
476
|
+
end
|
|
477
|
+
|
|
478
|
+
it "infers the height from the image file preserving the aspect ratio" do
|
|
479
|
+
expect(record).to receive(:render_size).at_least(:once).and_return("x25")
|
|
480
|
+
expect(subject[:min_size]).to eq([30, 25])
|
|
481
|
+
end
|
|
482
|
+
end
|
|
483
|
+
end
|
|
484
|
+
|
|
485
|
+
context "no crop sizes present in record" do
|
|
486
|
+
it "assigns default mask boxes" do
|
|
487
|
+
expect(subject[:default_box]).to eq(default_mask)
|
|
488
|
+
end
|
|
489
|
+
end
|
|
490
|
+
|
|
491
|
+
context "crop sizes present in record" do
|
|
492
|
+
let(:mask) { [0, 0, 120, 160] }
|
|
493
|
+
|
|
494
|
+
before do
|
|
495
|
+
allow(record).to receive(:crop_from).and_return("0x0")
|
|
496
|
+
allow(record).to receive(:crop_size).and_return("120x160")
|
|
497
|
+
end
|
|
498
|
+
|
|
499
|
+
it "assigns cropping boxes" do
|
|
500
|
+
expect(subject[:default_box]).to eq(default_mask)
|
|
501
|
+
end
|
|
502
|
+
end
|
|
503
|
+
|
|
504
|
+
context "with fixed_ratio set to false" do
|
|
505
|
+
let(:settings) do
|
|
506
|
+
{ fixed_ratio: false }
|
|
507
|
+
end
|
|
508
|
+
|
|
509
|
+
it "sets ratio to false" do
|
|
510
|
+
expect(subject[:ratio]).to eq(false)
|
|
511
|
+
end
|
|
512
|
+
end
|
|
513
|
+
|
|
514
|
+
context "with fixed_ratio set to a non float string" do
|
|
515
|
+
let(:settings) do
|
|
516
|
+
{ fixed_ratio: "123,45" }
|
|
517
|
+
end
|
|
518
|
+
|
|
519
|
+
it "raises an error" do
|
|
520
|
+
expect { subject }.to raise_exception(ArgumentError)
|
|
521
|
+
end
|
|
522
|
+
end
|
|
523
|
+
|
|
524
|
+
context "with no fixed_ratio set" do
|
|
525
|
+
let(:settings) do
|
|
526
|
+
{ size: "80x60" }
|
|
527
|
+
end
|
|
528
|
+
|
|
529
|
+
it "sets a fixed ratio from sizes" do
|
|
530
|
+
expect(subject[:ratio]).to eq(80.0 / 60.0)
|
|
531
|
+
end
|
|
532
|
+
end
|
|
533
|
+
|
|
534
|
+
context "with size set to different values" do
|
|
535
|
+
let(:settings) { { crop: true, size: size } }
|
|
536
|
+
|
|
537
|
+
before do
|
|
538
|
+
picture.image_file_width = 200
|
|
539
|
+
picture.image_file_height = 100
|
|
540
|
+
end
|
|
541
|
+
|
|
542
|
+
context "size 200x50" do
|
|
543
|
+
let(:size) { "200x50" }
|
|
544
|
+
|
|
545
|
+
it "default box should be [0, 25, 200, 75]" do
|
|
546
|
+
expect(subject[:default_box]).to eq([0, 25, 200, 75])
|
|
547
|
+
end
|
|
548
|
+
end
|
|
549
|
+
|
|
550
|
+
context "size 0x0" do
|
|
551
|
+
let(:size) { "0x0" }
|
|
552
|
+
|
|
553
|
+
it "it should not crop the picture" do
|
|
554
|
+
expect(subject[:default_box]).to eq([0, 0, 200, 100])
|
|
555
|
+
end
|
|
556
|
+
end
|
|
557
|
+
|
|
558
|
+
context "size 50x100" do
|
|
559
|
+
let(:size) { "50x100" }
|
|
560
|
+
|
|
561
|
+
it "the hash should be {x1: 75, y1: 0, x2: 125, y2: 100}" do
|
|
562
|
+
expect(subject[:default_box]).to eq([75, 0, 125, 100])
|
|
563
|
+
end
|
|
564
|
+
end
|
|
565
|
+
|
|
566
|
+
context "size 50x50" do
|
|
567
|
+
let(:size) { "50x50" }
|
|
568
|
+
|
|
569
|
+
it "the hash should be {x1: 50, y1: 0, x2: 150, y2: 100}" do
|
|
570
|
+
expect(subject[:default_box]).to eq([50, 0, 150, 100])
|
|
571
|
+
end
|
|
572
|
+
end
|
|
573
|
+
|
|
574
|
+
context "size 400x200" do
|
|
575
|
+
let(:size) { "400x200" }
|
|
576
|
+
|
|
577
|
+
it "the hash should be {x1: 0, y1: 0, x2: 200, y2: 100}" do
|
|
578
|
+
expect(subject[:default_box]).to eq([0, 0, 200, 100])
|
|
579
|
+
end
|
|
580
|
+
end
|
|
581
|
+
|
|
582
|
+
context "size 400x100" do
|
|
583
|
+
let(:size) { "400x100" }
|
|
584
|
+
|
|
585
|
+
it "the hash should be {x1: 0, y1: 25, x2: 200, y2: 75}" do
|
|
586
|
+
expect(subject[:default_box]).to eq([0, 25, 200, 75])
|
|
587
|
+
end
|
|
588
|
+
end
|
|
589
|
+
|
|
590
|
+
context "size 200x200" do
|
|
591
|
+
let(:size) { "200x200" }
|
|
592
|
+
|
|
593
|
+
it "the hash should be {x1: 50, y1: 0, x2: 150, y2: 100}" do
|
|
594
|
+
expect(subject[:default_box]).to eq([50, 0, 150, 100])
|
|
595
|
+
end
|
|
596
|
+
end
|
|
597
|
+
end
|
|
598
|
+
end
|
|
599
|
+
end
|
|
600
|
+
|
|
601
|
+
describe "#allow_image_cropping?" do
|
|
602
|
+
let(:picture) do
|
|
603
|
+
stub_model(Alchemy::Picture, image_file_width: 400, image_file_height: 300)
|
|
604
|
+
end
|
|
605
|
+
|
|
606
|
+
subject { record.allow_image_cropping? }
|
|
607
|
+
|
|
608
|
+
it { is_expected.to be_falsy }
|
|
609
|
+
|
|
610
|
+
context "with picture assigned" do
|
|
611
|
+
before do
|
|
612
|
+
allow(record).to receive(:picture) { picture }
|
|
613
|
+
end
|
|
614
|
+
|
|
615
|
+
it { is_expected.to be_falsy }
|
|
616
|
+
|
|
617
|
+
context "and with image larger than crop size" do
|
|
618
|
+
before do
|
|
619
|
+
allow(picture).to receive(:can_be_cropped_to?) { true }
|
|
620
|
+
end
|
|
621
|
+
|
|
622
|
+
it { is_expected.to be_falsy }
|
|
623
|
+
|
|
624
|
+
context "with crop set to true" do
|
|
625
|
+
before do
|
|
626
|
+
allow(record).to receive(:settings) { { crop: true } }
|
|
627
|
+
end
|
|
628
|
+
|
|
629
|
+
context "if picture.image_file is nil" do
|
|
630
|
+
before do
|
|
631
|
+
expect(picture).to receive(:image_file) { nil }
|
|
632
|
+
end
|
|
633
|
+
|
|
634
|
+
it { is_expected.to be_falsy }
|
|
635
|
+
end
|
|
636
|
+
|
|
637
|
+
context "if picture.image_file is present" do
|
|
638
|
+
let(:picture) { build_stubbed(:alchemy_picture) }
|
|
639
|
+
|
|
640
|
+
it { is_expected.to be(true) }
|
|
641
|
+
end
|
|
642
|
+
end
|
|
643
|
+
end
|
|
644
|
+
end
|
|
645
|
+
end
|
|
646
|
+
end
|