Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ AllCops:

RSpec/ExampleLength:
# default 5
Max: 10
Max: 12

RSpec/MultipleMemoizedHelpers:
# default: 5
Expand Down
1 change: 0 additions & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ gem 'capybara'
gem 'cuprite'
gem 'rspec_junit_formatter'
gem 'rspec-rails'
gem 'rspec-retry'
gem 'simplecov', require: false

# Linters
Expand Down
6 changes: 3 additions & 3 deletions spec/dummy/app/admin/posts.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,13 @@
end

form do |f|
buttons = %w[bold italic underline link justifyRight]
buttons = %w[strong em underline link justifyRight]

f.inputs 'Post' do
f.input :author
f.input :title
f.input :summary, as: :trumbowyg, input_html: { data: { options: { btns: buttons } } }
f.input :description, as: :trumbowyg # using default options
f.input :summary, as: :trumbowyg # using default options
f.input :description, as: :trumbowyg, input_html: { data: { options: { btns: buttons } } }
f.input :category
f.input :dt
f.input :position
Expand Down
9 changes: 9 additions & 0 deletions spec/page_objects/admin/authors/edit_page.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# frozen_string_literal: true

module Admin
module Authors
class EditPage < BasePage
include Capybara::DSL
end
end
end
9 changes: 9 additions & 0 deletions spec/page_objects/admin/posts/edit_page.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# frozen_string_literal: true

module Admin
module Posts
class EditPage < BasePage
include Capybara::DSL
end
end
end
12 changes: 12 additions & 0 deletions spec/page_objects/base_object.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# frozen_string_literal: true

class BaseObject
include Capybara::DSL

attr_reader :element, :selector

def initialize(selector:)
@selector = selector
@element = find(selector)
end
end
17 changes: 17 additions & 0 deletions spec/page_objects/base_page.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# frozen_string_literal: true

class BasePage
include Capybara::DSL

attr_reader :path

def initialize(path:)
@path = path
end

def load = visit(path)

def lookup_editor(editor_container:)
@editor = Shared::TrumbowygEditor.new(editor_container)
end
end
35 changes: 35 additions & 0 deletions spec/page_objects/shared/html_editor.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# frozen_string_literal: true

module Shared
class HtmlEditor < BaseObject
def content_element
raise NotImplementedError
end

def clear
select_all
content_element.send_keys(:delete)
self
end

# @return [self]
def open_dropdown
raise NotImplementedError
end

def select_all
content_element.send_keys([:control, "a"])
self
end

def toolbar_control(control, ...)
send(:"toggle_#{control}", ...)
self
end

def <<(content)
content_element.send_keys(content)
self
end
end
end
26 changes: 26 additions & 0 deletions spec/page_objects/shared/trumbowyg_editor.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# frozen_string_literal: true

module Shared
class TrumbowygEditor < HtmlEditor
attr_reader :editor_selector

def initialize(container)
@editor_selector = "#{container} .trumbowyg-box"
super(selector: editor_selector)
end

def content = content_element['innerHTML']

def content_element
@content_element ||= find("#{editor_selector} [contenteditable]")
end

def toggle_bold = find("#{editor_selector} .trumbowyg-strong-button").click

def toggle_delete = find("#{editor_selector} .trumbowyg-del-button").click

def toggle_italic = find("#{editor_selector} .trumbowyg-em-button").click

def toggle_underline = find("#{editor_selector} .trumbowyg-underline-button").click
end
end
8 changes: 5 additions & 3 deletions spec/rails_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

require_relative 'spec_helper'

require 'zeitwerk'
loader = Zeitwerk::Loader.new
loader.push_dir("#{__dir__}/page_objects")
loader.setup

ENV['RAILS_ENV'] = 'test'

require File.expand_path('dummy/config/environment.rb', __dir__)
Expand All @@ -10,7 +15,6 @@

require 'rspec/rails'
require 'capybara/rails'
require 'rspec/retry'

Dir[File.expand_path('support/**/*.rb', __dir__)].each { |f| require_relative f }

Expand All @@ -37,8 +41,6 @@
config.use_instantiated_fixtures = false
config.render_views = false

config.default_retry_count = 2

config.before(:suite) do
intro = ('-' * 80)
intro << "\n"
Expand Down
10 changes: 10 additions & 0 deletions spec/support/string_clean_multiline.rb
Original file line number Diff line number Diff line change
@@ -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
131 changes: 94 additions & 37 deletions spec/system/trumbowyg_editor_spec.rb
Original file line number Diff line number Diff line change
@@ -1,66 +1,123 @@
# frozen_string_literal: true

using StringCleanMultiline

RSpec.describe 'Trumbowyg editor' do
let(:author) { Author.create!(email: 'some_email@example.com', name: 'John Doe', age: 30) }
let(:post) do
Post.create!(title: 'Test', author: author, summary: 'Some content!', description: 'Some content...')
end

