katapult 0.2.0 → 0.3.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.
Files changed (143) hide show
  1. checksums.yaml +5 -5
  2. data/.rspec +1 -0
  3. data/.ruby-version +1 -1
  4. data/Gemfile +9 -0
  5. data/README.md +122 -94
  6. data/Rakefile +13 -0
  7. data/bin/katapult +59 -25
  8. data/features/application_model.feature +55 -0
  9. data/features/authenticate.feature +88 -62
  10. data/features/basics.feature +64 -402
  11. data/features/binary.feature +56 -42
  12. data/features/configuration.feature +4 -4
  13. data/features/model.feature +21 -30
  14. data/features/navigation.feature +35 -48
  15. data/features/step_definitions/aruba_steps.rb +3 -0
  16. data/features/step_definitions/katapult_steps.rb +307 -8
  17. data/features/step_definitions/rails_steps.rb +74 -14
  18. data/features/step_definitions/test_steps.rb +5 -5
  19. data/features/step_definitions/version_steps.rb +22 -0
  20. data/features/support/env.rb +11 -3
  21. data/features/{wui.feature → web_ui.feature} +175 -148
  22. data/katapult.gemspec +8 -13
  23. data/lib/generators/katapult/app_model/app_model_generator.rb +12 -0
  24. data/lib/generators/katapult/app_model/templates/lib/katapult/application_model.rb +40 -0
  25. data/lib/generators/katapult/basics/basics_generator.rb +186 -51
  26. data/lib/generators/katapult/basics/templates/.browserslistrc +1 -0
  27. data/lib/generators/katapult/basics/templates/.gitignore +20 -21
  28. data/lib/generators/katapult/basics/templates/.rspec_parallel +3 -0
  29. data/lib/generators/katapult/basics/templates/Capfile +5 -1
  30. data/lib/generators/katapult/basics/templates/Gemfile +23 -34
  31. data/lib/generators/katapult/basics/templates/Guardfile +0 -12
  32. data/lib/generators/katapult/basics/templates/app/controllers/errors_controller.rb +9 -0
  33. data/lib/generators/katapult/basics/templates/app/helpers/unpoly_helper.rb +13 -0
  34. data/lib/generators/katapult/{haml → basics}/templates/app/views/layouts/_flashes.html.haml +1 -1
  35. data/lib/generators/katapult/basics/templates/app/views/layouts/_menu_bar.html.haml.tt +12 -0
  36. data/lib/generators/katapult/basics/templates/app/views/layouts/application.html.haml.tt +25 -0
  37. data/lib/generators/katapult/basics/templates/app/webpack/assets/images/.keep +0 -0
  38. data/lib/generators/katapult/basics/templates/app/webpack/assets/index.js +16 -0
  39. data/lib/generators/katapult/basics/templates/app/webpack/assets/javascripts/application.js +0 -0
  40. data/lib/generators/katapult/basics/templates/app/webpack/assets/javascripts/bootstrap.js +12 -0
  41. data/lib/generators/katapult/basics/templates/app/webpack/assets/javascripts/compilers/.keep +0 -0
  42. data/lib/generators/katapult/basics/templates/app/webpack/assets/javascripts/macros/content_link.js +17 -0
  43. data/lib/generators/katapult/basics/templates/app/webpack/assets/javascripts/macros/modal_link.js +17 -0
  44. data/lib/generators/katapult/basics/templates/app/webpack/assets/javascripts/unpoly.js +9 -0
  45. data/lib/generators/katapult/basics/templates/app/webpack/assets/stylesheets/_definitions.sass +25 -0
  46. data/lib/generators/katapult/basics/templates/app/webpack/assets/stylesheets/_environment.sass +2 -0
  47. data/lib/generators/katapult/basics/templates/app/webpack/assets/stylesheets/_mixins.sass +3 -0
  48. data/lib/generators/katapult/basics/templates/app/webpack/assets/stylesheets/blocks/.keep +0 -0
  49. data/lib/generators/katapult/basics/templates/app/webpack/assets/stylesheets/custom_bootstrap.sass +50 -0
  50. data/lib/generators/katapult/basics/templates/app/webpack/assets/stylesheets/ext/.keep +0 -0
  51. data/lib/generators/katapult/basics/templates/app/webpack/assets/stylesheets/ext/bootstrap/navbar.sass +83 -0
  52. data/lib/generators/katapult/basics/templates/app/webpack/assets/stylesheets/theme.sass +11 -0
  53. data/lib/generators/katapult/basics/templates/app/webpack/assets/stylesheets/unpoly.sass +2 -0
  54. data/lib/generators/katapult/basics/templates/app/webpack/packs/application.js +13 -0
  55. data/lib/generators/katapult/basics/templates/config/database.sample.yml +1 -1
  56. data/lib/generators/katapult/basics/templates/config/deploy.rb +3 -4
  57. data/lib/generators/katapult/basics/templates/config/environments/staging.rb +5 -0
  58. data/lib/generators/katapult/basics/templates/config/initializers/better_errors.rb +23 -0
  59. data/lib/generators/katapult/basics/templates/config/initializers/exception_notification.rb.tt +1 -1
  60. data/lib/generators/katapult/basics/templates/config/initializers/ext.rb +1 -1
  61. data/lib/generators/katapult/basics/templates/config/webpack/loaders/unpoly.js +4 -0
  62. data/lib/generators/katapult/basics/templates/features/support/capybara_screenshot.rb +7 -0
  63. data/lib/generators/katapult/basics/templates/features/support/factory_bot.rb +1 -0
  64. data/lib/generators/katapult/basics/templates/features/support/paths.rb +7 -2
  65. data/lib/generators/katapult/basics/templates/features/support/rspec_doubles.rb +1 -0
  66. data/lib/generators/katapult/basics/templates/features/support/selectors.rb +3 -3
  67. data/lib/generators/katapult/basics/templates/features/support/selenium.rb +13 -0
  68. data/lib/generators/katapult/basics/templates/features/support/{env-custom.rb → spreewald.rb} +0 -0
  69. data/lib/generators/katapult/basics/templates/features/support/webpacker.rb +35 -0
  70. data/lib/generators/katapult/basics/templates/lib/ext/action_view/form_for_with_development_errors.rb +31 -31
  71. data/lib/generators/katapult/basics/templates/lib/ext/active_record/find_by_anything.rb +4 -3
  72. data/lib/generators/katapult/basics/templates/public/robots.txt +5 -0
  73. data/lib/generators/katapult/basics/templates/spec/assets/sample.pdf +0 -0
  74. data/lib/generators/katapult/basics/templates/spec/factories/factories.rb +1 -1
  75. data/lib/generators/katapult/basics/templates/spec/support/database_cleaner.rb +20 -0
  76. data/lib/generators/katapult/basics/templates/spec/support/factory_bot.rb +3 -0
  77. data/lib/generators/katapult/basics/templates/spec/support/fixture_file.rb +6 -0
  78. data/lib/generators/katapult/basics/templates/spec/support/postgresql_sequences.rb +15 -0
  79. data/lib/generators/katapult/basics/templates/spec/support/timecop.rb +3 -0
  80. data/lib/generators/katapult/clearance/clearance_generator.rb +14 -2
  81. data/lib/generators/katapult/clearance/templates/app/views/layouts/_current_user.html.haml +11 -0
  82. data/lib/generators/katapult/clearance/templates/app/views/passwords/create.html.haml +10 -4
  83. data/lib/generators/katapult/clearance/templates/app/views/passwords/edit.html.haml +12 -12
  84. data/lib/generators/katapult/clearance/templates/app/views/passwords/new.html.haml +14 -11
  85. data/lib/generators/katapult/clearance/templates/app/views/sessions/new.html.haml +16 -15
  86. data/lib/generators/katapult/clearance/templates/features/authentication.feature +3 -3
  87. data/lib/generators/katapult/cucumber_features/templates/feature.feature +1 -1
  88. data/lib/generators/katapult/model_specs/templates/model_spec.rb +3 -5
  89. data/lib/generators/katapult/navigation/navigation_generator.rb +7 -1
  90. data/lib/generators/katapult/navigation/templates/app/views/layouts/_navigation.html.haml +15 -0
  91. data/lib/generators/katapult/transform/transform_generator.rb +12 -17
  92. data/lib/generators/katapult/views/templates/_form.html.haml +48 -0
  93. data/lib/generators/katapult/views/templates/app/helpers/table_helper.rb +14 -0
  94. data/lib/generators/katapult/views/templates/app/webpack/assets/stylesheets/blocks/action_bar.sass +22 -0
  95. data/lib/generators/katapult/views/templates/app/webpack/assets/stylesheets/blocks/title.sass +11 -0
  96. data/lib/generators/katapult/views/templates/custom_action.html.haml +5 -0
  97. data/lib/generators/katapult/views/templates/edit.html.haml +4 -0
  98. data/lib/generators/katapult/views/templates/index.html.haml +26 -0
  99. data/lib/generators/katapult/{haml → views}/templates/new.html.haml +1 -1
  100. data/lib/generators/katapult/views/templates/show.html.haml +39 -0
  101. data/lib/generators/katapult/{haml/haml_generator.rb → views/views_generator.rb} +19 -25
  102. data/lib/generators/katapult/{w_u_i → web_ui}/templates/_route.rb +3 -3
  103. data/lib/generators/katapult/{w_u_i → web_ui}/templates/controller.rb +21 -23
  104. data/lib/generators/katapult/{w_u_i/w_u_i_generator.rb → web_ui/web_ui_generator.rb} +7 -12
  105. data/lib/katapult/action.rb +1 -1
  106. data/lib/katapult/application_model.rb +8 -8
  107. data/lib/katapult/binary_util.rb +48 -10
  108. data/lib/katapult/generator.rb +2 -10
  109. data/lib/katapult/generator_goodies.rb +23 -0
  110. data/lib/katapult/navigation.rb +10 -5
  111. data/lib/katapult/parser.rb +15 -8
  112. data/lib/katapult/version.rb +5 -1
  113. data/lib/katapult/{wui.rb → web_ui.rb} +19 -4
  114. data/lib/katapult.rb +0 -5
  115. data/script/console +5 -2
  116. data/script/kta +8 -0
  117. data/script/update +80 -0
  118. data/spec/action_spec.rb +0 -1
  119. data/spec/attribute_spec.rb +0 -1
  120. data/spec/element_spec.rb +0 -1
  121. data/spec/model_spec.rb +0 -1
  122. data/spec/parser_spec.rb +26 -0
  123. data/spec/util_spec.rb +0 -1
  124. data/spec/{wui_spec.rb → web_ui_spec.rb} +24 -12
  125. metadata +86 -124
  126. data/lib/generators/katapult/basics/templates/app/assets/stylesheets/application/blocks/_all.sass +0 -4
  127. data/lib/generators/katapult/basics/templates/app/assets/stylesheets/application/blocks/_items.sass +0 -11
  128. data/lib/generators/katapult/basics/templates/app/assets/stylesheets/application/blocks/_layout.sass +0 -26
  129. data/lib/generators/katapult/basics/templates/app/assets/stylesheets/application/blocks/_navigation.sass +0 -11
  130. data/lib/generators/katapult/basics/templates/app/assets/stylesheets/application/blocks/_tools.sass +0 -12
  131. data/lib/generators/katapult/basics/templates/app/assets/stylesheets/application.sass +0 -6
  132. data/lib/generators/katapult/basics/templates/config/spring.rb +0 -3
  133. data/lib/generators/katapult/basics/templates/features/support/factory_girl.rb +0 -1
  134. data/lib/generators/katapult/basics/templates/spec/support/factory_girl.rb +0 -3
  135. data/lib/generators/katapult/haml/templates/_form.html.haml +0 -38
  136. data/lib/generators/katapult/haml/templates/app/views/layouts/application.html.haml +0 -33
  137. data/lib/generators/katapult/haml/templates/custom_action.html.haml +0 -5
  138. data/lib/generators/katapult/haml/templates/edit.html.haml +0 -4
  139. data/lib/generators/katapult/haml/templates/index.html.haml +0 -29
  140. data/lib/generators/katapult/haml/templates/show.html.haml +0 -39
  141. data/lib/generators/katapult/install/install_generator.rb +0 -14
  142. data/lib/generators/katapult/install/templates/lib/katapult/application_model.rb +0 -20
  143. data/lib/generators/katapult/navigation/templates/app/models/navigation.rb +0 -12
