trusty-cms 7.0.39 → 7.0.40

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.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -0
  3. data/Gemfile.lock +6 -7
  4. data/README.md +25 -0
  5. data/app/assets/builds/trusty_cms/ckeditor5.css +6966 -0
  6. data/app/assets/builds/trusty_cms/ckeditor5.css.map +7 -0
  7. data/app/assets/builds/trusty_cms/ckeditor5.js +105634 -0
  8. data/app/assets/builds/trusty_cms/ckeditor5.js.map +7 -0
  9. data/app/assets/config/trusty-cms-manifest.js +2 -0
  10. data/app/assets/javascripts/admin.js +0 -1
  11. data/app/assets/stylesheets/admin/_ckeditor.css +109 -0
  12. data/app/assets/stylesheets/admin/main.scss +1 -0
  13. data/app/assets/stylesheets/admin/partials/_content.scss +2 -0
  14. data/app/controllers/admin/assets_controller.rb +78 -23
  15. data/app/controllers/admin/pages_controller.rb +31 -0
  16. data/app/javascript/trusty_cms/ckeditor5.js +391 -0
  17. data/app/models/asset.rb +3 -1
  18. data/app/views/admin/page_parts/_page_part.html.haml +13 -9
  19. data/app/views/layouts/application.html.haml +6 -0
  20. data/config/routes.rb +3 -0
  21. data/lib/generators/trusty_cms/templates/application.rb.erb +0 -1
  22. data/lib/trusty_cms/engine.rb +5 -8
  23. data/lib/trusty_cms/version.rb +1 -1
  24. data/lib/trusty_cms.rb +2 -0
  25. data/package.json +20 -2
  26. data/spec/controllers/assets_controller.rb +66 -0
  27. data/spec/dummy/config/application.rb +1 -1
  28. data/spec/dummy/config/storage.yml +7 -0
  29. data/spec/dummy/db/schema.rb +24 -20
  30. data/spec/fixtures/files/sample.ics +10 -0
  31. data/spec/fixtures/files/sample.txt +1 -0
  32. data/spec/models/asset_spec.rb +39 -0
  33. data/trusty_cms.gemspec +1 -1
  34. data/yarn.lock +2213 -493
  35. metadata +21 -15
  36. data/app/assets/javascripts/ckeditor/config.js +0 -22
  37. data/app/assets/javascripts/ckeditor/contents.css +0 -0
