Этот коммит содержится в:
Mattia Roccoberton
2025-04-13 16:30:58 +02:00
родитель 6946b78e4c
Коммит 8cac91f299
4 изменённых файлов: 100 добавлений и 93 удалений

Просмотреть файл

@@ -27,3 +27,7 @@ RSpec/ExampleLength:
RSpec/MultipleExpectations: RSpec/MultipleExpectations:
# default 1 # default 1
Max: 4 Max: 4
RSpec/MultipleMemoizedHelpers:
# default 5
Max: 10

Просмотреть файл

@@ -2,45 +2,34 @@
module Shared module Shared
class QuillEditor < HtmlEditor class QuillEditor < HtmlEditor
SELECTOR = '.ql-container' attr_reader :editor_selector, :toolbar_selector
TOOLBAR_SELECTOR = '.ql-toolbar'
attr_reader :toolbar, :toolbar_selector def initialize(container)
@editor_selector = "#{container} .ql-container"
def initialize(selector: SELECTOR, toolbar_selector: TOOLBAR_SELECTOR) @toolbar_selector = "#{container} .ql-toolbar"
super(selector: selector) super(selector: editor_selector)
@toolbar = find(toolbar_selector)
@toolbar_selector = toolbar_selector
end end
def content = content_element['innerHTML']
def content_element def content_element
@content_element ||= find("#{selector} .ql-editor") @content_element ||= find("#{selector} .ql-editor")
end end
def control_selector(control)
case control&.to_sym
when :bold then "#{toolbar_selector} button.ql-bold"
when :italic then "#{toolbar_selector} button.ql-italic"
when :underline then "#{toolbar_selector} button.ql-underline"
when :link then "#{toolbar_selector} button.ql-link"
else raise "Invalid control #{control}"
end
end
def toggle_bold def toggle_bold
find(control_selector(:bold)).click find("#{toolbar_selector} button.ql-bold").click
end end
def toggle_italic def toggle_italic
find(control_selector(:italic)).click find("#{toolbar_selector} button.ql-italic").click
end end
def toggle_underline def toggle_underline
find(control_selector(:underline)).click find("#{toolbar_selector} button.ql-underline").click
end end
def toggle_link def toggle_link
find(control_selector(:link)).click find("#{toolbar_selector} button.ql-link").click
end end
end end
end end

10
spec/support/string_clean_multiline.rb Обычный файл
Просмотреть файл

@@ -0,0 +1,10 @@
# frozen_string_literal: true
module StringCleanMultiline
refine String do
def clean_multiline
# Get rid of newlines and indentation spaces
strip.gsub(/\s*\n\s*/, "")
end
end
end

Просмотреть файл