@@ -0,0 +1,17 @@
1
+ const DEFAULT_TARGET = '.content'
2
+
3
+ up.macro('[content-link]', ($link) => {
4
+ let target = $link.attr('content-link') || DEFAULT_TARGET
5
+ let attrs = {
6
+ 'up-target': target,
7
+ 'up-preload': '',
8
+ 'up-instant': '',
9
+ }
10
+
11
+ // It feels wrong for a button
12
+ if ($link.is('.btn:not(.btn-link)')) {
13
+ delete attrs['up-instant']
14
+ }
15
+
16
+ $link.attr(attrs)
17
+ })
@@ -0,0 +1,17 @@
1
+ const DEFAULT_TARGET = '.content'
2
+
3
+ up.macro('[modal-link]', function($link) {
4
+ let target = $link.attr('modal-link') || DEFAULT_TARGET
5
+ let attrs = {
6
+ 'up-modal': target,
7
+ 'up-preload': '',
8
+ 'up-instant': '',
9
+ }
10
+
11
+ // It feels wrong for a button
12
+ if ($link.is('.btn:not(.btn-link)')) {
13
+ delete attrs['up-instant']
14
+ }
15
+
16
+ $link.attr(attrs)
17
+ })
@@ -0,0 +1,9 @@
1
+ $(() => {
2
+ if ($(document.body).data('environment') === 'test') {
3
+ // Disable animations in tests
4
+ up.motion.config.enabled = false
5
+
6
+ // When revealing elements, don't animate the scrolling
7
+ up.layout.config.duration = 0
8
+ }
9
+ })
@@ -0,0 +1,25 @@
1
+ // Colors
2
+ $theme-blue: #4682B4
3
+
4
+ $white: #fff
5
+
6
+ // Transitions
7
+ $transition-distinct: .21s
8
+ $transition-quick: .14s
9
+ $transition-subtle: .07s
10
+
11
+ // Spacing
12
+ $space-xs: 10px
13
+ $space-sm: 20px
14
+ $space-md: 30px
15
+ $space-lg: 40px
16
+
17
+ // Bootstrap configuration /////////////////////////////////////////////////////
18
+ $brand-primary: $theme-blue
19
+
20
+ $font-family-sans-serif: 'Open Sans', 'Segoe UI', sans-serif
21
+
22
+ $input-border-focus: $brand-primary
23
+ $border-radius-base: 3px
24
+
25
+ @import ~bootstrap-sass/assets/stylesheets/bootstrap/variables
@@ -0,0 +1,2 @@
1
+ @import definitions
2
+ @import mixins
@@ -0,0 +1,3 @@
1
+ =within-modal
2
+ .modal-content &
3
+ @content
@@ -0,0 +1,50 @@
1
+ @import environment
2
+
3
+ // Core variables and mixins
4
+ @import ~bootstrap-sass/assets/stylesheets/bootstrap/variables
5
+ @import ~bootstrap-sass/assets/stylesheets/bootstrap/mixins
6
+
7
+ // Reset and dependencies
8
+ @import ~bootstrap-sass/assets/stylesheets/bootstrap/normalize
9
+ @import ~bootstrap-sass/assets/stylesheets/bootstrap/print
10
+
11
+ // Core CSS
12
+ @import ~bootstrap-sass/assets/stylesheets/bootstrap/scaffolding
13
+ @import ~bootstrap-sass/assets/stylesheets/bootstrap/type
14
+ @import ~bootstrap-sass/assets/stylesheets/bootstrap/code
15
+ @import ~bootstrap-sass/assets/stylesheets/bootstrap/grid
16
+ @import ~bootstrap-sass/assets/stylesheets/bootstrap/tables
17
+ @import ~bootstrap-sass/assets/stylesheets/bootstrap/forms
18
+ @import ~bootstrap-sass/assets/stylesheets/bootstrap/buttons
19
+
20
+ // Components
21
+ @import ~bootstrap-sass/assets/stylesheets/bootstrap/component-animations
22
+ @import ~bootstrap-sass/assets/stylesheets/bootstrap/dropdowns
23
+ @import ~bootstrap-sass/assets/stylesheets/bootstrap/button-groups
24
+ @import ~bootstrap-sass/assets/stylesheets/bootstrap/input-groups
25
+ @import ~bootstrap-sass/assets/stylesheets/bootstrap/navs
26
+ @import ~bootstrap-sass/assets/stylesheets/bootstrap/navbar
27
+ //@import ~bootstrap-sass/assets/stylesheets/bootstrap/breadcrumbs
28
+ //@import ~bootstrap-sass/assets/stylesheets/bootstrap/pagination
29
+ //@import ~bootstrap-sass/assets/stylesheets/bootstrap/pager
30
+ //@import ~bootstrap-sass/assets/stylesheets/bootstrap/labels
31
+ //@import ~bootstrap-sass/assets/stylesheets/bootstrap/badges
32
+ //@import ~bootstrap-sass/assets/stylesheets/bootstrap/jumbotron
33
+ //@import ~bootstrap-sass/assets/stylesheets/bootstrap/thumbnails
34
+ @import ~bootstrap-sass/assets/stylesheets/bootstrap/alerts
35
+ //@import ~bootstrap-sass/assets/stylesheets/bootstrap/progress-bars
36
+ //@import ~bootstrap-sass/assets/stylesheets/bootstrap/media
37
+ //@import ~bootstrap-sass/assets/stylesheets/bootstrap/list-group
38
+ //@import ~bootstrap-sass/assets/stylesheets/bootstrap/responsive-embed
39
+ //@import ~bootstrap-sass/assets/stylesheets/bootstrap/wells
40
+ //@import ~bootstrap-sass/assets/stylesheets/bootstrap/close
41
+
42
+ // Components w/ JavaScript
43
+ //@import ~bootstrap-sass/assets/stylesheets/bootstrap/modal
44
+ //@import ~bootstrap-sass/assets/stylesheets/bootstrap/tooltip
45
+ //@import ~bootstrap-sass/assets/stylesheets/bootstrap/popover
46
+ //@import ~bootstrap-sass/assets/stylesheets/bootstrap/carousel
47
+
48
+ // Utility classes
49
+ @import ~bootstrap-sass/assets/stylesheets/bootstrap/utilities
50
+ @import ~bootstrap-sass/assets/stylesheets/bootstrap/responsive-utilities
@@ -0,0 +1,83 @@
1
+ @import ../../environment
2
+
3
+ .navbar-default .navbar-nav
4
+ & > li > a
5
+ transition: background-color $transition-subtle
6
+ &:hover
7
+ background-color: lighten($brand-primary, 5%)
8
+
9
+ .navbar-logout
10
+ &:hover
11
+ background-color: $btn-danger-bg
12
+ color: white
13
+
14
+ // Generated navbar ////////////////////////////////////////////////////////////
15
+ // Source: http://work.smarchal.com/twbscolor/sass/0066b3035ea3ffffffffffff0
16
+ $bgDefault: $brand-primary
17
+ $bgHighlight: darken($brand-primary, 5%)
18
+ $colDefault: $white
19
+ $colHighlight: $white
20
+ $dropDown: false
21
+
22
+ .navbar-default
23
+ background-color: $bgDefault
24
+ border-color: $bgHighlight
25
+ .navbar-brand
26
+ color: $colDefault
27
+ &:hover, &:focus
28
+ color: $colHighlight
29
+ .navbar-text
30
+ color: $colDefault
31
+ .navbar-nav
32
+ > li
33
+ > a
34
+ color: $colDefault
35
+ &:hover, &:focus
36
+ color: $colHighlight
37
+ @if $dropDown
38
+ > .dropdown-menu
39
+ background-color: $bgDefault
40
+ > li
41
+ > a
42
+ color: $colDefault
43
+ &:hover, &:focus
44
+ color: $colHighlight
45
+ background-color: $bgHighlight
46
+ > .divider
47
+ background-color: $bgHighlight
48
+ @if $dropDown
49
+ .open .dropdown-menu > .active
50
+ > a, > a:hover, > a:focus
51
+ color: $colHighlight
52
+ background-color: $bgHighlight
53
+ > .active
54
+ > a, > a:hover, > a:focus
55
+ color: $colHighlight
56
+ background-color: $bgHighlight
57
+ > .open
58
+ > a, > a:hover, > a:focus
59
+ color: $colHighlight
60
+ background-color: $bgHighlight
61
+ .navbar-toggle
62
+ border-color: $bgHighlight
63
+ &:hover, &:focus
64
+ background-color: $bgHighlight
65
+ .icon-bar
66
+ background-color: $colDefault
67
+ .navbar-collapse,
68
+ .navbar-form
69
+ border-color: $colDefault
70
+ .navbar-link
71
+ color: $colDefault
72
+ &:hover
73
+ color: $colHighlight
74
+ @media (max-width: 767px)
75
+ .navbar-default .navbar-nav .open .dropdown-menu
76
+ > li > a
77
+ color: $colDefault
78
+ &:hover, &:focus
79
+ color: $colHighlight
80
+ > .active
81
+ > a, > a:hover, > a:focus
82
+ color: $colHighlight
83
+ background-color: $bgHighlight
@@ -0,0 +1,11 @@
1
+ @import environment
2
+ @import url('https://fonts.googleapis.com/css?family=Open+Sans:400,700&subset=latin-ext')
3
+
4
+ html
5
+ -webkit-text-size-adjust: 100% // Prevent iOS font scaling in landscape
6
+
7
+ body
8
+ -webkit-font-smoothing: antialiased
9
+ -moz-osx-font-smoothing: grayscale
10
+
11
+ padding: $space-sm 0
@@ -0,0 +1,2 @@
1
+ @import ~unpoly/dist/unpoly
2
+ @import ~unpoly/dist/unpoly-bootstrap3
@@ -0,0 +1,13 @@
1
+ /* eslint no-console:0 */
2
+ import 'babel-polyfill' // ES6 for browsers like IE
3
+
4
+ import 'unpoly/dist/unpoly'
5
+ import 'unpoly/dist/unpoly-bootstrap3'
6
+ import 'jquery-ujs' // Rails goodies
7
+
8
+ import 'assets'
9
+
10
+ // Expose jQuery to developers
11
+ import jQuery from 'jquery'
12
+ window.$ = jQuery
13
+ window.jQuery = jQuery
@@ -2,7 +2,7 @@ common: &common
2
2
  adapter: postgresql