@@ -0,0 +1,391 @@
1
+ /**
2
+ * This configuration was generated using the CKEditor 5 Builder. You can modify it anytime using this link:
3
+ * https://ckeditor.com/ckeditor-5/builder/#installation/NoJgNARCB0Ds0FYKQByxARgGwNgFlgAYsURMBOPFAZkNmvJBxHxdgQyazz3JT2QQApgDtkhMMAxgJE6fIC6kLOQwAjFUIgKgA===
4
+ */
5
+
6
+ const defaultStyleDefinitions = [
7
+ {
8
+ name: 'Article category',
9
+ element: 'h3',
10
+ classes: ['category']
11
+ },
12
+ {
13
+ name: 'Title',
14
+ element: 'h2',
15
+ classes: ['document-title']
16
+ },
17
+ {
18
+ name: 'Subtitle',
19
+ element: 'h3',
20
+ classes: ['document-subtitle']
21
+ },
22
+ {
23
+ name: 'Info box',
24
+ element: 'p',
25
+ classes: ['info-box']
26
+ },
27
+ {
28
+ name: 'CTA Link Primary',
29
+ element: 'a',
30
+ classes: ['button', 'button--green']
31
+ },
32
+ {
33
+ name: 'CTA Link Secondary',
34
+ element: 'a',
35
+ classes: ['button', 'button--black']
36
+ },
37
+ {
38
+ name: 'Marker',
39
+ element: 'span',
40
+ classes: ['marker']
41
+ },
42
+ {
43
+ name: 'Spoiler',
44
+ element: 'span',
45
+ classes: ['spoiler']
46
+ }
47
+ ]
48
+
49
+ import {
50
+ ClassicEditor,
51
+ Alignment,
52
+ Autoformat,
53
+ AutoImage,
54
+ AutoLink,
55
+ Autosave,
56
+ BlockQuote,
57
+ Bold,
58
+ Bookmark,
59
+ Code,
60
+ Essentials,
61
+ FindAndReplace,
62
+ FontBackgroundColor,
63
+ FontColor,
64
+ FontFamily,
65
+ FontSize,
66
+ FullPage,
67
+ Fullscreen,
68
+ GeneralHtmlSupport,
69
+ Heading,
70
+ Highlight,
71
+ HorizontalLine,
72
+ HtmlComment,
73
+ HtmlEmbed,
74
+ ImageBlock,
75
+ ImageCaption,
76
+ ImageEditing,
77
+ ImageInline,
78
+ ImageInsert,
79
+ ImageInsertViaUrl,
80
+ ImageResize,
81
+ ImageStyle,
82
+ ImageTextAlternative,
83
+ ImageToolbar,
84
+ ImageUpload,
85
+ ImageUtils,
86
+ Indent,
87
+ IndentBlock,
88
+ Italic,
89
+ Link,
90
+ LinkImage,
91
+ List,
92
+ ListProperties,
93
+ Paragraph,
94
+ PasteFromOffice,
95
+ RemoveFormat,
96
+ ShowBlocks,
97
+ SimpleUploadAdapter,
98
+ SourceEditing,
99
+ SpecialCharacters,
100
+ SpecialCharactersArrows,
101
+ SpecialCharactersCurrency,
102
+ SpecialCharactersEssentials,
103
+ SpecialCharactersLatin,
104
+ SpecialCharactersMathematical,
105
+ SpecialCharactersText,
106
+ Strikethrough,
107
+ Style,
108
+ Subscript,
109
+ Superscript,
110
+ Table,
111
+ TableCaption,
112
+ TableCellProperties,
113
+ TableColumnResize,
114
+ TableLayout,
115
+ TableProperties,
116
+ TableToolbar,
117
+ TextTransformation,
118
+ TodoList,
119
+ Underline
120
+ } from 'ckeditor5';
121
+
122
+ import "ckeditor5/ckeditor5.css";
123
+
124
+
125
+ const editorConfig = {
126
+ toolbar: {
127
+ items: [
128
+ 'undo',
129
+ 'redo',
130
+ '|',
131
+ 'sourceEditing',
132
+ 'showBlocks',
133
+ 'findAndReplace',
134
+ 'fullscreen',
135
+ '|',
136
+ 'heading',
137
+ 'style',
138
+ '|',
139
+ 'fontSize',
140
+ 'fontFamily',
141
+ 'fontColor',
142
+ 'fontBackgroundColor',
143
+ '|',
144
+ 'bold',
145
+ 'italic',
146
+ 'underline',
147
+ 'strikethrough',
148
+ 'subscript',
149
+ 'superscript',
150
+ 'code',
151
+ 'removeFormat',
152
+ '|',
153
+ 'specialCharacters',
154
+ 'horizontalLine',
155
+ 'link',
156
+ 'bookmark',
157
+ 'insertImage',
158
+ 'insertTable',
159
+ 'insertTableLayout',
160
+ 'highlight',
161
+ 'blockQuote',
162
+ 'htmlEmbed',
163
+ '|',
164
+ 'alignment',
165
+ '|',
166
+ 'bulletedList',
167
+ 'numberedList',
168
+ 'todoList',
169
+ 'outdent',
170
+ 'indent'
171
+ ],
172
+ shouldNotGroupWhenFull: true
173
+ },
174
+ plugins: [
175
+ Alignment,
176
+ Autoformat,
177
+ AutoImage,
178
+ AutoLink,
179
+ Autosave,
180
+ BlockQuote,
181
+ Bold,
182
+ Bookmark,
183
+ Code,
184
+ Essentials,
185
+ FindAndReplace,
186
+ FontBackgroundColor,
187
+ FontColor,
188
+ FontFamily,
189
+ FontSize,
190
+ FullPage,
191
+ Fullscreen,
192
+ GeneralHtmlSupport,
193
+ Heading,
194
+ Highlight,
195
+ HorizontalLine,
196
+ HtmlComment,
197
+ HtmlEmbed,
198
+ ImageBlock,
199
+ ImageCaption,
200
+ ImageEditing,
201
+ ImageInline,
202
+ ImageInsert,
203
+ ImageInsertViaUrl,
204
+ ImageResize,
205
+ ImageStyle,
206
+ ImageTextAlternative,
207
+ ImageToolbar,
208
+ ImageUpload,
209
+ ImageUtils,
210
+ Indent,
211
+ IndentBlock,
212
+ Italic,
213
+ Link,
214
+ LinkImage,
215
+ List,
216
+ ListProperties,
217
+ Paragraph,
218
+ PasteFromOffice,
219
+ RemoveFormat,
220
+ ShowBlocks,
221
+ SimpleUploadAdapter,
222
+ SourceEditing,
223
+ SpecialCharacters,
224
+ SpecialCharactersArrows,
225
+ SpecialCharactersCurrency,
226
+ SpecialCharactersEssentials,
227
+ SpecialCharactersLatin,
228
+ SpecialCharactersMathematical,
229
+ SpecialCharactersText,
230
+ Strikethrough,
231
+ Style,
232
+ Subscript,
233
+ Superscript,
234
+ Table,
235
+ TableCaption,
236
+ TableCellProperties,
237
+ TableColumnResize,
238
+ TableLayout,
239
+ TableProperties,
240
+ TableToolbar,
241
+ TextTransformation,
242
+ TodoList,
243
+ Underline
244
+ ],
245
+ fontFamily: {
246
+ supportAllValues: true
247
+ },
248
+ fontSize: {
249
+ options: [10, 12, 14, 'default', 18, 20, 22],
250
+ supportAllValues: true
251
+ },
252
+ fullscreen: {
253
+ onEnterCallback: container =>
254
+ container.classList.add(
255
+ 'editor-container',
256
+ 'editor-container_classic-editor',
257
+ 'editor-container_include-style',
258
+ 'editor-container_include-fullscreen',
259
+ 'main-container'
260
+ )
261
+ },
262
+ heading: {
263
+ options: [
264
+ {
265
+ model: 'paragraph',
266
+ title: 'Paragraph',
267
+ class: 'ck-heading_paragraph'
268
+ },
269
+ {
270
+ model: 'heading1',
271
+ view: 'h1',
272
+ title: 'Heading 1',
273
+ class: 'ck-heading_heading1'
274
+ },
275
+ {
276
+ model: 'heading2',
277
+ view: 'h2',
278
+ title: 'Heading 2',
279
+ class: 'ck-heading_heading2'
280
+ },
281
+ {
282
+ model: 'heading3',
283
+ view: 'h3',
284
+ title: 'Heading 3',
285
+ class: 'ck-heading_heading3'
286
+ },
287
+ {
288
+ model: 'heading4',
289
+ view: 'h4',
290
+ title: 'Heading 4',
291
+ class: 'ck-heading_heading4'
292
+ },
293
+ {
294
+ model: 'heading5',
295
+ view: 'h5',
296
+ title: 'Heading 5',
297
+ class: 'ck-heading_heading5'
298
+ },
299
+ {
300
+ model: 'heading6',
301
+ view: 'h6',
302
+ title: 'Heading 6',
303
+ class: 'ck-heading_heading6'
304
+ }
305
+ ]
306
+ },
307
+ htmlSupport: {
308
+ allow: [
309
+ {
310
+ name: /^.*$/,
311
+ styles: true,
312
+ attributes: true,
313
+ classes: true
314
+ }
315
+ ]
316
+ },
317
+ image: {
318
+ toolbar: [
319
+ 'toggleImageCaption',
320
+ 'imageTextAlternative',
321
+ '|',
322
+ 'imageStyle:inline',
323
+ 'imageStyle:wrapText',
324
+ 'imageStyle:breakText',
325
+ '|',
326
+ 'resizeImage'
327
+ ]
328
+ },
329
+
330
+ licenseKey: 'GPL',
331
+ link: {
332
+ addTargetToExternalLinks: true,
333
+ defaultProtocol: 'https://',
334
+ decorators: {
335
+ toggleDownloadable: {
336
+ mode: 'manual',
337
+ label: 'Downloadable',
338
+ attributes: {
339
+ download: 'file'
340
+ }
341
+ }
342
+ }
343
+ },
344
+ list: {
345
+ properties: {
346
+ styles: true,
347
+ startIndex: true,
348
+ reversed: true
349
+ }
350
+ },
351
+ menuBar: {
352
+ isVisible: true
353
+ },
354
+ placeholder: 'Type or paste your content here!',
355
+ style: {
356
+ definitions:
357
+ window.TRUSTY_CMS_EDITOR?.styleDefinitions?.length
358
+ ? window.TRUSTY_CMS_EDITOR.styleDefinitions
359
+ : defaultStyleDefinitions,
360
+ },
361
+ table: {
362
+ contentToolbar: ['tableColumn', 'tableRow', 'mergeTableCells', 'tableProperties', 'tableCellProperties']
363
+ },
364
+ simpleUpload: {
365
+ uploadUrl: '/admin/assets/uploader',
366
+ headers: {
367
+ 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content')
368
+ }
369
+ }
370
+ };
371
+
372
+ const editorElements = document.querySelectorAll('[id^="editor_"]');
373
+
374
+ editorElements.forEach((editorElement) => {
375
+ ClassicEditor
376
+ .create(editorElement, editorConfig)
377
+ .then(editor => {
378
+ const pagePart = editorElement.getAttribute('data-part');
379
+ const hiddenInput = document.querySelector(`#part_${pagePart}_content`);
380
+
381
+ if (!hiddenInput) {
382
+ return;
383
+ }
384
+
385
+ editor.model.document.on('change:data', () => {
386
+ hiddenInput.value = editor.getData();
387
+ });
388
+ }).catch(error => {
389
+ console.error(error);
390
+ });
391
+ });
data/app/models/asset.rb CHANGED
@@ -1,4 +1,6 @@
1
1
  class Asset < ActiveRecord::Base