@@ -1,114 +1,118 @@
# frozen_string_literal: true # frozen_string_literal: true
using StringCleanMultiline
RSpec.describe 'Quill editor' do RSpec.describe 'Quill editor' do
def lookup_editor(field:) let(:author) { Author.create!(email: 'some_email@example.com', name: 'John Doe', age: 30) }
selector = ["##{field}_input.quill_editor", Shared::QuillEditor::SELECTOR].join(' ') let(:post) do
toolbar_selector = ["##{field}_input.quill_editor", Shared::QuillEditor::TOOLBAR_SELECTOR].join(' ') Post.create!(title: 'Test', author: author, description: '<p>Some content</p>', summary: '<p>Post summary</p>')
Shared::QuillEditor.new(selector: selector, toolbar_selector: toolbar_selector)
end end
let(:author) { Author.create!(email: 'some_email@example.com', name: 'John Doe', age: 30) } let(:submit_button) { find('#post_submit_action [type="submit"]') }
let!(:post) { Post.create!(title: 'Test', author: author, description: '') }
context 'with a Quill editor' do context 'with a Quill editor' do
let(:editor) { lookup_editor(field: 'post_description') } let(:edit_page) do
path = edit_admin_post_path(post)
Admin::Posts::EditPage.new(path: path)
end
let(:editor) { edit_page.lookup_editor(editor_container: '#post_description_input') }
let(:input_field) { find('#post_description[data-aa-quill-editor]') }
before do before do
path = edit_admin_post_path(post) edit_page.load
Admin::Posts::EditPage.new(path: path).load
end end
it 'adds some text to the description', :aggregate_failures do it 'initializes the editor', :aggregate_failures do
expect(page).to have_css('#post_description[data-aa-quill-editor]') expect(editor.content_element).to be_present
editor << 'Some content...' expect(editor.content).to eq('<p>Some content</p>')
%i[bold italic underline link].each do |control| expect(input_field).to be_present
expect(page).to have_css editor.control_selector(control)
end
expect(editor.content_element).to have_content('Some content...')
expect { find('[type="submit"]').click }
.to change { post.reload.description }.to '<p>Some content...</p>'
end end
it 'adds some bold text to the description', :aggregate_failures do it 'edits some content using the editor' do
editor.toolbar_control(:bold) editor << :return << 'More content'
editor << 'Some bold text' editor.toggle_bold
editor << 'Some bold'
editor.toggle_italic
editor << 'Some italic'
editor.toggle_underline
editor << 'Some underline'
expect(editor.content_element).to have_content('Some bold text') expect(editor.content).to eq <<~HTML.clean_multiline
expect { find('[type="submit"]').click } <p>Some content</p>
.to change { post.reload.description }.to '<p><strong>Some bold text</strong></p>' <p>More content<strong>Some bold<em>Some italic<u>Some underline</u></em></strong></p>
HTML
end end
it 'adds some italic text to the description', :aggregate_failures do it 'updates the field when submitting', :aggregate_failures do
editor.toolbar_control(:italic) editor.toggle_bold
editor << 'Some italic text' editor << 'More content'
expect(editor.content_element).to have_content('Some italic text') before = '<p>Some content</p>'
expect { find('[type="submit"]').click } after = '<p><strong>More content</strong>Some content</p>'
.to change { post.reload.description }.to '<p><em>Some italic text</em></p>' expect { submit_button.click }.to change { post.reload.description }.from(before).to(after)
end
it 'adds some underline text to the description', :aggregate_failures do expect(page).to have_content('was successfully updated')
editor.toolbar_control(:underline)
editor << 'Some underline text'
expect(editor.content_element).to have_content('Some underline text')
expect { find('[type="submit"]').click }
.to change { post.reload.description }.to '<p><u>Some underline text</u></p>'
end
it 'adds a link to the description', :aggregate_failures do
editor << "Just a link"
editor.select_all
editor.toolbar_control(:link)
editor.element.find('[data-link]').send_keys("https://www.google.com", :return)
expect(editor.content_element).to have_content('Just a link')
html = '<p><a href="Just a linkhttps://www.google.com" rel="noopener noreferrer" target="_blank">Just a link</a></p>'
expect { find('[type="submit"]').click }.to change { post.reload.description }.to html
end end
end end
context 'with 2 Quill editors' do context 'with 2 Quill editors' do
before do let(:edit_page) do
path = edit_admin_post_path(post) path = edit_admin_post_path(post)
Admin::Posts::EditPage.new(path: path).load Admin::Posts::EditPage.new(path: path)
end
let(:first_editor) { edit_page.lookup_editor(editor_container: '#post_description_input') }
let(:second_editor) { edit_page.lookup_editor(editor_container: '#post_summary_input') }
before do
edit_page.load
end end
it 'updates some HTML content for 2 fields', :aggregate_failures do it 'updates some HTML content for 2 fields', :aggregate_failures do
editor1 = lookup_editor(field: 'post_description') # Check the initial states
editor1.clear.toolbar_control(:bold) expect(first_editor.content).to eq('<p>Some content</p>')
editor1 << "Some description" expect(second_editor.content).to eq('<p>Post summary</p>')
editor2 = lookup_editor(field: 'post_summary') # Add some content to both the editors
editor2.clear.toolbar_control(:italic) first_editor.toggle_bold
editor2 << "Some summary" first_editor << 'Some bold'
find('[type="submit"]').click second_editor.toggle_italic
post.reload second_editor << 'Some italic'
expect(post.description).to eq '<p><strong>Some description</strong></p>' # Check that both the fields change
expect(post.summary).to eq '<p><em>Some summary</em></p>' before = '<p>Some content</p>'
after = '<p><strong>Some bold</strong>Some content</p>'
expect { submit_button.click }.to change { post.reload.description }.from(before).to(after)
expect(post.summary).to eq '<p><em>Some italic</em>Post summary</p>'
end end
end end
context 'with a Quill editor in a nested resource' do context 'with a Quill editor in a nested resource' do
before do let(:edit_page) do
path = edit_admin_author_path(author) path = edit_admin_author_path(author)
Admin::Authors::EditPage.new(path: path).load Admin::Authors::EditPage.new(path: path)
end
let(:submit_button) { find('#author_submit_action [type="submit"]') }
before do
post
edit_page.load
end end
it 'updates some HTML content of a new nested resource', :aggregate_failures do it 'updates some HTML content of a new nested resource', :aggregate_failures do
find('.posts.has_many_container .has_many_add').click click_on 'Add New Post'
expect(page).to have_css('.posts.has_many_container .ql-editor', count: 2)
editor = lookup_editor(field: 'author_posts_attributes_1_description') first_editor = edit_page.lookup_editor(editor_container: '#author_posts_attributes_0_description_input')
editor << "Some post text" expect(first_editor.content).to eq('<p>Some content</p>')
fill_in('author[posts_attributes][1][title]', with: 'A new post') fill_in('author[posts_attributes][1][title]', with: 'Some title')
find('[type="submit"]').click second_editor = edit_page.lookup_editor(editor_container: '#author_posts_attributes_1_description_input')
second_editor.toggle_underline
second_editor << 'Some underline'
expect(page).to have_content('was successfully updated') expect { submit_button.click }.to change(Post, :count).by(1)
expect(author.posts.last.description).to eq '<p>Some post text</p>' expect(Post.last.description).to eq '<p><u>Some underline</u></p>'
end end
end end
end end