3
3
  encoding: unicode
4
4
  host: localhost
5
- username: root
5
+ username:
6
6
  password:
7
7
 
8
8
  development:
@@ -1,7 +1,7 @@
1
1
  abort 'You must run this using "bundle exec ..."' unless ENV['BUNDLE_BIN_PATH'] || ENV['BUNDLE_GEMFILE']
2
2
 
3
3
  # config valid only for current version of Capistrano
4
- lock '3.4.0'
4
+ lock '<%= @version %>'
5
5
 
6
6
  # Default value for :format is :pretty
7
7
  # set :format, :pretty
@@ -13,11 +13,11 @@ set :log_level, :info # %i(debug info error), default: :debug
13
13
 
14
14
  # Default value for :linked_files is []
15
15
  # set :linked_files, fetch(:linked_files, []).push('config/database.yml', 'config/secrets.yml')
16
- set :linked_files, %w(config/database.yml)
16
+ set :linked_files, %w(config/database.yml config/secrets.yml)
17
17
 
18
18
  # Default value for linked_dirs is []
19
19
  # set :linked_dirs, fetch(:linked_dirs, []).push('log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'vendor/bundle', 'public/system')
20
- set :linked_dirs, %w(log public/system)
20
+ set :linked_dirs, %w(log public/system tmp/pids)
21
21
 