2
+ APPROVED_CONTENT_TYPES = %w[application/zip image/jpg image/jpeg image/png image/gif application/pdf text/css text/calendar].freeze
3
+
2
4
  has_many :page_attachments, dependent: :destroy
3
5
  has_many :pages, through: :page_attachments
4
6
  has_site if respond_to? :has_site
@@ -36,7 +38,7 @@ class Asset < ActiveRecord::Base
36
38
  presence: true,
37
39
  blob:
38
40
  {
39
- content_type: %w[application/zip image/jpg image/jpeg image/png image/gif application/pdf text/css],
41
+ content_type: APPROVED_CONTENT_TYPES,
40
42
  size_range: 1..10.megabytes,
41
43
  }
42
44
  before_save :assign_title
@@ -1,14 +1,18 @@
1
- .page{:id => "page_#{page_part.name.to_slug}", 'data-caption'=>h(page_part.name)}
2
- .part{:id => "part-#{page_part.name.to_slug}"}
3
- = hidden_field_tag "page[parts_attributes][#{page_part_counter}][name]", page_part.name, :id => "part_#{page_part.name.to_slug}_name"
4
- = hidden_field_tag "page[parts_attributes][#{page_part_counter}][id]", page_part.id, :id => "part_#{page_part_counter}_id", :class => 'id_input' unless page_part.new_record?
5
- = hidden_field_tag "page[parts_attributes][#{page_part_counter}][_destroy]", page_part._destroy, :class => 'delete_input'
1
+ .page{ :id => "page_#{ page_part.name.to_slug }", 'data-caption'=>h(page_part.name) }
2
+ .part{ :id => "part-#{ page_part.name.to_slug }" }
3
+ = hidden_field_tag "page[parts_attributes][#{ page_part_counter }][name]", page_part.name, :id => "part_#{ page_part.name.to_slug }_name"
4
+ = hidden_field_tag "page[parts_attributes][#{ page_part_counter }][id]", page_part.id, :id => "part_#{ page_part_counter }_id", :class => 'id_input' unless page_part.new_record?
5
+ = hidden_field_tag "page[parts_attributes][#{ page_part_counter }][_destroy]", page_part._destroy, :class => 'delete_input'
6
6
  .content
