capybara_active_admin 0.3.3 → 1.0.0
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.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +88 -0
- data/.github/workflows/codeql.yml +104 -0
- data/.gitignore +1 -0
- data/CHANGELOG.md +19 -0
- data/Gemfile +12 -19
- data/README.md +7 -1
- data/Rakefile +1 -11
- data/capybara_active_admin.gemspec +2 -2
- data/lib/capybara/active_admin/actions/form.rb +1 -1
- data/lib/capybara/active_admin/actions/layout.rb +3 -3
- data/lib/capybara/active_admin/actions/table.rb +12 -0
- data/lib/capybara/active_admin/finders/form.rb +7 -0
- data/lib/capybara/active_admin/finders/layout.rb +18 -7
- data/lib/capybara/active_admin/finders/table.rb +17 -0
- data/lib/capybara/active_admin/matchers/attributes_table.rb +2 -2
- data/lib/capybara/active_admin/matchers/form.rb +42 -7
- data/lib/capybara/active_admin/matchers/layout.rb +33 -7
- data/lib/capybara/active_admin/matchers/table.rb +39 -3
- data/lib/capybara/active_admin/selectors/attributes_table.rb +1 -1
- data/lib/capybara/active_admin/selectors/form.rb +7 -1
- data/lib/capybara/active_admin/selectors/table.rb +23 -3
- data/lib/capybara/active_admin/version.rb +1 -1
- metadata +14 -11
- data/.travis.yml +0 -45
- data/yarn.lock +0 -7947
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7734f257fe31b75bea9782d9c0cd24bc8591a0c05a9db0a0b7a6f264d8515b20
|
|
4
|
+
data.tar.gz: 5270545aa73089ac413bd1e1e250da449f795ffde996259b6f8d14c49476d257
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 88319fec5e984e419f0dc3c130a49907f98aec9fd7f62560acdc276f10e2c670772f44198bf81e1439dc14bf3f0bf0a306b1aef22059427c14fdbdffe3a7c47d
|
|
7
|
+
data.tar.gz: 694336b60366c1a9ae9ca61e7df39370fd2e86eb242850c93faf0689663ebc827bd448e49f5fa238a7bb78377dc29fcdbfa4cabe2b9ee1081e4bdc039fe64b5b
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
on:
|
|
3
|
+
pull_request:
|
|
4
|
+
push:
|
|
5
|
+
branches: [master]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
pages: write
|
|
10
|
+
id-token: write
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
test:
|
|
14
|
+
name: Ruby ${{ matrix.ruby }} / Rails ${{ matrix.rails }} / AA ${{ matrix.activeadmin }}
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
strategy:
|
|
17
|
+
fail-fast: false
|
|
18
|
+
matrix:
|
|
19
|
+
ruby: ['3.3', '3.4', '4.0']
|
|
20
|
+
rails: ['~> 7.2.0', '~> 8.0.0', '~> 8.1.0']
|
|
21
|
+
activeadmin: ['~> 3.2', '~> 3.3', '~> 3.4', '~> 3.5']
|
|
22
|
+
env:
|
|
23
|
+
RAILS_VERSION: ${{ matrix.rails }}
|
|
24
|
+
ACTIVE_ADMIN_VERSION: ${{ matrix.activeadmin }}
|
|
25
|
+
steps:
|
|
26
|
+
- uses: actions/checkout@v4
|
|
27
|
+
- uses: ruby/setup-ruby@v1
|
|
28
|
+
with:
|
|
29
|
+
ruby-version: ${{ matrix.ruby }}
|
|
30
|
+
bundler-cache: true
|
|
31
|
+
- name: Run tests
|
|
32
|
+
run: bundle exec rspec spec
|
|
33
|
+
|
|
34
|
+
- name: Generate badge.json
|
|
35
|
+
if: matrix.ruby == '4.0' && matrix.rails == '~> 8.1.0' && matrix.activeadmin == '~> 3.5'
|
|
36
|
+
run: |
|
|
37
|
+
LAST_RUN="coverage/.last_run.json"
|
|
38
|
+
if [ ! -f "$LAST_RUN" ]; then
|
|
39
|
+
mkdir -p badge
|
|
40
|
+
echo '{"schemaVersion":1,"label":"coverage","message":"unknown","color":"lightgrey"}' > badge/badge.json
|
|
41
|
+
exit 0
|
|
42
|
+
fi
|
|
43
|
+
PERCENT=$(ruby -rjson -e "puts JSON.parse(File.read('$LAST_RUN')).dig('result','line').round(1)")
|
|
44
|
+
PERCENT_NUM=$(ruby -rjson -e "puts JSON.parse(File.read('$LAST_RUN')).dig('result','line')")
|
|
45
|
+
if ruby -e "exit(($PERCENT_NUM >= 90) ? 0 : 1)"; then COLOR="brightgreen"
|
|
46
|
+
elif ruby -e "exit(($PERCENT_NUM >= 75) ? 0 : 1)"; then COLOR="green"
|
|
47
|
+
elif ruby -e "exit(($PERCENT_NUM >= 60) ? 0 : 1)"; then COLOR="yellow"
|
|
48
|
+
else COLOR="red"; fi
|
|
49
|
+
mkdir -p badge
|
|
50
|
+
echo "{\"schemaVersion\":1,\"label\":\"coverage\",\"message\":\"${PERCENT}%\",\"color\":\"${COLOR}\"}" > badge/badge.json
|
|
51
|
+
|
|
52
|
+
- name: Upload badge artifact
|
|
53
|
+
if: matrix.ruby == '4.0' && matrix.rails == '~> 8.1.0' && matrix.activeadmin == '~> 3.5'
|
|
54
|
+
uses: actions/upload-artifact@v4
|
|
55
|
+
with:
|
|
56
|
+
name: coverage-badge
|
|
57
|
+
path: badge
|
|
58
|
+
|
|
59
|
+
deploy-coverage:
|
|
60
|
+
needs: test
|
|
61
|
+
if: github.ref == 'refs/heads/master' && github.event_name == 'push'
|
|
62
|
+
runs-on: ubuntu-latest
|
|
63
|
+
environment:
|
|
64
|
+
name: github-pages
|
|
65
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
66
|
+
|
|
67
|
+
steps:
|
|
68
|
+
- uses: actions/checkout@v4
|
|
69
|
+
with:
|
|
70
|
+
ref: gh-pages
|
|
71
|
+
|
|
72
|
+
- name: Download coverage badge
|
|
73
|
+
uses: actions/download-artifact@v4
|
|
74
|
+
with:
|
|
75
|
+
name: coverage-badge
|
|
76
|
+
path: .
|
|
77
|
+
|
|
78
|
+
- name: Setup Pages
|
|
79
|
+
uses: actions/configure-pages@v5
|
|
80
|
+
|
|
81
|
+
- name: Upload Pages artifact
|
|
82
|
+
uses: actions/upload-pages-artifact@v3
|
|
83
|
+
with:
|
|
84
|
+
path: .
|
|
85
|
+
|
|
86
|
+
- name: Deploy to GitHub Pages
|
|
87
|
+
id: deployment
|
|
88
|
+
uses: actions/deploy-pages@v4
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# For most projects, this workflow file will not need changing; you simply need
|
|
2
|
+
# to commit it to your repository.
|
|
3
|
+
#
|
|
4
|
+
# You may wish to alter this file to override the set of languages analyzed,
|
|
5
|
+
# or to provide custom queries or build logic.
|
|
6
|
+
#
|
|
7
|
+
# ******** NOTE ********
|
|
8
|
+
# We have attempted to detect the languages in your repository. Please check
|
|
9
|
+
# the `language` matrix defined below to confirm you have the correct set of
|
|
10
|
+
# supported CodeQL languages.
|
|
11
|
+
#
|
|
12
|
+
name: "CodeQL Advanced"
|
|
13
|
+
|
|
14
|
+
on:
|
|
15
|
+
push:
|
|
16
|
+
branches: [ "master" ]
|
|
17
|
+
pull_request:
|
|
18
|
+
branches: [ "master" ]
|
|
19
|
+
schedule:
|
|
20
|
+
- cron: '38 15 * * 0'
|
|
21
|
+
|
|
22
|
+
jobs:
|
|
23
|
+
analyze:
|
|
24
|
+
name: Analyze (${{ matrix.language }})
|
|
25
|
+
# Runner size impacts CodeQL analysis time. To learn more, please see:
|
|
26
|
+
# - https://gh.io/recommended-hardware-resources-for-running-codeql
|
|
27
|
+
# - https://gh.io/supported-runners-and-hardware-resources
|
|
28
|
+
# - https://gh.io/using-larger-runners (GitHub.com only)
|
|
29
|
+
# Consider using larger runners or machines with greater resources for possible analysis time improvements.
|
|
30
|
+
runs-on: 'ubuntu-latest'
|
|
31
|
+
permissions:
|
|
32
|
+
# required for all workflows
|
|
33
|
+
security-events: write
|
|
34
|
+
|
|
35
|
+
# required to fetch internal or private CodeQL packs
|
|
36
|
+
packages: read
|
|
37
|
+
|
|
38
|
+
# only required for workflows in private repositories
|
|
39
|
+
actions: read
|
|
40
|
+
contents: read
|
|
41
|
+
|
|
42
|
+
strategy:
|
|
43
|
+
fail-fast: false
|
|
44
|
+
matrix:
|
|
45
|
+
include:
|
|
46
|
+
- language: actions
|
|
47
|
+
build-mode: none
|
|
48
|
+
- language: ruby
|
|
49
|
+
build-mode: none
|
|
50
|
+
# CodeQL supports the following values keywords for 'language': 'actions', 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'rust', 'swift'
|
|
51
|
+
# Use `c-cpp` to analyze code written in C, C++ or both
|
|
52
|
+
# Use 'java-kotlin' to analyze code written in Java, Kotlin or both
|
|
53
|
+
# Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both
|
|
54
|
+
# To learn more about changing the languages that are analyzed or customizing the build mode for your analysis,
|
|
55
|
+
# see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning.
|
|
56
|
+
# If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how
|
|
57
|
+
# your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
|
|
58
|
+
steps:
|
|
59
|
+
- name: Checkout repository
|
|
60
|
+
uses: actions/checkout@v4
|
|
61
|
+
|
|
62
|
+
# Add any setup steps before running the `github/codeql-action/init` action.
|
|
63
|
+
# This includes steps like installing compilers or runtimes (`actions/setup-node`
|
|
64
|
+
# or others). This is typically only required for manual builds.
|
|
65
|
+
# - name: Setup runtime (example)
|
|
66
|
+
# uses: actions/setup-example@v1
|
|
67
|
+
|
|
68
|
+
# Initializes the CodeQL tools for scanning.
|
|
69
|
+
- name: Initialize CodeQL
|
|
70
|
+
uses: github/codeql-action/init@v4
|
|
71
|
+
with:
|
|
72
|
+
languages: ${{ matrix.language }}
|
|
73
|
+
build-mode: ${{ matrix.build-mode }}
|
|
74
|
+
config: |
|
|
75
|
+
paths-ignore:
|
|
76
|
+
- '**/spec/**'
|
|
77
|
+
# If you wish to specify custom queries, you can do so here or in a config file.
|
|
78
|
+
# By default, queries listed here will override any specified in a config file.
|
|
79
|
+
# Prefix the list here with "+" to use these queries and those in the config file.
|
|
80
|
+
|
|
81
|
+
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
|
82
|
+
# queries: security-extended,security-and-quality
|
|
83
|
+
|
|
84
|
+
# If the analyze step fails for one of the languages you are analyzing with
|
|
85
|
+
# "We were unable to automatically build your code", modify the matrix above
|
|
86
|
+
# to set the build mode to "manual" for that language. Then modify this step
|
|
87
|
+
# to build your code.
|
|
88
|
+
# ℹ️ Command-line programs to run using the OS shell.
|
|
89
|
+
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
|
90
|
+
- name: Run manual build steps
|
|
91
|
+
if: matrix.build-mode == 'manual'
|
|
92
|
+
shell: bash
|
|
93
|
+
run: |
|
|
94
|
+
echo 'If you are using a "manual" build mode for one or more of the' \
|
|
95
|
+
'languages you are analyzing, replace this with the commands to build' \
|
|
96
|
+
'your code, for example:'
|
|
97
|
+
echo ' make bootstrap'
|
|
98
|
+
echo ' make release'
|
|
99
|
+
exit 1
|
|
100
|
+
|
|
101
|
+
- name: Perform CodeQL Analysis
|
|
102
|
+
uses: github/codeql-action/analyze@v4
|
|
103
|
+
with:
|
|
104
|
+
category: "/language:${{matrix.language}}"
|
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [1.0.0] - 2026-04-09
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
- `have_fields_date_range` matcher for date range filter fields
|
|
13
|
+
- `within_table_footer` finder for table footer row
|
|
14
|
+
- `click_table_scope` action for clicking table scope links
|
|
15
|
+
- `table_header_selector` selector now accepts text and options (sortable, sort_direction, column)
|
|
16
|
+
- `have_table_header` matcher for table header columns
|
|
17
|
+
- `find_table_header` finder for table header columns
|
|
18
|
+
- `click_table_header` action for clicking sortable table headers
|
|
19
|
+
- `find_action_item` finder for action item elements
|
|
20
|
+
- `have_action_item_link` matcher for action item links (with optional href)
|
|
21
|
+
- `within_action_item_dropdown` finder for action item dropdown menu
|
|
22
|
+
- `have_status_tag` matcher for status tag elements
|
|
23
|
+
|
|
24
|
+
### Changed
|
|
25
|
+
- `within_sidebar` now scopes within the sidebar section directly using `ancestor`
|
|
26
|
+
- `have_table_scope` now accepts an optional title as first positional argument and `selected:` keyword arg
|
|
27
|
+
|
|
9
28
|
## [0.3.3] - 2020-04-17
|
|
10
29
|
### Changed
|
|
11
30
|
- `batch_action_selector`, `click_batch_action` finds element by link text
|
data/Gemfile
CHANGED
|
@@ -1,23 +1,16 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
1
|
source 'https://rubygems.org'
|
|
4
|
-
|
|
5
|
-
# Specify your gem's dependencies in capybara_active_admin.gemspec
|
|
6
2
|
gemspec
|
|
7
3
|
|
|
8
|
-
gem '
|
|
9
|
-
gem '
|
|
10
|
-
|
|
11
|
-
gem '
|
|
12
|
-
gem 'puma'
|
|
13
|
-
gem 'rake', '~> 12.0'
|
|
14
|
-
gem 'rspec-rails', '~> 4.0'
|
|
15
|
-
gem 'rubocop', '~> 0.81.0', require: false
|
|
16
|
-
gem 'system_test_html_screenshots', require: false
|
|
17
|
-
gem 'yard', require: false
|
|
4
|
+
gem 'activeadmin', ENV.fetch('ACTIVE_ADMIN_VERSION', '~> 3.2')
|
|
5
|
+
gem 'rails', ENV.fetch('RAILS_VERSION', '~> 7.1.0')
|
|
6
|
+
gem 'sprockets-rails'
|
|
7
|
+
gem 'sassc-rails'
|
|
18
8
|
|
|
19
|
-
|
|
20
|
-
gem '
|
|
21
|
-
gem '
|
|
22
|
-
gem '
|
|
23
|
-
gem '
|
|
9
|
+
group :test do
|
|
10
|
+
gem 'capybara'
|
|
11
|
+
gem 'cuprite'
|
|
12
|
+
gem 'puma'
|
|
13
|
+
gem 'rspec-rails', '~> 6.0'
|
|
14
|
+
gem 'simplecov', require: false
|
|
15
|
+
gem 'sqlite3', '~> 2.0'
|
|
16
|
+
end
|
data/README.md
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
# Capybara Active Admin
|
|
2
2
|
|
|
3
|
-
[](https://github.com/activeadmin-plugins/capybara_active_admin/actions/workflows/ci.yml)
|
|
4
|
+
[](https://activeadmin-plugins.github.io/capybara_active_admin/)
|
|
5
|
+
[](https://badge.fury.io/rb/capybara_active_admin)
|
|
6
|
+
[](https://rubygems.org/gems/capybara_active_admin)
|
|
7
|
+
[](https://opensource.org/licenses/MIT)
|
|
4
8
|
|
|
5
9
|
Capybara DSL for fast and easy testing Active Admin applications.
|
|
6
10
|
|
|
@@ -24,6 +28,8 @@ Or install it yourself as:
|
|
|
24
28
|
|
|
25
29
|
$ gem install capybara_active_admin
|
|
26
30
|
|
|
31
|
+
**Note: `capybara_active_admin` should be required after `capybara`.**
|
|
32
|
+
|
|
27
33
|
## Usage
|
|
28
34
|
|
|
29
35
|
`rails_helper.rb`
|
data/Rakefile
CHANGED
|
@@ -2,17 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
require 'bundler/gem_tasks'
|
|
4
4
|
require 'rspec/core/rake_task'
|
|
5
|
-
require 'rubocop/rake_task'
|
|
6
|
-
require 'yard'
|
|
7
|
-
require 'yard/rake/yardoc_task'
|
|
8
5
|
|
|
9
6
|
RSpec::Core::RakeTask.new(:spec)
|
|
10
|
-
RuboCop::RakeTask.new(:rubocop)
|
|
11
|
-
YARD::Rake::YardocTask.new(:yard) do |task|
|
|
12
|
-
task.options += [
|
|
13
|
-
%(--output-dir=./docs/.vuepress/public/api/),
|
|
14
|
-
%(--title=Capybara Active Admin API Reference)
|
|
15
|
-
]
|
|
16
|
-
end
|
|
17
7
|
|
|
18
|
-
task default: [:
|
|
8
|
+
task default: [:spec]
|
|
@@ -12,7 +12,7 @@ Gem::Specification.new do |spec|
|
|
|
12
12
|
spec.description = 'Capybara DSL for fast and easy testing Active Admin applications.'
|
|
13
13
|
spec.homepage = 'https://github.com/active_admin_plugins/capybara_active_admin'
|
|
14
14
|
spec.license = 'MIT'
|
|
15
|
-
spec.required_ruby_version = Gem::Requirement.new('>=
|
|
15
|
+
spec.required_ruby_version = Gem::Requirement.new('>= 3.3.0')
|
|
16
16
|
|
|
17
17
|
spec.metadata['homepage_uri'] = spec.homepage
|
|
18
18
|
spec.metadata['source_code_uri'] = spec.homepage
|
|
@@ -27,7 +27,7 @@ Gem::Specification.new do |spec|
|
|
|
27
27
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
28
28
|
spec.require_paths = ['lib']
|
|
29
29
|
|
|
30
|
-
spec.add_dependency 'activeadmin'
|
|
30
|
+
spec.add_dependency 'activeadmin', '>= 3.0', '< 4.0'
|
|
31
31
|
# spec.add_dependency 'devise'
|
|
32
32
|
spec.add_dependency 'rspec', '~> 3.0'
|
|
33
33
|
end
|
|
@@ -7,13 +7,13 @@ module Capybara
|
|
|
7
7
|
module Layout
|
|
8
8
|
def click_action_item(title, options = {})
|
|
9
9
|
within(action_items_container_selector) do
|
|
10
|
-
click_link(title, options)
|
|
10
|
+
click_link(title, **options)
|
|
11
11
|
end
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
def switch_tab(tab_name, options = {})
|
|
15
15
|
opts = Util.options_with_text(tab_name, options)
|
|
16
|
-
find(tab_header_link_selector, opts).click
|
|
16
|
+
find(tab_header_link_selector, **opts).click
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
def click_batch_action(title, exact: true)
|
|
@@ -21,7 +21,7 @@ module Capybara
|
|
|
21
21
|
within(dropdown_list_selector) do
|
|
22
22
|
selector = batch_action_selector
|
|
23
23
|
opts = Util.options_with_text(title, exact: exact)
|
|
24
|
-
find(selector, opts).click
|
|
24
|
+
find(selector, **opts).click
|
|
25
25
|
end
|
|
26
26
|
end
|
|
27
27
|
|
|
@@ -16,6 +16,18 @@ module Capybara
|
|
|
16
16
|
selector = %(input[id^="batch_action_item_"])
|
|
17
17
|
find_all(selector, minimum: index + 1)[index].click
|
|
18
18
|
end
|
|
19
|
+
|
|
20
|
+
# @param text [String] exact text of the scope to click.
|
|
21
|
+
def click_table_scope(text)
|
|
22
|
+
selector = "#{table_scopes_container_selector} > #{table_scope_selector}"
|
|
23
|
+
page.find(selector, exact_text: text).click
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# @param text [String] column header text.
|
|
27
|
+
# @param options [Hash] options passed to find_table_header.
|
|
28
|
+
def click_table_header(text, options = {})
|
|
29
|
+
find_table_header(text, options).find('a').click
|
|
30
|
+
end
|
|
19
31
|
end
|
|
20
32
|
end
|
|
21
33
|
end
|
|
@@ -22,6 +22,13 @@ module Capybara
|
|
|
22
22
|
within(fieldset) { yield }
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
+
# @param association_name [String]
|
|
26
|
+
# @yield within container have_many by passed association_name
|
|
27
|
+
def within_has_many(association_name)
|
|
28
|
+
selector = has_many_container_selector(association_name)
|
|
29
|
+
within(selector) { yield }
|
|
30
|
+
end
|
|
31
|
+
|
|
25
32
|
# @yield within filters container.
|
|
26
33
|
def within_filters
|
|
27
34
|
selector = filter_form_selector
|
|
@@ -7,7 +7,7 @@ module Capybara
|
|
|
7
7
|
module Layout
|
|
8
8
|
def find_footer(options = {})
|
|
9
9
|
selector = footer_selector
|
|
10
|
-
have_selector(selector, options)
|
|
10
|
+
have_selector(selector, **options)
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
def within_tab_body
|
|
@@ -16,17 +16,15 @@ module Capybara
|
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
def within_sidebar(title, exact: nil)
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
within(
|
|
22
|
-
within_panel(title, exact: exact) { yield }
|
|
23
|
-
end
|
|
19
|
+
opts = Util.options_with_text(title, exact: exact)
|
|
20
|
+
sidebar = page.find("#{sidebar_selector} .sidebar_section #{panel_title_selector}", **opts).ancestor('.sidebar_section')
|
|
21
|
+
within(sidebar) { yield }
|
|
24
22
|
end
|
|
25
23
|
|
|
26
24
|
def within_panel(title, exact: nil)
|
|
27
25
|
title_selector = "#{panel_selector} > #{panel_title_selector}"
|
|
28
26
|
title_opts = Util.options_with_text(title, exact: exact)
|
|
29
|
-
panel_title = find(title_selector, title_opts)
|
|
27
|
+
panel_title = find(title_selector, **title_opts)
|
|
30
28
|
panel_content = panel_title.sibling(panel_content_selector)
|
|
31
29
|
|
|
32
30
|
within(panel_content) { yield }
|
|
@@ -35,6 +33,19 @@ module Capybara
|
|
|
35
33
|
def within_modal_dialog
|
|
36
34
|
within(modal_dialog_selector) { yield }
|
|
37
35
|
end
|
|
36
|
+
|
|
37
|
+
# @param title [String] action item link text.
|
|
38
|
+
# @param exact [Boolean] whether to match the title exactly (default true).
|
|
39
|
+
# @return [Capybara::Node::Element] the found action item element.
|
|
40
|
+
def find_action_item(title, exact: true)
|
|
41
|
+
opts = exact ? { exact_text: title } : { text: title }
|
|
42
|
+
page.find(action_item_selector, **opts)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# @yield within action item dropdown menu list.
|
|
46
|
+
def within_action_item_dropdown
|
|
47
|
+
within("#{action_item_selector} .dropdown_menu_list_wrapper") { yield }
|
|
48
|
+
end
|
|
38
49
|
end
|
|
39
50
|
end
|
|
40
51
|
end
|
|
@@ -34,6 +34,23 @@ module Capybara
|
|
|
34
34
|
find_all(selector, minimum: index + 1)[index]
|
|
35
35
|
end
|
|
36
36
|
|
|
37
|
+
# @yield within table>tfoot>tr
|
|
38
|
+
def within_table_footer
|
|
39
|
+
within('tfoot > tr') { yield }
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# @param text [String] column header text.
|
|
43
|
+
# @param options [Hash]
|
|
44
|
+
# @option column [String, nil] column name override (defaults to text).
|
|
45
|
+
# @option sortable [Boolean] whether the column is sortable.
|
|
46
|
+
# @option sort_direction [String, nil] sort direction ('asc' or 'desc').
|
|
47
|
+
# @return [Capybara::Node::Element] the found table header element.
|
|
48
|
+
def find_table_header(text, options = {})
|
|
49
|
+
selector = table_header_selector(text, options)
|
|
50
|
+
opts = options.except(:column, :sortable, :sort_direction).merge(exact_text: text)
|
|
51
|
+
find(selector, **opts)
|
|
52
|
+
end
|
|
53
|
+
|
|
37
54
|
# @yield within table>tbody>tr>td
|
|
38
55
|
def within_table_cell(name)
|
|
39
56
|
cell = find_table_cell(name)
|
|
@@ -8,12 +8,12 @@ module Capybara
|
|
|
8
8
|
model = options.delete(:model)
|
|
9
9
|
id = options.delete(:id)
|
|
10
10
|
selector = attributes_table_selector(model: model, id: id)
|
|
11
|
-
have_selector(selector, options)
|
|
11
|
+
have_selector(selector, **options)
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
def have_attribute_row(label, options = {})
|
|
15
15
|
selector = attributes_row_selector(label)
|
|
16
|
-
have_selector(selector, options)
|
|
16
|
+
have_selector(selector, **options)
|
|
17
17
|
end
|
|
18
18
|
end
|
|
19
19
|
end
|
|
@@ -7,30 +7,65 @@ module Capybara
|
|
|
7
7
|
def have_form_error(text, options = {})
|
|
8
8
|
field = options.delete(:field)
|
|
9
9
|
opts = Util.options_with_text(text, options)
|
|
10
|
-
li_selector = input_container_selector field, options.slice(:exact)
|
|
10
|
+
li_selector = input_container_selector field, **options.slice(:exact)
|
|
11
11
|
|
|
12
|
-
have_selector("#{li_selector} #{inline_error_selector}", opts)
|
|
12
|
+
have_selector("#{li_selector} #{inline_error_selector}", **opts)
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
def have_no_form_errors(options = {})
|
|
16
16
|
field = options.delete(:field)
|
|
17
|
-
li_selector = input_container_selector field, options.slice(:exact)
|
|
17
|
+
li_selector = input_container_selector field, **options.slice(:exact)
|
|
18
18
|
|
|
19
|
-
have_none_of_selectors(:css, "#{li_selector} #{inline_error_selector}", options)
|
|
19
|
+
have_none_of_selectors(:css, "#{li_selector} #{inline_error_selector}", **options)
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
def have_semantic_error(text, options = {})
|
|
23
23
|
opts = Util.options_with_text(text, options)
|
|
24
|
-
have_selector(semantic_error_selector, opts)
|
|
24
|
+
have_selector(semantic_error_selector, **opts)
|
|
25
25
|
end
|
|
26
26
|
|
|
27
27
|
def have_semantic_errors(options = {})
|
|
28
|
-
have_selector(semantic_error_selector, options)
|
|
28
|
+
have_selector(semantic_error_selector, **options)
|
|
29
29
|
end
|
|
30
30
|
|
|
31
31
|
def have_has_many_fields_for(association_name, options = {})
|
|
32
32
|
selector = has_many_fields_selector(association_name)
|
|
33
|
-
have_selector(selector, options)
|
|
33
|
+
have_selector(selector, **options)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# @param label [String] label text of the date range filter.
|
|
37
|
+
# @param options [Hash]
|
|
38
|
+
# @option from [String, nil] expected value of the "from" field.
|
|
39
|
+
# @option to [String, nil] expected value of the "to" field.
|
|
40
|
+
# @option exact [Boolean, nil] whether to match field values exactly.
|
|
41
|
+
# @example
|
|
42
|
+
# expect(page).to have_fields_date_range('Created At', from: '2020-01-01', to: '2020-12-31')
|
|
43
|
+
#
|
|
44
|
+
def have_fields_date_range(label, options = {})
|
|
45
|
+
exact = options[:exact]
|
|
46
|
+
satisfy do |actual|
|
|
47
|
+
expect(actual).to have_selector('div.filter_date_range label', text: label)
|
|
48
|
+
container = actual.find('div.filter_date_range label', text: label).ancestor('div.filter_date_range')
|
|
49
|
+
base_name = container[:id].gsub(/_input\z/, '')
|
|
50
|
+
expect(container).to have_field("#{base_name}_gteq_datetime", with: options[:from].to_s, exact: exact)
|
|
51
|
+
expect(container).to have_field("#{base_name}_lteq_datetime", with: options[:to].to_s, exact: exact)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# @param text [String] button title
|
|
56
|
+
# @param options [Hash]
|
|
57
|
+
# @option selector [String, nil] optional selector to append
|
|
58
|
+
# @option disabled [Boolean] button disabled or not (default false)
|
|
59
|
+
# @example
|
|
60
|
+
# expect(page).to have_submit_input('Submit') # check that submit input is present
|
|
61
|
+
# expect(page).to have_submit_input('Submit', selector: '.custom-class') # check custom class presence
|
|
62
|
+
# expect(page).to have_submit_input('Submit', disabled: true) # check that submit input is disabled
|
|
63
|
+
# expect(page).to have_submit_input('Submit', disabled: true, count: 0) # check that submit input is enabled
|
|
64
|
+
#
|
|
65
|
+
def have_submit_input(text, options = {})
|
|
66
|
+
selector = "#{form_submit_selector(text)}#{options.delete(:selector)}"
|
|
67
|
+
selector += '[disabled="disabled"].disabled' if options.delete(:disabled)
|
|
68
|
+
have_selector(selector, **options)
|
|
34
69
|
end
|
|
35
70
|
end
|
|
36
71
|
end
|
|
@@ -7,42 +7,68 @@ module Capybara
|
|
|
7
7
|
module Layout
|
|
8
8
|
def have_action_item(text, options = {})
|
|
9
9
|
opts = Util.options_with_text(text, options)
|
|
10
|
-
have_selector(action_item_selector, opts)
|
|
10
|
+
have_selector(action_item_selector, **opts)
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
def have_page_title(text, options = {})
|
|
14
14
|
opts = Util.options_with_text(text, options)
|
|
15
|
-
have_selector(page_title_selector, opts)
|
|
15
|
+
have_selector(page_title_selector, **opts)
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
def have_flash_message(text, options = {})
|
|
19
19
|
type = options.delete(:type)
|
|
20
20
|
opts = Util.options_with_text(text, options)
|
|
21
21
|
selector = flash_message_selector(type)
|
|
22
|
-
have_selector(selector, opts)
|
|
22
|
+
have_selector(selector, **opts)
|
|
23
23
|
end
|
|
24
24
|
|
|
25
25
|
def have_footer(options = {})
|
|
26
26
|
selector = footer_selector
|
|
27
|
-
have_selector(selector, options)
|
|
27
|
+
have_selector(selector, **options)
|
|
28
28
|
end
|
|
29
29
|
|
|
30
30
|
def have_panel(title, options = {})
|
|
31
31
|
title_selector = "#{panel_selector} > #{panel_title_selector}"
|
|
32
32
|
opts = Util.options_with_text(title, options)
|
|
33
|
-
have_selector(title_selector, opts)
|
|
33
|
+
have_selector(title_selector, **opts)
|
|
34
34
|
end
|
|
35
35
|
|
|
36
36
|
def have_sidebar(title, options = {})
|
|
37
37
|
title_selector = "#{sidebar_selector} #{panel_selector} > #{panel_title_selector}"
|
|
38
38
|
opts = Util.options_with_text(title, options)
|
|
39
|
-
have_selector(title_selector, opts)
|
|
39
|
+
have_selector(title_selector, **opts)
|
|
40
40
|
end
|
|
41
41
|
|
|
42
42
|
def have_batch_action(title, exact: true)
|
|
43
43
|
selector = "#{dropdown_list_selector} #{batch_action_selector}"
|
|
44
44
|
opts = Util.options_with_text(title, exact: exact)
|
|
45
|
-
have_selector(selector, opts)
|
|
45
|
+
have_selector(selector, **opts)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# @param title [String] action item link text.
|
|
49
|
+
# @param exact [Boolean] whether to match the title exactly (default true).
|
|
50
|
+
# @param href [String, nil] expected href attribute of the link.
|
|
51
|
+
# @param options [Hash] additional options passed to have_selector.
|
|
52
|
+
# @example
|
|
53
|
+
# expect(page).to have_action_item_link('New User')
|
|
54
|
+
# expect(page).to have_action_item_link('New User', href: new_admin_user_path)
|
|
55
|
+
#
|
|
56
|
+
def have_action_item_link(title, exact: true, href: nil, **options)
|
|
57
|
+
opts = exact ? { exact_text: title } : { text: title }
|
|
58
|
+
opts.merge!(options)
|
|
59
|
+
selector = "#{action_item_selector} > a"
|
|
60
|
+
selector += "[href=\"#{href}\"]" if href.present?
|
|
61
|
+
have_selector(selector, **opts)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# @param type [String, Symbol] status tag type (e.g. :yes, :no, :warning).
|
|
65
|
+
# @param options [Hash] additional options passed to have_selector (e.g. exact_text:).
|
|
66
|
+
# @example
|
|
67
|
+
# expect(page).to have_status_tag(:yes)
|
|
68
|
+
# expect(page).to have_status_tag(:error, exact_text: 'DOWN')
|
|
69
|
+
#
|
|
70
|
+
def have_status_tag(type, **options)
|
|
71
|
+
have_selector("span.status_tag.#{type}", **options)
|
|
46
72
|
end
|
|
47
73
|
end
|
|
48
74
|
end
|