22
22
  # Default value for default_env is {}
23
23
  # set :default_env, { path: "/opt/ruby/bin:$PATH" }
@@ -27,7 +27,6 @@ set :keep_releases, 10
27
27
  set :ssh_options, {
28
28
  forward_agent: true
29
29
  }
30
- set :scm, :git
31
30
  set :repo_url, 'git@code.makandra.de:makandra/<%= app_name %>.git'
32
31
 
33
32
  # set :whenever_roles, :cron
@@ -0,0 +1,5 @@
1
+ require_relative 'production'
2
+
3
+ Rails.application.configure do
4
+
5
+ end
@@ -0,0 +1,23 @@
1
+ # Avoid better_errors taking forever to render by ignoring variables larger than
2
+ # 10 Kilobytes. Based on https://github.com/charliesome/better_errors/issues/334
3
+
4
+ if defined?(BetterErrors) && Rails.env.development?
5
+ module BetterErrorsHugeInspectWarning
6
+
7
+ def inspect_value(obj)
8
+ inspected = obj.inspect
9
+ if inspected.size > 20_000
10
+ inspected = "Object was too large to inspect (#{inspected.size} bytes)."
11
+ end
12
+ CGI.escapeHTML(inspected)
13
+ rescue NoMethodError
14
+ "<span class='unsupported'>(object doesn't support inspect)</span>"
15
+ rescue Exception
16
+ "<span class='unsupported'>(exception was raised in inspect)</span>"
17
+ end
18
+
19
+ end
20
+
21
+ BetterErrors.ignored_instance_variables += [:@_request, :@_assigns, :@_controller, :@view_renderer]
22
+ BetterErrors::ErrorPage.prepend(BetterErrorsHugeInspectWarning)
23
+ end
@@ -5,7 +5,7 @@ ExceptionNotification.configure do |config|
5
5
  config.add_notifier :email, {
6
6
  email_prefix: '[<%= app_name %>] ',
7
7
  exception_recipients: %w[fail@makandra.de],
8
- sender_address: 'fail@makandra.de',
8
+ sender_address: Rails.configuration.system_email,
9
9
  sections: %w[request backtrace],
10
10
  background_sections: %w[backtrace],
11
11
  }