7
7
  %label To use HTML or Radius tags, switch to plain text view by clicking the 'Source' button.
8
8
  %span.reference_links
9
9
  = t('reference')
10
- %span{:id => "tag_reference_link_#{page_part.name.to_slug}"}
10
+ %span{ :id => "tag_reference_link_#{ page_part.name.to_slug }" }
11
11
  = link_to t('available_tags'), admin_reference_url(:tags), id: 'tag_reference'
12
- = render_region :part_controls, :locals => {:page_part => page_part}
13
- %div
14
- = cktext_area :page_part, page_part.content || '', :name => "page[parts_attributes][#{page_part_counter}][content]", :value => page_part.content || '', :style => 'width: 100%', :id => "part_#{page_part.name.to_slug}_content"
12
+ = render_region :part_controls, :locals => { :page_part => page_part }
13
+ .main-container
14
+ .editor-container.editor-container_classic-editor.editor-container_include-style.editor-container_include-fullscreen#editor-container
15
+ .editor-container__editor
16
+ %div{ id: "editor_#{ page_part.name.to_slug }", data: { part: page_part.name.to_slug } }
17
+ = page_part.content.to_s.html_safe # rubocop:disable Rails/OutputSafety
18
+ = hidden_field_tag :page_part, page_part.content || '', name: "page[parts_attributes][#{ page_part_counter }][content]", id: "part_#{ page_part.name.to_slug }_content"
@@ -41,7 +41,12 @@
41
41
  - javascript_overrides.each do |javascript|
