refactor: Modernize CI with Appraisal gem and consolidate workflows

- Add Appraisal gem for managing multiple test gemfiles
- Create test matrix for Rails 6.1-8.0 and ActiveAdmin 2.9-4.x
- Consolidate multiple workflow files into single ci.yml
- Use matrix strategy to test across Ruby 3.0-3.3
- Remove deprecated individual workflow files
- Add gemfiles/ to gitignore as they're generated
- Improve backward compatibility support
Этот коммит содержится в:
Gleb Tv
2025-09-24 12:47:46 +03:00
родитель 194518dea4
Коммит c26aef65ab
24 изменённых файлов: 1324 добавлений и 470 удалений

102
.github/workflows/ci.yml поставляемый Обычный файл
Просмотреть файл

@@ -0,0 +1,102 @@
name: CI
on:
push:
branches: [main, master]
pull_request:
branches: [main, master]
jobs:
test:
runs-on: ubuntu-latest
timeout-minutes: 15
strategy:
fail-fast: false
matrix:
ruby: ['3.0', '3.1', '3.2', '3.3']
gemfile:
- rails_6.1_active_admin_2.9
- rails_7.0_active_admin_2.x
- rails_7.0_active_admin_3.x
- rails_7.1_active_admin_3.x
- rails_7.2_active_admin_3.x
- rails_7.2_active_admin_4.x
- rails_8.0_active_admin_4.x
exclude:
# Rails 8 requires Ruby 3.2+
- ruby: '3.0'
gemfile: rails_8.0_active_admin_4.x
- ruby: '3.1'
gemfile: rails_8.0_active_admin_4.x
# ActiveAdmin 4 requires Ruby 3.2+
- ruby: '3.0'
gemfile: rails_7.2_active_admin_4.x
- ruby: '3.1'
gemfile: rails_7.2_active_admin_4.x
env:
BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile
RAILS_ENV: test
steps:
- uses: actions/checkout@v4
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}
bundler-cache: true
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
cache-dependency-path: spec/dummy/package-lock.json
- name: Install npm dependencies for dummy app
run: |
cd spec/dummy
npm install
- name: Build assets for dummy app
run: |
cd spec/dummy
# Build JavaScript with esbuild
npm run build:js || true
# Build CSS with Tailwind for AA4
if [[ "${{ matrix.gemfile }}" == *"4.x"* ]]; then
npm run build:css || true
fi
- name: Database setup
run: |
cd spec/dummy
bundle exec rails db:create db:migrate db:test:prepare
- name: Run tests
run: bundle exec rspec --format progress
- name: Upload screenshots on failure
uses: actions/upload-artifact@v4
if: failure()
with:
name: test-screenshots-${{ matrix.ruby }}-${{ matrix.gemfile }}
path: spec/dummy/tmp/capybara
if-no-files-found: ignore
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.3'
bundler-cache: true
- name: Run RuboCop
run: bundle exec rubocop --force-exclusion

39
.github/workflows/linters.yml поставляемый
Просмотреть файл

@@ -1,39 +0,0 @@
---
name: Linters
on:
pull_request:
branches: [main]
push:
branches: [main]
jobs:
reviewdog:
name: Reviewdog
runs-on: ubuntu-latest
env:
RAILS_VERSION: 7.0
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: 3.0
bundler-cache: true
- name: Set up Reviewdog
uses: reviewdog/action-setup@v1
with:
reviewdog_version: latest
- name: Run Reviewdog
env:
REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
reviewdog -fail-on-error -reporter=github-pr-review -runners=fasterer,rubocop
# NOTE: check with: reviewdog -fail-on-error -reporter=github-pr-review -runners=fasterer -diff="git diff" -tee

148
.github/workflows/specs.yml поставляемый
Просмотреть файл