@@ -1,3 +1,3 @@
1
- Dir.glob(Rails.root.join('lib/ext/**/*.rb')).each do |filename|
1
+ Dir.glob(Rails.root.join('lib/ext/**/*.rb')).sort.each do |filename|
2
2
  require filename
3
3
  end
@@ -0,0 +1,4 @@
1
+ module.exports = {
2
+ test: require.resolve('unpoly'),
3
+ use: 'imports-loader?this=>window'
4
+ }
@@ -2,3 +2,10 @@ require 'capybara-screenshot/cucumber'
2
2
 
3
3
  # Keep up to the number of screenshots specified in the hash
4
4
  Capybara::Screenshot.prune_strategy = { keep: 10 }
5
+
6
+ # This asset host will become a `<base>` tag in the HTML's `<head>` and allow
7
+ # resolving test assets via the development Rails server. This makes HTML
8
+ # screenshots prettier.
9
+ # Note that *you won't be using development assets* but the compiled files from
10
+ # `RAILS_ROOT/public/packs-test/`.
11
+ Capybara.asset_host = 'http://localhost:3000/'
@@ -0,0 +1 @@
1
+ World(FactoryBot::Syntax::Methods)
@@ -14,7 +14,7 @@ module NavigationHelpers
14
14
  when /^the (page|form) for the (.*?) above$/