42
42
  = javascript_include_tag javascript
43
43
 
44
+ = stylesheet_link_tag href="trusty_cms/ckeditor5"
44
45
  = csrf_meta_tags
46
+
47
+ :javascript
48
+ window.TRUSTY_CMS_EDITOR = window.TRUSTY_CMS_EDITOR || {};
49
+ window.TRUSTY_CMS_EDITOR.styleDefinitions = #{(@editor_style_definitions || []).to_json.html_safe};
45
50
 
46
51
  %body{:class=>body_classes.join(" ")}
47
52
  - if gtm_container_id
@@ -84,3 +89,4 @@
84
89
 
85
90
  #popups
86
91
  = yield :popups
92
+ = javascript_include_tag "trusty_cms/ckeditor5", "data-turbo-track": "reload", defer: true
data/config/routes.rb CHANGED
@@ -29,6 +29,9 @@ TrustyCms::Application.routes.draw do
29
29
  get :remove, on: :member
30
30
  get :refresh, on: :collection
31
31
  put :refresh, on: :member
32
+ collection do
33
+ post :uploader
34
+ end
32
35
  end
33
36
  resources :page_attachments, only: [:new] do
34
37
  get :remove, on: :member
@@ -3,7 +3,6 @@ require File.expand_path('../boot', __FILE__)
3
3
  require 'rails/all'
4
4
  require 'acts_as_tree'
5
5
  require 'trusty_cms'
6
- require 'ckeditor'
7
6
  require 'radius'
8
7
  require 'trusty_cms/extension_loader'
9
8
  require 'trusty_cms/initializer'