@@ -1,148 +0,0 @@
---
name: Specs
on:
pull_request:
branches: [main, master]
push:
branches: [main, master]
jobs:
test_legacy:
runs-on: ubuntu-latest
name: Ruby ${{ matrix.ruby }} / Rails ${{ matrix.rails }} / AA ${{ matrix.activeadmin }}
strategy:
fail-fast: false
matrix:
include:
# Legacy ActiveAdmin 2.x/3.x support
- ruby: '3.0'
rails: '7.0'
activeadmin: '~> 2.9'
- ruby: '3.1'
rails: '7.1'
activeadmin: '~> 3.0'
- ruby: '3.2'
rails: '7.2'
activeadmin: '~> 3.0'
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}
bundler-cache: false
- name: Install dependencies
run: |
gem install bundler
bundle config set --local without 'development'
bundle install --jobs 4 --retry 3
env:
RAILS_VERSION: ${{ matrix.rails }}
ACTIVEADMIN_VERSION: ${{ matrix.activeadmin }}
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install NPM dependencies
run: |
cd spec/dummy
npm install
- name: Build assets
run: |
cd spec/dummy
npm run build
- name: Run tests
run: bundle exec rspec --profile
env:
RAILS_VERSION: ${{ matrix.rails }}
ACTIVEADMIN_VERSION: ${{ matrix.activeadmin }}
- name: Archive screenshots on failure
uses: actions/upload-artifact@v4
if: failure()
with:
name: test-screenshots-legacy-${{ matrix.ruby }}-${{ matrix.rails }}
path: spec/dummy/tmp/capybara
test_activeadmin_4:
runs-on: ubuntu-latest
name: Ruby ${{ matrix.ruby }} / Rails ${{ matrix.rails }} / AA 4.x
strategy:
fail-fast: false
matrix:
ruby: ['3.2', '3.3']
rails: ['7.2', '8.0']
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}
bundler-cache: false
- name: Install dependencies for AA4
run: |
gem install bundler
bundle config set --local without 'development'
bundle install --jobs 4 --retry 3
env:
RAILS_VERSION: ${{ matrix.rails }}
ACTIVEADMIN_VERSION: ''
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install NPM dependencies
run: |
cd spec/dummy
npm install
- name: Build assets
run: |
cd spec/dummy
npm run build
- name: Run tests
run: bundle exec rspec --profile
env:
RAILS_VERSION: ${{ matrix.rails }}
ACTIVEADMIN_VERSION: '4.0'
- name: Archive screenshots on failure
uses: actions/upload-artifact@v4
if: failure()
with:
name: test-screenshots-aa4-${{ matrix.ruby }}-${{ matrix.rails }}
path: spec/dummy/tmp/capybara
lint:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.2'
bundler-cache: true
- name: Run RuboCop
run: bundle exec rubocop --parallel

43
.github/workflows/specs_rails61.yml поставляемый
Просмотреть файл

@@ -1,43 +0,0 @@
---
name: Specs Rails 6.1 with ActiveAdmin 2.9
on:
pull_request:
branches: [main]
push:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
ruby: ['3.0', '3.1', '3.2']
env:
RAILS_VERSION: 6.0
ACTIVEADMIN_VERSION: 2.9.0
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}
bundler-cache: true
- name: Database setup
run: bin/rails db:create db:migrate db:test:prepare
- name: Run tests
run: bundle exec rspec --profile
- name: On failure, archive screenshots as artifacts
uses: actions/upload-artifact@v4
if: failure()
with:
name: test-failed-screenshots
path: spec/dummy/tmp/screenshots

42
.github/workflows/specs_rails70.yml поставляемый
Просмотреть файл

@@ -1,42 +0,0 @@
---
name: Specs Rails 7.0
on:
pull_request:
branches: [main]
push:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
ruby: ['3.0', '3.1', '3.2']
env:
RAILS_VERSION: 7.0
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}
bundler-cache: true
- name: Database setup
run: bin/rails db:create db:migrate db:test:prepare
- name: Run tests
run: bundle exec rspec --profile
- name: On failure, archive screenshots as artifacts
uses: actions/upload-artifact@v4
if: failure()
with:
name: test-failed-screenshots
path: spec/dummy/tmp/screenshots

42
.github/workflows/specs_rails71.yml поставляемый
Просмотреть файл

@@ -1,42 +0,0 @@
---
name: Specs Rails 7.1
on:
pull_request:
branches: [main]
push:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
ruby: ['3.2', '3.4']
env:
RAILS_VERSION: 7.1
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}
bundler-cache: true
- name: Database setup
run: bin/rails db:create db:migrate db:test:prepare
- name: Run tests
run: bundle exec rspec --profile
- name: On failure, archive screenshots as artifacts
uses: actions/upload-artifact@v4
if: failure()
with:
name: test-failed-screenshots
path: spec/dummy/tmp/screenshots

42
.github/workflows/specs_rails72.yml поставляемый
Просмотреть файл