15
15
  action_prose, model_prose = $1, $2
16
16
  route = "#{action_prose == 'form' ? 'edit_' : ''}#{model_prose_to_route_segment(model_prose)}_path"
17
- model = model_prose.classify.constantize
17
+ model = model_prose_to_class(model_prose)
18
18
  send(route, model.last)
19
19
 
20
20
  when /^the (page|form) for the (.*?) "(.*?)"$/
@@ -39,12 +39,17 @@ module NavigationHelpers
39
39
  private
40
40
 
41
41
  def path_to_show_or_edit(action_prose, model_prose, identifier)
42
- model = model_prose.classify.constantize
42
+ model = model_prose_to_class(model_prose)
43
43
  route = "#{action_prose == 'form' ? 'edit_' : ''}#{model_prose_to_route_segment(model_prose)}_path"
44
44
  send(route, model.find_by_anything!(identifier))
45
45
  end
46
46
 
47
+ def model_prose_to_class(model_prose)
48
+ model_prose.gsub(' ', '_').classify.constantize
49
+ end
50
+
47
51
  def model_prose_to_route_segment(model_prose)
52
+ model_prose = model_prose.downcase
48
53
  model_prose.gsub(/[\ \/]/, '_')
49
54
  end
50
55
 
@@ -0,0 +1 @@
1
+ require 'cucumber/rspec/doubles'
@@ -13,12 +13,12 @@ module HtmlSelectorsHelpers
13
13
  # Usage examples:
14
14
  # the main menu -> '.main-menu'
15
15
  # the item box's header -> '.item-box--header'
16
- # the slider's item that is current -> '.slider--item.is-current'
17
- when /^the (.+?)(?:'s (.+?))?(?: that (.+))?$/
16
+ # the slider's item (current) -> '.slider--item.-current'
17
+ when /^the (.+?)(?:'s (.+?))?(?: \((.+)\))?$/
18
18
  selector = '.'
19
19
  selector << selectorify($1)
20
20
  selector << '--' << selectorify($2) if $2
21
- selector << '.' << selectorify($3) if $3
21
+ selector << '.-' << selectorify($3) if $3
22
22
  selector
23
23
 
24
24
  # Add more mappings here.
@@ -0,0 +1,13 @@
1
+ chrome_args = %w[--mute-audio --disable-infobars]
2
+ no_password_bubble = {
3
+ 'credentials_enable_service' => false,
4
+ 'profile.password_manager_enabled' => false
5
+ }
6
+
7
+ Capybara.register_driver :selenium do |app|
8
+ Capybara::Selenium::Driver.new(app,
9
+ browser: :chrome,
10
+ args: chrome_args,
11
+ prefs: no_password_bubble
12
+ )
13
+ end
@@ -0,0 +1,35 @@
1
+ module WebpackerHelper
2
+
3
+ module_function def compile_once
4
+ digest_file = Rails.root.join("tmp/webpacker_#{Rails.env}_digest")
5
+
6
+ packable_contents = Dir[Webpacker.config.source_path.join('**/*')]
7
+ .sort
8
+ .map { |filename| File.read(filename) if File.file?(filename) }
9
+ .join
10
+ digest = Digest::SHA256.hexdigest(packable_contents)
11
+
12
+ return if digest_file.exist? && digest_file.read == digest
13
+
14
+ # Base process compiles
15
+ if ENV['TEST_ENV_NUMBER'].to_i < 1
16
+ output_path = Webpacker.config.public_output_path
17
+ FileUtils.rm_r(output_path) if File.exist?(output_path)
18
+ puts "Removed Webpack output directory #{output_path}"
19
+
20
+ Webpacker.compile or raise 'Compilation failed'
21
+
22
+ digest_file.write(digest)
23
+
24
+ # Parallel processes wait for compilation
25
+ else
26
+ loop do
27
+ break if digest_file.exist? && digest_file.read == digest
28
+ sleep 0.1
29
+ end
30
+ end
31
+ end
32
+
33
+ end
34
+
35
+ WebpackerHelper.compile_once
@@ -1,43 +1,43 @@
1
- if Rails.env == 'development'
2
-
3
- ActionView::Helpers::FormHelper.class_eval do
1
+ if Rails.env.development?
4
2
 
3
+ ActionView::Helpers::FormHelper.module_eval do
5
4
  def form_for_with_development_errors(*args, &block)
6
5
  form_for_without_development_errors(*args) do |form|
7
6
  html = ''.html_safe
8
- if form.object && form.object.respond_to?(:errors) && form.object.errors.any?
9
- html << content_tag(:div, form.object.errors.full_messages.collect { |m| h m }.join('<br />').html_safe, :class => 'development_errors', :onclick => 'this.parentNode.removeChild(this);')
10
- html << '<style type="text/css"><!--'.html_safe
11
- css = <<-EOF
12
- .development_errors {
13
- position: fixed;
14
- bottom: 0;
15
- right: 0;
16
- z-index: 999999;
17
- font-size: 11px;
18
- line-height: 15px;
19
- background-color: #fed;
20
- border-top: 1px solid #cba;
21
- border-left: 1px solid #cba;
22
- color: #821;
23
- padding: 10px;
24
- cursor: pointer;
25
- filter:alpha(opacity=80);
26
- -moz-opacity:0.8;
27
- -khtml-opacity: 0.8;
28
- opacity: 0.8;
29
-
30
- }
31
- EOF
32
- html << css.html_safe
33
- html << '</style>'.html_safe
34
- end
7
+ html << form_development_errors(form.object)
35
8
  html << capture(form, &block)
36
9
  end
37
10
  end
38
11
 
39
- alias_method_chain :form_for, :development_errors
12
+ alias_method :form_for_without_development_errors, :form_for
13
+ alias_method :form_for, :form_for_with_development_errors
14
+
15
+ private
16
+
17
+ def form_development_errors(object)
18
+ return unless object
19
+ return unless object.respond_to?(:errors)
20
+ return unless object.errors.any?
40
21
 
22
+ safe_messages = object.errors.full_messages.map { |message| h(message) }.join('<br />').html_safe
23
+
24
+ styles = <<~CSS
25
+ position: fixed;
26
+ bottom: 0;
27
+ right: 0;
28
+ z-index: 999999;
29
+ font-size: 0.8rem;
30
+ background-color: #fed;
31
+ border-top: 1px solid #cba;
32
+ border-left: 1px solid #cba;
33
+ color: #821;
34
+ padding: 0.5em 1em;
35
+ cursor: pointer;
36
+ opacity: 0.8;
37
+ CSS
38
+
39
+ content_tag(:div, safe_messages, style: styles.squish, onclick: 'this.parentNode.removeChild(this)')
40
+ end
41
41
  end
42
42
 
43
43
  end
@@ -4,16 +4,17 @@ ActiveRecord::Base.class_eval do
4
4
  matchable_columns = columns.reject { |column| [:binary, :boolean].include?(column.type) }
5
5
  query_clauses = matchable_columns.collect do |column|
6
6
  qualified_column_name = "#{table_name}.#{column.name}"
7
- column_as_string = "CAST(#{qualified_column_name} AS CHAR)"
7
+ is_mysql = connection.class.name =~ /mysql/i
8
+ target_type = is_mysql ? 'CHAR' : 'TEXT' # CHAR is only 1 character in PostgreSQL
9
+ column_as_string = "CAST(#{qualified_column_name} AS #{target_type})"
8
10
  "#{column_as_string} = ?"
9
11
  end
10
12
  bindings = [identifier] * query_clauses.size
11
13
  where([query_clauses.join(' OR '), *bindings]).first
12
14
  end
13
-
15
+
14
16
  def self.find_by_anything!(identifier)
15
17
  find_by_anything(identifier) or raise ActiveRecord::RecordNotFound, "No column equals \"#{identifier}\""
16
18
  end
17
19
 
18
20
  end
19
-
@@ -0,0 +1,5 @@
1
+ # This empty file allows all robots, see http://www.robotstxt.org/robotstxt.html
2
+ #
3
+ # To exclude all robots from the entire domain, uncomment this:
4
+ # User-agent: *
5
+ # Disallow: /
@@ -1,4 +1,4 @@
1
- FactoryGirl.define do
1
+ FactoryBot.define do
2
2
 
3
3
  factory :EXAMPLE do
4
4
  status 'pending'
@@ -0,0 +1,20 @@
1
+ RSpec.configure do |config|
2
+ config.before(:suite) do
3
+ DatabaseCleaner.clean_with(:deletion)
4
+ end
5
+
6
+ config.around do |example|
7
+ DatabaseCleaner.strategy = case
8
+ when example.metadata[:transaction] == false
9
+ :deletion
10
+ when example.metadata[:js] == true
11
+ :deletion
12
+ else
13
+ :transaction
14
+ end
15
+
16
+ DatabaseCleaner.start
17
+ example.run
18
+ DatabaseCleaner.clean
19
+ end
20
+ end
@@ -0,0 +1,3 @@
1
+ RSpec.configure do |config|
2
+ config.include FactoryBot::Syntax::Methods
3
+ end
@@ -0,0 +1,6 @@
1
+ include ActionDispatch::TestProcess
2
+
3
+ def fixture_file(file_name)
4
+ file_path = Rails.root.join('spec/assets', file_name)
5
+ File.open(file_path)
6
+ end
@@ -0,0 +1,15 @@
1
+ # We initialize all Postgres sequences with high values so that tests setting
2
+ # specific ids will not accidentally reuse the same ids
3
+
4
+ RSpec.configure do |config|
5
+ config.before(:suite) do
6
+
7
+ connection = ActiveRecord::Base.connection
8
+ sequences = connection.select_values("SELECT relname FROM pg_class WHERE pg_class.relkind = 'S'")
9
+
10
+ sequences.each do |sequence|
11
+ connection.execute("SELECT setval('#{sequence}', 1000000)")
12
+ end
13
+
14
+ end
15
+ end
@@ -0,0 +1,3 @@
1
+ RSpec.configure do |config|
2
+ config.after { Timecop.return }
3
+ end