@@ -1,4 +1,3 @@
1
- require 'ckeditor'
2
1
  require 'devise'
3
2
  require 'ransack'
4
3
  require 'paper_trail'
@@ -10,14 +9,12 @@ module TrustyCms
10
9
  paths['app/helpers'] = []
11
10
  initializer 'trusty_cms.assets.precompile' do |app|
12
11
  app.config.assets.paths << Rails.root.join('../trusty-cms/node_modules')
12
+ engine_builds = Rails.root.join('app/assets/builds')
13
+ app.config.assets.paths << engine_builds
13
14
  app.config.assets.precompile += %w(
14
- admin/main.css admin.js
15
- ckeditor/config.js
16
- ckeditor/contents.css
17
- ckeditor/config.js
18
- ckeditor/styles.js
19
- ckeditor/skins/moono/editor.css
20
- ckeditor/lang/en.js
15
+ admin/main.css
16
+ admin.js
17
+ trusty-cms-manifest.js
21
18
  )
22
19
  end
23
20
  end
@@ -1,3 +1,3 @@
1
1
  module TrustyCms
2
- VERSION = '7.0.39'.freeze
2
+ VERSION = '7.0.40'.freeze
3
3
  end
data/lib/trusty_cms.rb CHANGED
@@ -2,6 +2,8 @@ require 'trusty_cms/version'
2
2
  require 'trusty_cms/engine'
3
3
 
4
4
  module TrustyCms
5
+ mattr_accessor :editor_stylesheets, default: []
6
+ mattr_accessor :editor_style_definitions, default: []
5
7
  end
6
8
 
7
9
  TRUSTY_CMS_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..')) unless defined? TRUSTY_CMS_ROOT
data/package.json CHANGED
@@ -3,12 +3,16 @@
3
3
  "version": "5.3.1",
4
4
  "description": "TrustyCMS is a branch of Radiant CMS. Its goal is to pull the Radiant framework into Rails 6 with minimal changes to its infrastructure.",
5
5
  "main": "index.js",
6
- "repository": "https://github.com/pgharts/trusty-cms.git",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/pgharts/trusty-cms.git"
9
+ },
7
10
  "author": "Danielle Greaves <danigreaves@gmail.com>",
8
11
  "license": "MIT",
9
12
  "dependencies": {
10
13
  "@fortawesome/fontawesome-free": "^5.15.4",
11
14
  "blueimp-file-upload": "^10.32.0",
15
+ "ckeditor5": "^46.0.3",
12
16
  "jquery": "^3.6.1",
13
17
  "jquery-treetable": "^3.2.0-1",
14
18
  "jquery-ui": "^1.13.2",
@@ -18,9 +22,23 @@
18
22
  "tablesaw": "^3.1.2"
19
23
  },
20
24
  "devDependencies": {
25
+ "esbuild": "^0.23.0",
21
26
  "stylelint": "^13.3.2",
22
27
  "stylelint-config-recommended": "^3.0.0",
23
28
  "stylelint-order": "^4.0.0",
24
29
  "stylelint-scss": "^3.17.0"
25
- }
30
+ },
31
+ "directories": {
32
+ "lib": "lib"
33
+ },
34
+ "scripts": {
35
+ "test": "echo \"Error: no test specified\" && exit 1",
36
+ "build": "esbuild app/javascript/trusty_cms/ckeditor5.js --bundle --sourcemap --outdir=app/assets/builds/trusty_cms --public-path=/assets",
37
+ "build:watch": "npm run build -- --watch"
38
+ },
39
+ "keywords": [],
40
+ "bugs": {
41
+ "url": "https://github.com/pgharts/trusty-cms/issues"
42
+ },
43
+ "homepage": "https://github.com/pgharts/trusty-cms#readme"
26
44
  }