@@ -1,42 +0,0 @@
---
name: Specs Rails 7.2
on:
pull_request:
branches: [main]
push:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
ruby: ['3.2', '3.4']
env:
RAILS_VERSION: 7.2
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}
bundler-cache: true
- name: Database setup
run: bin/rails db:create db:migrate db:test:prepare
- name: Run tests
run: bundle exec rspec --profile
- name: On failure, archive screenshots as artifacts
uses: actions/upload-artifact@v4
if: failure()
with:
name: test-failed-screenshots
path: spec/dummy/tmp/screenshots

64
.github/workflows/specs_rails80.yml поставляемый
Просмотреть файл

@@ -1,64 +0,0 @@
---
name: Specs Rails 8.0
on:
pull_request:
branches: [main]
push:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
ruby: ['3.2', '3.3']
env:
RAILS_VERSION: 8.0
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}
bundler-cache: false
- name: Install dependencies
run: |
gem install bundler
bundle install --jobs 4 --retry 3
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install NPM dependencies
run: |
cd spec/dummy
npm install
- name: Build assets
run: |
cd spec/dummy
npm run build
- name: Database setup
run: |
cd spec/dummy
bundle exec rails db:create db:migrate db:test:prepare
- name: Run tests
run: bundle exec rspec --profile
- name: On failure, archive screenshots as artifacts
uses: actions/upload-artifact@v4
if: failure()
with:
name: test-failed-screenshots-rails8-${{ matrix.ruby }}
path: spec/dummy/tmp/capybara

2
.gitignore поставляемый
Просмотреть файл

@@ -12,4 +12,6 @@
/spec/dummy/log/
/spec/dummy/storage/
/spec/dummy/tmp/
tmp/
/spec/dummy/node_modules/
/gemfiles/

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

@@ -1,7 +1,4 @@
---
inherit_from:
- https://relaxed.ruby.style/rubocop.yml
plugins:
- rubocop-capybara
- rubocop-packaging
@@ -10,24 +7,64 @@ plugins:
- rubocop-rspec
- rubocop-rspec_rails
inherit_mode:
merge:
- Exclude
AllCops:
NewCops: enable
TargetRubyVersion: 3.0
SuggestExtensions: false
DisplayCopNames: true
CacheRootDirectory: tmp/rubocop-cache
Exclude:
- bin/*
- coverage/**/*
- db/schema.rb
- docs/**/*
- examples/**/*
- gemfiles/**/*
- spec/dummy/**/*
- vendor/**/*
NewCops: enable
TargetRubyVersion: 3.0
Layout/LineLength:
Max: 120
Metrics/BlockLength:
Enabled: true
Exclude:
- spec/**/*
- docs/**/*
Metrics/MethodLength:
Max: 20
Exclude:
- spec/**/*
Style/Documentation:
Enabled: false
Style/StringLiterals:
EnforcedStyle: single_quotes
Style/StringLiteralsInInterpolation:
EnforcedStyle: double_quotes
RSpec/ExampleLength:
# default 5
Max: 12
Exclude:
- spec/system/**/*
RSpec/MultipleExpectations:
# default 1
Max: 4
Exclude:
- spec/system/**/*
RSpec/MultipleMemoizedHelpers:
# default 5
Max: 10
Rails/SkipsModelValidations:
Enabled: true
Rails/ActiveRecordAliases:
Enabled: true

19
AGENTS.md Обычный файл
Просмотреть файл