before do
post
Post.create!(title: 'Test', author: author, description: '<p>Some content</p>', summary: '<p>Post summary</p>')
end

after do
Post.delete_all
author.delete
end
let(:submit_button) { find('#post_submit_action [type="submit"]') }

context 'with a Trumbowyg editor' do
it 'initialize the editor', :aggregate_failures do
visit "/admin/posts/#{post.id}/edit"

%w[bold italic underline link justifyRight].each do |button|
expect(page).to have_css(".trumbowyg button.trumbowyg-#{button}-button")
end
expect(page).to have_css('#post_description[data-aa-trumbowyg]', visible: :hidden)
expect(page).to have_css('#post_description_input .trumbowyg-editor', text: 'Some content...')
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-trumbowyg]', visible: :hidden) }

it 'adds some text to the summary', :aggregate_failures do
visit "/admin/posts/#{post.id}/edit"
before do
edit_page.load
end

find('#post_summary_input .trumbowyg-editor').base.send_keys('More text')
find('[type="submit"]').click
it 'initializes the editor', :aggregate_failures do
expect(editor.content_element).to be_present
expect(editor.content).to eq('<p>Some content</p>')
expect(input_field.value).to eq('<p>Some content</p>')
end

expect(page).to have_content('was successfully updated')
expect(post.reload.summary).to eq '<p>Some content!More text</p>'
it 'edits some content using the editor' do
editor << :return << 'More content'
editor.toggle_bold
editor << 'Some bold'
editor.toggle_italic
editor << 'Some italic'
editor.toggle_underline
editor << 'Some underline'

expect(editor.content).to eq <<~HTML.clean_multiline
<p>Some content</p>
<p>More content<strong>Some bold<em>Some italic<u>Some underline</u></em></strong></p>
HTML
end

it 'adds right aligned text to the summary', :aggregate_failures do
visit "/admin/posts/#{post.id}/edit"
it 'updates the field when submitting', :aggregate_failures do
editor.toggle_bold
editor << 'More content'

find('#post_summary_input .trumbowyg-button-pane .trumbowyg-justifyRight-button').click
find('[type="submit"]').click
before = '<p>Some content</p>'
after = '<p><strong>More content</strong>Some content</p>'
expect { submit_button.click }.to change { post.reload.description }.from(before).to(after)

expect(page).to have_content('was successfully updated')
expect(post.reload.summary).to match /text-align: right.*Some content/
end
end

context 'with 2 Trumbowyg editors' do
let(:edit_page) do
path = edit_admin_post_path(post)
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') }
let(:first_field) { find('#post_description[data-aa-trumbowyg]', visible: :hidden) }
let(:second_field) { find('#post_summary[data-aa-trumbowyg]', visible: :hidden) }

before do
edit_page.load
end

it 'updates some HTML content for 2 fields', :aggregate_failures do
# Check the initial states
expect(first_editor.content).to eq('<p>Some content</p>')
expect(second_editor.content).to eq('<p>Post summary</p>')

expect(first_field.value).to eq('<p>Some content</p>')
expect(second_field.value).to eq('<p>Post summary</p>')

# Add some content to both the editors
first_editor.toggle_bold
first_editor << 'Some bold'

second_editor.toggle_italic
second_editor << 'Some italic'

# Check that both the fields change
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

context 'with a Trumbowyg editor in a nested resource' do
let(:edit_page) do
path = edit_admin_author_path(author)
Admin::Authors::EditPage.new(path: path)
end
let(:submit_button) { find('#author_submit_action [type="submit"]') }

before do
post
edit_page.load
end

it 'updates some HTML content of a new nested resource', :aggregate_failures do
visit "/admin/authors/#{author.id}/edit"
click_on 'Add New Post'

expect(page).to have_css('.posts.has_many_container .trumbowyg-box', text: 'Some content...')
find('.posts.has_many_container .has_many_add').click
expect(page).to have_css('.posts.has_many_container .trumbowyg-box', count: 2)
first_editor = edit_page.lookup_editor(editor_container: '#author_posts_attributes_0_description_input')
expect(first_editor.content).to eq('<p>Some content</p>')

fill_in('author[posts_attributes][1][title]', with: 'A new post')
find('#author_posts_attributes_1_description_input .trumbowyg-editor').base.send_keys('new post text')
find('[type="submit"]').click
fill_in('author[posts_attributes][1][title]', with: 'Some title')
second_editor = edit_page.lookup_editor(editor_container: '#author_posts_attributes_1_description_input')
second_editor.toggle_delete
second_editor << 'Some deleted'

expect(page).to have_content('was successfully updated')
expect(author.posts.last.description).to eq '<p>new post text</p>'
expect { submit_button.click }.to change(Post, :count).by(1)
expect(Post.last.description).to eq '<p><del>Some deleted</del></p>'
end
end
end