@@ -0,0 +1,66 @@
1
+ require 'spec_helper'
2
+ require 'rack/test'
3
+
4
+ RSpec.describe Admin::AssetsController, type: :controller do
5
+ routes { TrustyCms::Engine.routes }
6
+
7
+ let(:user) { create(:admin) }
8
+ let(:fixtures_path) { TrustyCms::Engine.root.join('spec', 'fixtures', 'files') }
9
+
10
+ before do
11
+ allow(controller).to receive(:authenticate_user!).and_return(true)
12
+ allow(controller).to receive(:current_user).and_return(user)
13
+ end
14
+
15
+ around do |example|
16
+ original_kraken = defined?($kraken) ? $kraken : nil
17
+ $kraken = double('KrakenClient', api_key: nil)
18
+ example.run
19
+ $kraken = original_kraken
20
+ end
21
+
22
+ describe 'POST #uploader' do
23
+ it 'returns the asset url when the upload succeeds' do
24
+ file = Rack::Test::UploadedFile.new(fixtures_path.join('sample.ics'), 'text/calendar')
25
+ asset_storage = double('AssetStorage', url: '/assets/sample.ics')
26
+ asset = instance_double(Asset,
27
+ valid?: true,
28
+ asset: asset_storage,
29
+ page_attachments: double('Assoc', build: nil),
30
+ id: 1)
31
+
32
+ allow(asset).to receive(:created_by_id=)
33
+ allow(asset).to receive(:updated_by_id=)
34
+ allow(asset).to receive(:save!)
35
+ allow(Asset).to receive(:create).and_return(asset)
36
+ allow(controller).to receive(:maybe_compress).and_return(file)
37
+
38
+ post :uploader, params: { upload: file }, format: :json
39
+
40
+ expect(response).to have_http_status(:ok)
41
+ expect(JSON.parse(response.body)).to eq('url' => '/assets/sample.ics')
42
+ expect(controller).to have_received(:maybe_compress).with(file)
43
+ expect(Asset).to have_received(:create).with(asset: file, caption: '')
44
+ end
45
+
46
+ it 'returns unsupported media type for disallowed content types' do
47
+ file = Rack::Test::UploadedFile.new(fixtures_path.join('sample.txt'), 'text/plain')
48
+
49
+ expect(Asset).not_to receive(:create)
50
+
51
+ post :uploader, params: { upload: file }, format: :json
52
+
53
+ expect(response).to have_http_status(:unsupported_media_type)
54
+ expect(JSON.parse(response.body)['error']).to eq('Unsupported file type.')
55
+ expect(flash[:error]).to eq('Unsupported file type.')
56
+ end
57
+
58
+ it 'returns unprocessable entity when no file is provided' do
59
+ post :uploader, params: {}, format: :json
60
+
61
+ expect(response).to have_http_status(:unprocessable_entity)
62
+ expect(JSON.parse(response.body)['error']).to eq('No file uploaded.')
63
+ expect(flash[:error]).to eq('No file uploaded.')
64
+ end
65
+ end
66
+ end
@@ -3,7 +3,6 @@ require File.expand_path('../boot', __FILE__)
3
3
  require 'rails/all'
4
4
  require 'acts_as_tree'
5
5
  require "trusty_cms"
6
- require 'ckeditor'
7
6
  require 'radius'
8
7
  require 'trusty_cms/extension_loader'
9
8
  require 'trusty_cms/initializer'
@@ -93,6 +92,7 @@ module TrustyCms
93
92
  :allow_revalidate => false
94
93
  config.middleware.insert_before(Rack::ConditionalGet, Rack::Cache)
95
94
  config.assets.enabled = true
95
+ config.active_storage.service = :test
96
96
  config.filter_parameters += [:password, :password_confirmation]
97
97
 
98
98
  # Use the database for sessions instead of the cookie-based default,
@@ -0,0 +1,7 @@
1
+ test:
2
+ service: Disk
3
+ root: <%= Rails.root.join("tmp/storage") %>
4
+
5
+ local:
6
+ service: Disk
7
+ root: <%= Rails.root.join("storage") %>