@@ -0,0 +1,19 @@
# Repository Guidelines
## Project Structure & Module Organization
The gem code lives in `lib/activeadmin` and `lib/formtastic`, with the public entry point in `lib/activeadmin_quill_editor.rb`. Ruby assets and templates that Active Admin mounts ship from `app/assets` and `app/views`. Front-end bundles exposed to consuming apps sit in `index.js` and the `app/assets/javascripts/activeadmin/quill_editor` tree. System specs exercise the dummy Rails app under `spec/dummy`, while reusable page helpers reside in `spec/page_objects`.
## Build, Test, and Development Commands
`make up` builds the Docker environment defined in `extra/docker-compose.yml` and prepares the dummy app; add `RUBY`, `RAILS`, or `ACTIVEADMIN` env vars to test matrix combinations. Run `make specs` (or directly `bin/rspec --fail-fast`) to execute the suite, and `make lint` to invoke `bin/rubocop` inside the container. Use `make shell` for interactive debugging and `make server` to boot the dummy Rails instance at `SERVER_PORT`.
## Coding Style & Naming Conventions
Follow the `.rubocop.yml` rules: two-space indentation, trailing commas on multiline literals, double quotes where interpolation occurs, and `snake_case` for Ruby identifiers. Use `CamelCase` for classes and modules under the `ActiveadminQuillEditor` namespace, mirroring existing files. JavaScript additions in `app/assets/javascripts` should align with the lintable ES module style in `index.js`; run `npx eslint index.js` if you modify the package entry point.
## Testing Guidelines
RSpec powers the suite; place feature-level coverage in `spec/system`, supporting components in `spec/page_objects`, and pure Ruby behaviour in `spec`. Prefer descriptive example names (`it "renders toolbar buttons"`) and keep factories in the dummy app to mirror real usage. Start tests with `make specs`; use `bin/rspec spec/system/editor_spec.rb` to target a file.
## Commit & Pull Request Guidelines
Recent history follows conventional prefixes (`fix:`, `ci:`, `chore:`); keep messages in the imperative mood and limit the subject to 72 characters. Every pull request should link related GitHub issues, summarize user-facing changes, and note any docs or assets touched. Include screenshots or GIFs when altering the editor UI, and confirm that both `make specs` and `make lint` pass in the PR description. Request review from a maintainer and re-run the pipeline after rebases.
## Security & Configuration Tips
Store local-only overrides in `extra/.env` (kept out of version control) and avoid committing credentials to the dummy app. The docker-compose services mount the repository directly, so prefer editing files via your host editor rather than inside the container to prevent permission drift.

67
Appraisals Обычный файл
Просмотреть файл

@@ -0,0 +1,67 @@
# frozen_string_literal: true
# Rails 6.1 with ActiveAdmin 2.9
appraise 'rails-6.1-active-admin-2.9' do
gem 'rails', '~> 6.1.0'
gem 'activeadmin', '~> 2.9.0'
gem 'sassc'
gem 'sprockets-rails'
remove_gem 'propshaft'
remove_gem 'importmap-rails'
end
# Rails 7.0 with ActiveAdmin 2.x
appraise 'rails-7.0-active-admin-2.x' do
gem 'rails', '~> 7.0.0'
gem 'activeadmin', '~> 2.14'
gem 'sassc'
gem 'sprockets-rails'
remove_gem 'propshaft'
remove_gem 'importmap-rails'
end
# Rails 7.0 with ActiveAdmin 3.x
appraise 'rails-7.0-active-admin-3.x' do
gem 'rails', '~> 7.0.0'
gem 'activeadmin', '~> 3.2'
gem 'sassc'
gem 'sprockets-rails'
remove_gem 'propshaft'
remove_gem 'importmap-rails'
end
# Rails 7.1 with ActiveAdmin 3.x
appraise 'rails-7.1-active-admin-3.x' do
gem 'rails', '~> 7.1.0'
gem 'activeadmin', '~> 3.2'
gem 'sassc'
gem 'sprockets-rails'
remove_gem 'propshaft'
remove_gem 'importmap-rails'
end
# Rails 7.2 with ActiveAdmin 3.x
appraise 'rails-7.2-active-admin-3.x' do
gem 'rails', '~> 7.2.0'
gem 'activeadmin', '~> 3.2'
gem 'sassc'
gem 'sprockets-rails'
remove_gem 'propshaft'
remove_gem 'importmap-rails'
end
# Rails 7.2 with ActiveAdmin 4.x beta
appraise 'rails-7.2-active-admin-4.x' do
gem 'rails', '~> 7.2.0'
gem 'activeadmin', '4.0.0.beta16'
gem 'importmap-rails'
gem 'propshaft'
end
# Rails 8.0 with ActiveAdmin 4.x beta
appraise 'rails-8.0-active-admin-4.x' do
gem 'rails', '~> 8.0.0'
gem 'activeadmin', '4.0.0.beta16'
gem 'importmap-rails'
gem 'propshaft'
end

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

