ckeditor5 1.15.8 → 1.15.10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +6 -5
- data/README.md +3 -0
- data/lib/ckeditor5/rails/cdn/ckbox_bundle.rb +2 -2
- data/lib/ckeditor5/rails/cdn/helpers.rb +6 -0
- data/lib/ckeditor5/rails/context/helpers.rb +1 -1
- data/lib/ckeditor5/rails/editor/editable_height_normalizer.rb +50 -0
- data/lib/ckeditor5/rails/editor/helpers/config_helpers.rb +3 -3
- data/lib/ckeditor5/rails/editor/helpers/editor_helpers.rb +5 -4
- data/lib/ckeditor5/rails/editor/props.rb +3 -20
- data/lib/ckeditor5/rails/engine.rb +3 -2
- data/lib/ckeditor5/rails/plugins/simple_upload_adapter.rb +1 -1
- data/lib/ckeditor5/rails/presets/plugins_builder.rb +9 -9
- data/lib/ckeditor5/rails/presets/preset_builder.rb +6 -9
- data/lib/ckeditor5/rails/version.rb +1 -1
- data/lib/ckeditor5/rails/version_detector.rb +6 -0
- data/spec/lib/ckeditor5/rails/assets/asset_bundle_hml_serializer_spec.rb +111 -0
- data/spec/lib/ckeditor5/rails/assets/assets_bundle_spec.rb +191 -0
- data/spec/lib/ckeditor5/rails/cdn/ckbox_bundle_spec.rb +69 -0
- data/spec/lib/ckeditor5/rails/cdn/ckeditor_bundle_spec.rb +72 -0
- data/spec/lib/ckeditor5/rails/cdn/helpers_spec.rb +235 -0
- data/spec/lib/ckeditor5/rails/context/helpers_spec.rb +67 -0
- data/spec/lib/ckeditor5/rails/context/props_spec.rb +70 -0
- data/spec/lib/ckeditor5/rails/editor/editable_height_normalizer_spec.rb +50 -0
- data/spec/lib/ckeditor5/rails/editor/helpers/config_helpers_spec.rb +52 -0
- data/spec/lib/ckeditor5/rails/editor/helpers/editor_helpers_spec.rb +192 -0
- data/spec/lib/ckeditor5/rails/editor/props_inline_plugin_spec.rb +43 -0
- data/spec/lib/ckeditor5/rails/editor/props_plugin_spec.rb +66 -0
- data/spec/lib/ckeditor5/rails/editor/props_spec.rb +104 -0
- data/spec/lib/ckeditor5/rails/engine_spec.rb +88 -0
- data/spec/lib/ckeditor5/rails/hooks/form_spec.rb +203 -0
- data/spec/lib/ckeditor5/rails/hooks/simple_form_spec.rb +100 -0
- data/spec/lib/ckeditor5/rails/presets/manager_spec.rb +100 -0
- data/spec/lib/ckeditor5/rails/presets/plugins_builder_spec.rb +98 -0
- data/spec/lib/ckeditor5/rails/presets/preset_builder_spec.rb +347 -0
- data/spec/lib/ckeditor5/rails/presets/toolbar_builder_spec.rb +70 -0
- data/spec/lib/ckeditor5/rails/semver_spec.rb +58 -0
- data/spec/lib/ckeditor5/rails/version_detector_spec.rb +131 -0
- data/spec/lib/ckeditor5/rails/version_spec.rb +25 -0
- data/spec/spec_helper.rb +8 -2
- data/spec/support/test_models.rb +6 -0
- metadata +49 -2
@@ -0,0 +1,191 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
RSpec.describe CKEditor5::Rails::Assets::AssetsBundle do
|
6
|
+
let(:concrete_class) do
|
7
|
+
Class.new(described_class) do
|
8
|
+
def scripts
|
9
|
+
[]
|
10
|
+
end
|
11
|
+
|
12
|
+
def stylesheets
|
13
|
+
[]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '#initialize' do
|
19
|
+
it 'raises error when required methods are not implemented' do
|
20
|
+
expect { described_class.new }.to raise_error(NotImplementedError)
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'initializes successfully when required methods are implemented' do
|
24
|
+
expect { concrete_class.new }.not_to raise_error
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe '#empty?' do
|
29
|
+
subject(:bundle) { concrete_class.new }
|
30
|
+
|
31
|
+
it 'returns true when no assets are present' do
|
32
|
+
expect(bundle).to be_empty
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe '#translations_scripts' do
|
37
|
+
let(:bundle) { concrete_class.new }
|
38
|
+
let(:translation_script) { instance_double(CKEditor5::Rails::Assets::JSExportsMeta, translation?: true) }
|
39
|
+
let(:regular_script) { instance_double(CKEditor5::Rails::Assets::JSExportsMeta, translation?: false) }
|
40
|
+
|
41
|
+
before do
|
42
|
+
allow(bundle).to receive(:scripts).and_return([translation_script, regular_script])
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'returns only translation scripts' do
|
46
|
+
expect(bundle.translations_scripts).to eq([translation_script])
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe '#<<' do
|
51
|
+
let(:script1) { instance_double(CKEditor5::Rails::Assets::JSExportsMeta) }
|
52
|
+
let(:script2) { instance_double(CKEditor5::Rails::Assets::JSExportsMeta) }
|
53
|
+
let(:stylesheet1) { '/path/to/style1.css' }
|
54
|
+
let(:stylesheet2) { '/path/to/style2.css' }
|
55
|
+
|
56
|
+
let(:bundle1) do
|
57
|
+
Class.new(described_class) do
|
58
|
+
attr_writer :scripts, :stylesheets
|
59
|
+
|
60
|
+
def scripts
|
61
|
+
@scripts ||= []
|
62
|
+
end
|
63
|
+
|
64
|
+
def stylesheets
|
65
|
+
@stylesheets ||= []
|
66
|
+
end
|
67
|
+
end.new
|
68
|
+
end
|
69
|
+
|
70
|
+
let(:bundle2) do
|
71
|
+
Class.new(described_class) do
|
72
|
+
attr_writer :scripts, :stylesheets
|
73
|
+
|
74
|
+
def scripts
|
75
|
+
@scripts ||= []
|
76
|
+
end
|
77
|
+
|
78
|
+
def stylesheets
|
79
|
+
@stylesheets ||= []
|
80
|
+
end
|
81
|
+
end.new
|
82
|
+
end
|
83
|
+
|
84
|
+
before do
|
85
|
+
bundle1.scripts = [script1]
|
86
|
+
bundle1.stylesheets = [stylesheet1]
|
87
|
+
bundle2.scripts = [script2]
|
88
|
+
bundle2.stylesheets = [stylesheet2]
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'raises TypeError when argument is not an AssetsBundle' do
|
92
|
+
expect { bundle1 << 'not a bundle' }.to raise_error(TypeError)
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'merges scripts and stylesheets from both bundles' do
|
96
|
+
bundle1 << bundle2
|
97
|
+
|
98
|
+
expect(bundle1.scripts).to eq([script1, script2])
|
99
|
+
expect(bundle1.stylesheets).to eq([stylesheet1, stylesheet2])
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
describe '#preloads' do
|
104
|
+
let(:script1) { instance_double(CKEditor5::Rails::Assets::JSExportsMeta, url: '/js/script1.js') }
|
105
|
+
let(:script2) { instance_double(CKEditor5::Rails::Assets::JSExportsMeta, url: '/js/script2.js') }
|
106
|
+
let(:stylesheet1) { '/css/style1.css' }
|
107
|
+
let(:stylesheet2) { '/css/style2.css' }
|
108
|
+
|
109
|
+
let(:bundle) do
|
110
|
+
Class.new(described_class) do
|
111
|
+
attr_writer :scripts, :stylesheets
|
112
|
+
|
113
|
+
def scripts
|
114
|
+
@scripts ||= []
|
115
|
+
end
|
116
|
+
|
117
|
+
def stylesheets
|
118
|
+
@stylesheets ||= []
|
119
|
+
end
|
120
|
+
end.new
|
121
|
+
end
|
122
|
+
|
123
|
+
before do
|
124
|
+
bundle.scripts = [script1, script2]
|
125
|
+
bundle.stylesheets = [stylesheet1, stylesheet2]
|
126
|
+
end
|
127
|
+
|
128
|
+
it 'returns array of stylesheet paths and script urls' do
|
129
|
+
expect(bundle.preloads).to eq([
|
130
|
+
'/css/style1.css',
|
131
|
+
'/css/style2.css',
|
132
|
+
'/js/script1.js',
|
133
|
+
'/js/script2.js'
|
134
|
+
])
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
RSpec.describe CKEditor5::Rails::Assets::JSExportsMeta do
|
140
|
+
let(:url) { '/path/to/script.js' }
|
141
|
+
|
142
|
+
describe '#initialize' do
|
143
|
+
it 'creates instance with import_name' do
|
144
|
+
meta = described_class.new(url, import_name: 'module')
|
145
|
+
expect(meta.import_name).to eq('module')
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'creates instance with window_name' do
|
149
|
+
meta = described_class.new(url, window_name: 'MyModule')
|
150
|
+
expect(meta.window_name).to eq('MyModule')
|
151
|
+
end
|
152
|
+
|
153
|
+
it 'marks as translation when specified' do
|
154
|
+
meta = described_class.new(url, translation: true, import_name: 'module')
|
155
|
+
expect(meta).to be_translation
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
RSpec.describe CKEditor5::Rails::Assets::JSImportMeta do
|
161
|
+
describe '#initialize' do
|
162
|
+
it 'raises error when neither import_name nor window_name is provided' do
|
163
|
+
expect { described_class.new }.to raise_error(ArgumentError)
|
164
|
+
end
|
165
|
+
|
166
|
+
it 'raises error when import_as is present without import_name' do
|
167
|
+
expect { described_class.new(import_as: 'alias', window_name: 'Module') }
|
168
|
+
.to raise_error(ArgumentError)
|
169
|
+
end
|
170
|
+
|
171
|
+
it 'creates valid instance with import_name' do
|
172
|
+
meta = described_class.new(import_name: 'module')
|
173
|
+
expect(meta).to be_esm
|
174
|
+
end
|
175
|
+
|
176
|
+
it 'creates valid instance with window_name' do
|
177
|
+
meta = described_class.new(window_name: 'Module')
|
178
|
+
expect(meta).to be_window
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
describe '#to_h' do
|
183
|
+
it 'returns hash with only present values' do
|
184
|
+
meta = described_class.new(import_name: 'module', import_as: 'alias')
|
185
|
+
expect(meta.to_h).to eq({
|
186
|
+
import_name: 'module',
|
187
|
+
import_as: 'alias'
|
188
|
+
})
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
RSpec.describe CKEditor5::Rails::Cdn::CKBoxBundle do
|
6
|
+
let(:version) { CKEditor5::Rails::Semver.new('2.6.0') }
|
7
|
+
let(:cdn) { :jsdelivr }
|
8
|
+
let(:theme) { :lark }
|
9
|
+
let(:translations) { [] }
|
10
|
+
let(:bundle) { described_class.new(version, theme: theme, cdn: cdn, translations: translations) }
|
11
|
+
|
12
|
+
describe '#initialize' do
|
13
|
+
context 'with valid parameters' do
|
14
|
+
it 'creates bundle successfully' do
|
15
|
+
expect { bundle }.not_to raise_error
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
context 'with invalid parameters' do
|
20
|
+
it 'raises error for invalid version' do
|
21
|
+
expect { described_class.new('invalid', theme: theme) }
|
22
|
+
.to raise_error(ArgumentError, 'version must be semver')
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'raises error for invalid theme type' do
|
26
|
+
expect { described_class.new(version, theme: 123) }
|
27
|
+
.to raise_error(ArgumentError, 'theme must be a string or symbol')
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'raises error for invalid translations type' do
|
31
|
+
expect { described_class.new(version, theme: theme, translations: 'invalid') }
|
32
|
+
.to raise_error(ArgumentError, 'translations must be an array')
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe '#scripts' do
|
38
|
+
it 'returns array with main script' do
|
39
|
+
expect(bundle.scripts.first).to be_a(CKEditor5::Rails::Assets::JSExportsMeta)
|
40
|
+
expect(bundle.scripts.first.url).to include('ckbox.js')
|
41
|
+
expect(bundle.scripts.first.window_name).to eq('CKBox')
|
42
|
+
end
|
43
|
+
|
44
|
+
context 'with translations' do
|
45
|
+
let(:translations) { [:pl] }
|
46
|
+
|
47
|
+
it 'includes translation scripts' do
|
48
|
+
translation_script = bundle.scripts.last
|
49
|
+
expect(translation_script.url).to include('translations/pl.js')
|
50
|
+
expect(translation_script.window_name).to eq('CKBOX_TRANSLATIONS')
|
51
|
+
expect(translation_script.translation?).to be true
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe '#stylesheets' do
|
57
|
+
it 'returns array with theme stylesheet' do
|
58
|
+
expect(bundle.stylesheets.first).to include('styles/themes/lark.css')
|
59
|
+
end
|
60
|
+
|
61
|
+
context 'with custom theme' do
|
62
|
+
let(:theme) { :custom }
|
63
|
+
|
64
|
+
it 'uses custom theme in stylesheet path' do
|
65
|
+
expect(bundle.stylesheets.first).to include('styles/themes/custom.css')
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
RSpec.describe CKEditor5::Rails::Cdn::CKEditorBundle do
|
6
|
+
let(:version) { CKEditor5::Rails::Semver.new('34.1.0') }
|
7
|
+
let(:import_name) { '@ckeditor/ckeditor5-build-classic' }
|
8
|
+
let(:translations) { %w[pl de] }
|
9
|
+
let(:cdn) { 'https://cdn.example.com' }
|
10
|
+
|
11
|
+
before do
|
12
|
+
allow(CKEditor5::Rails::Engine.default_preset).to receive(:cdn).and_return(cdn)
|
13
|
+
allow_any_instance_of(described_class).to receive(:create_cdn_url) do |_, pkg, ver, file|
|
14
|
+
"#{cdn}/npm/#{pkg}@#{ver}/build/#{file}"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '#initialize' do
|
19
|
+
it 'creates instance with valid parameters' do
|
20
|
+
expect do
|
21
|
+
described_class.new(version, import_name, translations: translations)
|
22
|
+
end.not_to raise_error
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'raises error when version is not Semver' do
|
26
|
+
expect do
|
27
|
+
described_class.new('34.1.0', import_name)
|
28
|
+
end.to raise_error(ArgumentError, 'version must be semver')
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'raises error when import_name is not string' do
|
32
|
+
expect do
|
33
|
+
described_class.new(version, :invalid)
|
34
|
+
end.to raise_error(ArgumentError, 'import_name must be a string')
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'raises error when translations is not array' do
|
38
|
+
expect do
|
39
|
+
described_class.new(version, import_name, translations: 'invalid')
|
40
|
+
end.to raise_error(ArgumentError, 'translations must be an array')
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe '#scripts' do
|
45
|
+
subject(:bundle) { described_class.new(version, import_name, translations: translations) }
|
46
|
+
|
47
|
+
it 'returns main script and translation scripts' do
|
48
|
+
expect(bundle.scripts.count).to eq(3)
|
49
|
+
expect(bundle.scripts.first.url).to eq("#{cdn}/npm/#{import_name}@#{version}/build/#{import_name}.js")
|
50
|
+
expect(bundle.scripts.first).not_to be_translation
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'includes translation scripts' do
|
54
|
+
translation_scripts = bundle.scripts.select(&:translation?)
|
55
|
+
expect(translation_scripts.count).to eq(2)
|
56
|
+
expect(translation_scripts.map(&:url)).to contain_exactly(
|
57
|
+
"#{cdn}/npm/#{import_name}@#{version}/build/translations/pl.js",
|
58
|
+
"#{cdn}/npm/#{import_name}@#{version}/build/translations/de.js"
|
59
|
+
)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe '#stylesheets' do
|
64
|
+
subject(:bundle) { described_class.new(version, import_name) }
|
65
|
+
|
66
|
+
it 'returns stylesheet URL' do
|
67
|
+
expect(bundle.stylesheets).to eq(
|
68
|
+
["#{cdn}/npm/#{import_name}@#{version}/build/#{import_name}.css"]
|
69
|
+
)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,235 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
RSpec.describe CKEditor5::Rails::Cdn::Helpers do
|
6
|
+
let(:test_class) { Class.new { include CKEditor5::Rails::Cdn::Helpers } }
|
7
|
+
let(:helper) { test_class.new }
|
8
|
+
let(:preset) do
|
9
|
+
instance_double(
|
10
|
+
CKEditor5::Rails::Presets::PresetBuilder,
|
11
|
+
to_h_with_overrides: {
|
12
|
+
cdn: :cloud,
|
13
|
+
version: '34.1.0',
|
14
|
+
type: 'classic',
|
15
|
+
translations: %w[pl],
|
16
|
+
ckbox: nil,
|
17
|
+
license_key: nil,
|
18
|
+
premium: false
|
19
|
+
}
|
20
|
+
)
|
21
|
+
end
|
22
|
+
let(:bundle_html) { '<script src="test.js"></script>' }
|
23
|
+
let(:serializer) do
|
24
|
+
instance_double(CKEditor5::Rails::Assets::AssetsBundleHtmlSerializer, to_html: bundle_html)
|
25
|
+
end
|
26
|
+
|
27
|
+
before do
|
28
|
+
allow(CKEditor5::Rails::Engine).to receive(:find_preset).and_return(preset)
|
29
|
+
allow(CKEditor5::Rails::Assets::AssetsBundleHtmlSerializer).to receive(:new).and_return(serializer)
|
30
|
+
end
|
31
|
+
|
32
|
+
describe '#ckeditor5_assets' do
|
33
|
+
context 'with valid preset' do
|
34
|
+
it 'returns serialized bundle html' do
|
35
|
+
expect(helper.ckeditor5_assets(preset: :default)).to eq(bundle_html)
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'creates base bundle' do
|
39
|
+
expect(CKEditor5::Rails::Cdn::CKEditorBundle).to receive(:new)
|
40
|
+
.with(
|
41
|
+
instance_of(CKEditor5::Rails::Semver),
|
42
|
+
'ckeditor5',
|
43
|
+
translations: %w[pl],
|
44
|
+
cdn: :cloud
|
45
|
+
)
|
46
|
+
.and_call_original
|
47
|
+
|
48
|
+
helper.ckeditor5_assets(preset: :default)
|
49
|
+
end
|
50
|
+
|
51
|
+
context 'with premium features' do
|
52
|
+
let(:preset) do
|
53
|
+
instance_double(
|
54
|
+
CKEditor5::Rails::Presets::PresetBuilder,
|
55
|
+
to_h_with_overrides: {
|
56
|
+
cdn: :cloud,
|
57
|
+
version: '34.1.0',
|
58
|
+
type: 'classic',
|
59
|
+
translations: %w[pl],
|
60
|
+
ckbox: nil,
|
61
|
+
license_key: nil,
|
62
|
+
premium: true
|
63
|
+
}
|
64
|
+
)
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'creates base and premium bundles' do
|
68
|
+
expect(CKEditor5::Rails::Cdn::CKEditorBundle).to receive(:new)
|
69
|
+
.with(
|
70
|
+
instance_of(CKEditor5::Rails::Semver),
|
71
|
+
'ckeditor5',
|
72
|
+
translations: %w[pl],
|
73
|
+
cdn: :cloud
|
74
|
+
)
|
75
|
+
.and_call_original
|
76
|
+
.ordered
|
77
|
+
|
78
|
+
expect(CKEditor5::Rails::Cdn::CKEditorBundle).to receive(:new)
|
79
|
+
.with(
|
80
|
+
instance_of(CKEditor5::Rails::Semver),
|
81
|
+
'ckeditor5-premium-features',
|
82
|
+
translations: %w[pl],
|
83
|
+
cdn: :cloud
|
84
|
+
)
|
85
|
+
.and_call_original
|
86
|
+
.ordered
|
87
|
+
|
88
|
+
helper.ckeditor5_assets(preset: :default)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
context 'with ckbox' do
|
93
|
+
let(:preset) do
|
94
|
+
instance_double(
|
95
|
+
CKEditor5::Rails::Presets::PresetBuilder,
|
96
|
+
to_h_with_overrides: {
|
97
|
+
cdn: :cloud,
|
98
|
+
version: '34.1.0',
|
99
|
+
type: 'classic',
|
100
|
+
translations: %w[pl],
|
101
|
+
ckbox: { version: '1.0.0', theme: :lark },
|
102
|
+
license_key: nil,
|
103
|
+
premium: false
|
104
|
+
}
|
105
|
+
)
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'creates ckbox bundle' do
|
109
|
+
expect(CKEditor5::Rails::Cdn::CKBoxBundle).to receive(:new)
|
110
|
+
.with(
|
111
|
+
instance_of(CKEditor5::Rails::Semver),
|
112
|
+
theme: :lark,
|
113
|
+
cdn: :ckbox
|
114
|
+
)
|
115
|
+
.and_call_original
|
116
|
+
|
117
|
+
helper.ckeditor5_assets(preset: :default)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
context 'when destructuring preset hash' do
|
122
|
+
let(:preset) do
|
123
|
+
instance_double(
|
124
|
+
CKEditor5::Rails::Presets::PresetBuilder,
|
125
|
+
to_h_with_overrides: {
|
126
|
+
cdn: :cloud,
|
127
|
+
version: '34.1.0',
|
128
|
+
type: 'classic',
|
129
|
+
translations: %w[pl],
|
130
|
+
ckbox: nil,
|
131
|
+
license_key: nil,
|
132
|
+
premium: false,
|
133
|
+
extra: 'value'
|
134
|
+
}
|
135
|
+
)
|
136
|
+
end
|
137
|
+
|
138
|
+
it 'successfully matches and extracts required parameters' do
|
139
|
+
expect { helper.ckeditor5_assets(preset: :default) }.not_to raise_error
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
context 'with invalid preset' do
|
145
|
+
before do
|
146
|
+
allow(CKEditor5::Rails::Engine).to receive(:find_preset).and_return(nil)
|
147
|
+
end
|
148
|
+
|
149
|
+
it 'raises error' do
|
150
|
+
expect { helper.ckeditor5_assets(preset: :invalid) }
|
151
|
+
.to raise_error(ArgumentError, /forgot to define your invalid preset/)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
context 'with missing required parameters' do
|
156
|
+
let(:preset) do
|
157
|
+
instance_double(
|
158
|
+
CKEditor5::Rails::Presets::PresetBuilder,
|
159
|
+
to_h_with_overrides: { cdn: :cloud }
|
160
|
+
)
|
161
|
+
end
|
162
|
+
|
163
|
+
before do
|
164
|
+
allow(helper).to receive(:merge_with_editor_preset).and_return({})
|
165
|
+
end
|
166
|
+
|
167
|
+
it 'raises error about missing required parameters' do
|
168
|
+
expect { helper.ckeditor5_assets(preset: :default) }
|
169
|
+
.to raise_error(NoMatchingPatternKeyError)
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
context 'with empty hash from preset' do
|
174
|
+
let(:preset) do
|
175
|
+
instance_double(
|
176
|
+
CKEditor5::Rails::Presets::PresetBuilder,
|
177
|
+
to_h_with_overrides: {}
|
178
|
+
)
|
179
|
+
end
|
180
|
+
|
181
|
+
it 'raises error about missing version and type' do
|
182
|
+
expect { helper.ckeditor5_assets(preset: :default) }
|
183
|
+
.to raise_error(ArgumentError, /forgot to define version/)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
context 'when overriding preset values with kwargs' do
|
189
|
+
let(:preset) do
|
190
|
+
CKEditor5::Rails::Presets::PresetBuilder.new do
|
191
|
+
version '34.1.0'
|
192
|
+
type :classic
|
193
|
+
translations :pl
|
194
|
+
cdn :cloud
|
195
|
+
license_key 'preset-license'
|
196
|
+
premium false
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
before do
|
201
|
+
allow(CKEditor5::Rails::Engine).to receive(:find_preset).and_return(preset)
|
202
|
+
end
|
203
|
+
|
204
|
+
it 'allows overriding preset values with kwargs' do
|
205
|
+
result = helper.send(:merge_with_editor_preset, :default, license_key: 'overridden-license')
|
206
|
+
expect(result).to include(license_key: 'overridden-license')
|
207
|
+
end
|
208
|
+
|
209
|
+
it 'preserves non-overridden preset values' do
|
210
|
+
result = helper.send(:merge_with_editor_preset, :default, license_key: 'overridden-license')
|
211
|
+
expect(result).to eq(
|
212
|
+
version: '34.1.0',
|
213
|
+
premium: false,
|
214
|
+
cdn: :cloud,
|
215
|
+
translations: [:pl],
|
216
|
+
license_key: 'overridden-license',
|
217
|
+
type: :classic,
|
218
|
+
ckbox: nil,
|
219
|
+
config: { plugins: [], toolbar: [] }
|
220
|
+
)
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
describe 'cdn helper methods' do
|
225
|
+
it 'generates helper methods for third-party CDNs' do
|
226
|
+
expect(helper).to respond_to(:ckeditor5_unpkg_assets)
|
227
|
+
expect(helper).to respond_to(:ckeditor5_jsdelivr_assets)
|
228
|
+
end
|
229
|
+
|
230
|
+
it 'calls main helper with proper cdn parameter' do
|
231
|
+
expect(helper).to receive(:ckeditor5_assets).with(cdn: :unpkg, version: '34.1.0')
|
232
|
+
helper.ckeditor5_unpkg_assets(version: '34.1.0')
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
require 'action_view'
|
5
|
+
|
6
|
+
RSpec.describe CKEditor5::Rails::Context::Helpers do
|
7
|
+
let(:test_class) do
|
8
|
+
Class.new do
|
9
|
+
include ActionView::Helpers::TagHelper
|
10
|
+
include CKEditor5::Rails::Context::Helpers
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
let(:helper) { test_class.new }
|
15
|
+
|
16
|
+
describe '#ckeditor5_context' do
|
17
|
+
it 'creates context component with default attributes' do
|
18
|
+
expect(helper.ckeditor5_context).to have_tag(
|
19
|
+
'ckeditor-context-component',
|
20
|
+
with: {
|
21
|
+
plugins: '[]',
|
22
|
+
config: '{}'
|
23
|
+
}
|
24
|
+
)
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'creates context component with preset configuration' do
|
28
|
+
expect(helper.ckeditor5_context(preset: :custom)).to have_tag(
|
29
|
+
'ckeditor-context-component',
|
30
|
+
with: {
|
31
|
+
plugins: '[]',
|
32
|
+
config: '{"preset":"custom"}'
|
33
|
+
}
|
34
|
+
)
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'creates context component with cdn configuration' do
|
38
|
+
expect(helper.ckeditor5_context(cdn: :jsdelivr)).to have_tag(
|
39
|
+
'ckeditor-context-component',
|
40
|
+
with: {
|
41
|
+
plugins: '[]',
|
42
|
+
config: '{"cdn":"jsdelivr"}'
|
43
|
+
}
|
44
|
+
)
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'creates context component with multiple configurations' do
|
48
|
+
result = helper.ckeditor5_context(preset: :custom, cdn: :jsdelivr)
|
49
|
+
|
50
|
+
expect(result).to have_tag(
|
51
|
+
'ckeditor-context-component',
|
52
|
+
with: {
|
53
|
+
plugins: '[]',
|
54
|
+
config: '{"preset":"custom","cdn":"jsdelivr"}'
|
55
|
+
}
|
56
|
+
)
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'accepts block content' do
|
60
|
+
result = helper.ckeditor5_context { 'Content' }
|
61
|
+
|
62
|
+
expect(result).to have_tag('ckeditor-context-component') do
|
63
|
+
with_text 'Content'
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
RSpec.describe CKEditor5::Rails::Context::Props do
|
6
|
+
let(:config) do
|
7
|
+
{
|
8
|
+
plugins: [
|
9
|
+
CKEditor5::Rails::Editor::PropsPlugin.new('Plugin1', import_name: '@ckeditor/plugin1'),
|
10
|
+
CKEditor5::Rails::Editor::PropsInlinePlugin.new('plugin2', 'export default class Plugin2 {}')
|
11
|
+
],
|
12
|
+
toolbar: { items: %w[bold italic] },
|
13
|
+
language: 'en'
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
subject(:props) { described_class.new(config) }
|
18
|
+
|
19
|
+
describe '#initialize' do
|
20
|
+
it 'accepts a config hash' do
|
21
|
+
expect { described_class.new({}) }.not_to raise_error
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe '#to_attributes' do
|
26
|
+
subject(:attributes) { props.to_attributes }
|
27
|
+
|
28
|
+
it 'returns a hash with plugins and config keys' do
|
29
|
+
expect(attributes).to be_a(Hash)
|
30
|
+
expect(attributes.keys).to match_array(%i[plugins config])
|
31
|
+
end
|
32
|
+
|
33
|
+
describe ':plugins key' do
|
34
|
+
subject(:plugins_json) { attributes[:plugins] }
|
35
|
+
|
36
|
+
it 'serializes plugins array to JSON' do
|
37
|
+
expect(plugins_json).to be_a(String)
|
38
|
+
expect(JSON.parse(plugins_json)).to be_an(Array)
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'normalizes and includes all plugins' do
|
42
|
+
plugins = JSON.parse(plugins_json)
|
43
|
+
expect(plugins.size).to eq(2)
|
44
|
+
expect(plugins.first).to include(
|
45
|
+
'type' => 'external',
|
46
|
+
'import_name' => '@ckeditor/plugin1'
|
47
|
+
)
|
48
|
+
expect(plugins.last).to include(
|
49
|
+
'type' => 'inline',
|
50
|
+
'name' => 'plugin2',
|
51
|
+
'code' => 'export default class Plugin2 {}'
|
52
|
+
)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe ':config key' do
|
57
|
+
subject(:config_json) { attributes[:config] }
|
58
|
+
|
59
|
+
it 'serializes config to JSON excluding plugins' do
|
60
|
+
expect(config_json).to be_a(String)
|
61
|
+
parsed = JSON.parse(config_json)
|
62
|
+
expect(parsed).to include(
|
63
|
+
'toolbar' => { 'items' => %w[bold italic] },
|
64
|
+
'language' => 'en'
|
65
|
+
)
|
66
|
+
expect(parsed).not_to include('plugins')
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|