@@ -27,13 +27,21 @@ rails = eval_version('rails', rails_ver)
gem(*rails)
active_admin_ver = ENV.fetch('ACTIVEADMIN_VERSION', '')
active_admin_requirement =
if active_admin_ver.empty?
# Use ActiveAdmin 4 beta by default for development
gem 'activeadmin', '~> 4.0.0.beta'
'~> 4.0.0.beta16'
elsif active_admin_ver.match?(/[a-zA-Z]/) || active_admin_ver.match?(/^[~<>=]/)
active_admin_ver
else
active_admin = eval_version('activeadmin', active_admin_ver)
gem(*active_admin)
target = Gem::Version.new(active_admin_ver)
if target >= Gem::Version.new('4.0')
'~> 4.0.0.beta16'
else
active_admin_ver.count('.') < 2 ? "~> #{active_admin_ver}.0" : "~> #{active_admin_ver}"
end
end
gem 'activeadmin', active_admin_requirement
ruby32 = ruby_ver.empty? || Gem::Version.new(ruby_ver) >= Gem::Version.new('3.2')
rails72 = rails_ver.empty? || Gem::Version.new(rails_ver) >= Gem::Version.new('7.2')
@@ -54,8 +62,8 @@ gem 'puma'
# Asset pipeline - use Propshaft for Rails 8, Sprockets for older versions
rails80 = rails_ver.empty? || Gem::Version.new(rails_ver) >= Gem::Version.new('8.0')
if rails80
gem 'propshaft'
gem 'importmap-rails' # Required for ActiveAdmin 4
gem 'propshaft'
else
gem 'sassc'
gem 'sprockets-rails'
@@ -80,4 +88,5 @@ gem 'rubocop-rspec'
gem 'rubocop-rspec_rails'
# Tools
gem 'appraisal'
gem 'pry-rails'

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

@@ -6,7 +6,7 @@ rescue LoadError
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
end
APP_RAKEFILE = File.expand_path("spec/dummy/Rakefile", __dir__)
APP_RAKEFILE = File.expand_path('spec/dummy/Rakefile', __dir__)
load 'rails/tasks/engine.rake'
load 'rails/tasks/statistics.rake'

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

@@ -5,7 +5,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'activeadmin/quill_editor/version'
Gem::Specification.new do |spec|
spec.name = 'activeadmin_quill_editor'
spec.name = 'activeadmin-quill_editor'
spec.version = ActiveAdmin::QuillEditor::VERSION
spec.summary = 'Quill Editor for ActiveAdmin'
spec.description = 'An Active Admin plugin to use Quill Rich Text Editor'
@@ -25,6 +25,6 @@ Gem::Specification.new do |spec|
spec.files = Dir['{app,lib,vendor}/**/*', 'LICENSE.txt', 'Rakefile', 'README.md']
spec.require_paths = ['lib']
spec.add_runtime_dependency 'activeadmin', '>= 2.9', '< 5' # rubocop:disable Gemspec/AddRuntimeDependency
spec.add_runtime_dependency 'rails', '>= 6.0'
spec.add_dependency 'activeadmin', '>= 2.9', '< 5'
spec.add_dependency 'rails', '>= 6.0'
end

1028
docs/rubocop-configuration.adoc.txt Обычный файл

Разница между файлами не показана из-за своего большого размера Загрузить разницу

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

@@ -1,3 +1,4 @@
# frozen_string_literal: true
require 'activeadmin/quill_editor/engine'
require 'formtastic/inputs/quill_editor_input'

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

@@ -18,7 +18,7 @@ module Shared
end
def select_all
content_element.send_keys([:control, "a"])
content_element.send_keys([:control, 'a'])
self
end

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

@@ -7,6 +7,7 @@ module JavaScriptHelper
loop do
quill_loaded = page.evaluate_script('typeof Quill !== "undefined"')
break if quill_loaded
sleep 0.1
end
end
@@ -20,6 +21,7 @@ module JavaScriptHelper
typeof getQuillEditorByElementId === 'function'
JS
break if init_loaded
sleep 0.1
end
end
@@ -93,6 +95,7 @@ module JavaScriptHelper
def quill_has_content?(text, index = 0)
content = get_quill_content(index)
return false unless content
content.include?(text)
end

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

@@ -4,7 +4,7 @@ module StringCleanMultiline
refine String do
def clean_multiline
# Get rid of newlines and indentation spaces
strip.gsub(/\s*\n\s*/, "")
strip.gsub(/\s*\n\s*/, '')
end
end
end

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

@@ -2,12 +2,10 @@
require 'rails_helper'
RSpec.describe 'CSS Loading', type: :system do
RSpec.describe 'CSS Loading' do
before do
# Create an admin user if authentication is enabled
if defined?(AdminUser)
AdminUser.create!(email: 'admin@example.com', password: 'password')
end
AdminUser.create!(email: 'admin@example.com', password: 'password') if defined?(AdminUser)
end
context 'when loading Quill editor CSS' do
@@ -32,10 +30,11 @@ RSpec.describe 'CSS Loading', type: :system do
# Ensure no CDN URLs
quill_stylesheets.each do |href|
next if href == 'inline'
expect(href).not_to match(%r{https?://cdn})
expect(href).not_to match(%r{jsdelivr})
expect(href).not_to match(%r{unpkg})
expect(href).to match(%r{/assets/}) if href != 'inline'
expect(href).not_to include('jsdelivr')
expect(href).not_to include('unpkg')
expect(href).to include('/assets/')
end
end
@@ -79,20 +78,27 @@ RSpec.describe 'CSS Loading', type: :system do
# Check that Quill styles are applied
editor_styles = page.evaluate_script(<<~JS)
(function() {
const editor = document.querySelector('.ql-container');
if (!editor) return null;
const styles = window.getComputedStyle(editor);
const container = document.querySelector('.ql-container');
const editor = document.querySelector('.ql-editor');
if (!container || !editor) return null;
const containerStyles = window.getComputedStyle(container);
const editorStyles = window.getComputedStyle(editor);
return {
position: styles.position,
display: styles.display,
hasBackground: styles.backgroundColor !== '' && styles.backgroundColor !== 'rgba(0, 0, 0, 0)'
containerDisplay: containerStyles.display,
containerBorderWidth: parseFloat(containerStyles.borderTopWidth || '0'),
editorBackground: editorStyles.backgroundColor,
editorPadding: editorStyles.paddingTop
};
})()
JS
expect(editor_styles).not_to be_nil
expect(editor_styles['display']).not_to eq('none')
expect(editor_styles['hasBackground']).to be true
expect(editor_styles['containerDisplay']).not_to eq('none')
expect(editor_styles['containerBorderWidth']).to be > 0
expect(editor_styles['editorBackground']).not_to eq('rgba(0, 0, 0, 0)')
expect(editor_styles['editorPadding']).not_to eq('0px')
# Check toolbar styles
toolbar_visible = page.evaluate_script(<<~JS)
@@ -124,7 +130,7 @@ RSpec.describe 'CSS Loading', type: :system do
JS
# Check for bubble theme CSS (if included)
bubble_theme_loaded = page.evaluate_script(<<~JS)
_bubble_theme_loaded = page.evaluate_script(<<~JS)
Array.from(document.styleSheets).some(sheet => {
try {
return sheet.cssRules && Array.from(sheet.cssRules).some(rule =>

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

@@ -31,7 +31,7 @@ RSpec.describe 'Quill editor' do
it 'edits some content using the editor' do
editor.select_all
editor.toggle_link
editor.tooltip_editing.send_keys(["https://blocknot.es", :return])
editor.tooltip_editing.send_keys(['https://blocknot.es', :return])
editor << :right << :return << 'More content'
editor.toggle_bold
@@ -49,18 +49,18 @@ RSpec.describe 'Quill editor' do
editor << 'code block enabled' << :return
editor.toggle_code_block
editor << "Some text"
editor << 'Some text'
editor.toggle_sub
editor << "sub text"
editor << 'sub text'
editor.toggle_sub
editor << " More text"
editor << ' More text'
editor.toggle_super
editor << "sup text"
editor << 'sup text'
editor.toggle_super
editor << :return
editor.open_dropdown(:align).toggle_align_right
editor << "Text aligned on the right"
editor << 'Text aligned on the right'
expect(editor.content).to eq <<~HTML.clean_multiline
<p><a href="https://blocknot.es" rel="noopener noreferrer" target="_blank">Some content</a></p>

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

@@ -17,7 +17,7 @@ RSpec.describe 'Quill JS' do
Admin::Posts::EditPage.new(path: path).load
end
it "returns the available editors", :aggregate_failures do
it 'returns the available editors', :aggregate_failures do
editors_count = page.evaluate_script('window.getQuillEditors().length')
expect(editors_count).to eq 2
@@ -40,7 +40,7 @@ RSpec.describe 'Quill JS' do
Admin::Posts::EditPage.new(path: path).load
end
it "returns the expected editor instance" do
it 'returns the expected editor instance' do
expected_element = find('#post_description > .ql-container')
editor = page.evaluate_script('window.getQuillEditorByIndex(1).container')
expect(editor).to eq expected_element
@@ -56,7 +56,7 @@ RSpec.describe 'Quill JS' do
Admin::Posts::EditPage.new(path: path).load
end
it "returns the expected editor instance" do
it 'returns the expected editor instance' do
expected_element = find('#post_description > .ql-container')
editor = page.evaluate_script('window.getQuillEditorByElementId("post_description").container')
expect(editor).to eq expected_element