katapult 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/.rspec +2 -0
  4. data/.ruby-version +1 -0
  5. data/Gemfile +4 -0
  6. data/Guardfile +11 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +122 -0
  9. data/Rakefile +14 -0
  10. data/bin/katapult +44 -0
  11. data/features/binary.feature +48 -0
  12. data/features/configuration.feature +24 -0
  13. data/features/katapult.feature +201 -0
  14. data/features/model.feature +203 -0
  15. data/features/navigation.feature +80 -0
  16. data/features/step_definitions/db_steps.rb +8 -0
  17. data/features/step_definitions/file_steps.rb +14 -0
  18. data/features/step_definitions/katapult_steps.rb +14 -0
  19. data/features/step_definitions/rails_steps.rb +44 -0
  20. data/features/step_definitions/test_steps.rb +7 -0
  21. data/features/support/env.rb +16 -0
  22. data/features/wui.feature +319 -0
  23. data/katapult.gemspec +35 -0
  24. data/katapult.png +0 -0
  25. data/lib/generators/katapult/basics/basics_generator.rb +95 -0
  26. data/lib/generators/katapult/basics/templates/Gemfile +76 -0
  27. data/lib/generators/katapult/basics/templates/app/assets/stylesheets/application.css.sass +6 -0
  28. data/lib/generators/katapult/basics/templates/app/assets/stylesheets/application/blocks/_all.css.sass +4 -0
  29. data/lib/generators/katapult/basics/templates/app/assets/stylesheets/application/blocks/_items.css.sass +11 -0
  30. data/lib/generators/katapult/basics/templates/app/assets/stylesheets/application/blocks/_layout.css.sass +26 -0
  31. data/lib/generators/katapult/basics/templates/app/assets/stylesheets/application/blocks/_navigation.css.sass +11 -0
  32. data/lib/generators/katapult/basics/templates/app/assets/stylesheets/application/blocks/_tools.css.sass +12 -0
  33. data/lib/generators/katapult/basics/templates/config/database.sample.yml +16 -0
  34. data/lib/generators/katapult/basics/templates/config/database.yml +13 -0
  35. data/lib/generators/katapult/basics/templates/config/spring.rb +3 -0
  36. data/lib/generators/katapult/basics/templates/features/support/env-custom.rb +3 -0
  37. data/lib/generators/katapult/basics/templates/features/support/paths.rb +47 -0
  38. data/lib/generators/katapult/cucumber_features/cucumber_features_generator.rb +23 -0
  39. data/lib/generators/katapult/cucumber_features/templates/feature.feature +59 -0
  40. data/lib/generators/katapult/haml/haml_generator.rb +90 -0
  41. data/lib/generators/katapult/haml/templates/_form.html.haml +38 -0
  42. data/lib/generators/katapult/haml/templates/app/views/layouts/application.html.haml +25 -0
  43. data/lib/generators/katapult/haml/templates/custom_action.html.haml +5 -0
  44. data/lib/generators/katapult/haml/templates/edit.html.haml +4 -0
  45. data/lib/generators/katapult/haml/templates/index.html.haml +29 -0
  46. data/lib/generators/katapult/haml/templates/new.html.haml +4 -0
  47. data/lib/generators/katapult/haml/templates/show.html.haml +41 -0
  48. data/lib/generators/katapult/install/install_generator.rb +14 -0
  49. data/lib/generators/katapult/install/templates/lib/katapult/application_model.rb +18 -0
  50. data/lib/generators/katapult/model/model_generator.rb +59 -0
  51. data/lib/generators/katapult/model/templates/app/models/shared/does_flag.rb +32 -0
  52. data/lib/generators/katapult/model/templates/model.rb +21 -0
  53. data/lib/generators/katapult/model_specs/model_specs_generator.rb +51 -0
  54. data/lib/generators/katapult/model_specs/templates/model_spec.rb +34 -0
  55. data/lib/generators/katapult/navigation/navigation_generator.rb +25 -0
  56. data/lib/generators/katapult/navigation/templates/app/models/navigation.rb +12 -0
  57. data/lib/generators/katapult/transform/transform_generator.rb +47 -0
  58. data/lib/generators/katapult/w_u_i/templates/_route.rb +13 -0
  59. data/lib/generators/katapult/w_u_i/templates/controller.rb +106 -0
  60. data/lib/generators/katapult/w_u_i/w_u_i_generator.rb +57 -0
  61. data/lib/katapult.rb +5 -0
  62. data/lib/katapult/action.rb +44 -0
  63. data/lib/katapult/application_model.rb +45 -0
  64. data/lib/katapult/attribute.rb +83 -0
  65. data/lib/katapult/element.rb +72 -0
  66. data/lib/katapult/generator.rb +28 -0
  67. data/lib/katapult/model.rb +33 -0
  68. data/lib/katapult/navigation.rb +22 -0
  69. data/lib/katapult/parser.rb +39 -0
  70. data/lib/katapult/util.rb +16 -0
  71. data/lib/katapult/version.rb +3 -0
  72. data/lib/katapult/wui.rb +77 -0
  73. data/script/console +16 -0
  74. data/spec/action_spec.rb +44 -0
  75. data/spec/attribute_spec.rb +48 -0
  76. data/spec/model_spec.rb +18 -0
  77. data/spec/spec_helper.rb +19 -0
  78. data/spec/util_spec.rb +23 -0
  79. data/spec/wui_spec.rb +49 -0
  80. metadata +253 -0
@@ -0,0 +1,203 @@
1
+ Feature: Generate Models
2
+
3
+ Background:
4
+ Given a pristine Rails application
5
+ And I install katapult
6
+ And I generate katapult basics
7
+
8
+
9
+ Scenario: Generate ActiveRecord Model
10
+ When I overwrite "lib/katapult/application_model.rb" with:
11
+ """
12
+ model 'Car'
13
+ """
14
+ And I successfully transform the application model
15
+ Then the file "app/models/car.rb" should contain exactly:
16
+ """
17
+ class Car < ActiveRecord::Base
18
+
19
+ def to_s
20
+ "Car##{id}"
21
+ end
22
+ end
23
+
24
+ """
25
+ And there should be a migration with:
26
+ """
27
+ class CreateCars < ActiveRecord::Migration
28
+ def change
29
+ create_table :cars do |t|
30
+
31
+ t.timestamps
32
+ end
33
+ end
34
+ end
35
+
36
+ """
37
+ And the file "spec/models/car_spec.rb" should contain exactly:
38
+ """
39
+ require 'rails_helper'
40
+
41
+ describe Car do
42
+
43
+ describe '#to_s' do
44
+ it 'returns its class name with its id' do
45
+ subject.id = 17
46
+ expect(subject.to_s).to eql("Car#17")
47
+ end
48
+ end
49
+
50
+ end
51
+
52
+ """
53
+
54
+
55
+ Scenario: Generate ActiveRecord Model with attributes
56
+ When I overwrite "lib/katapult/application_model.rb" with:
57
+ """
58
+ model 'Person' do |person|
59
+
60
+ # Basic types
61
+ person.attr :age, type: :integer
62
+ person.attr :nick, type: :string
63
+ person.attr :hobby # string is default
64
+
65
+ # Special types
66
+ person.attr :email # type is detected as email
67
+ person.attr :income, type: :money
68
+ person.attr :homepage, type: :url, default: 'http://www.makandra.de'
69
+ person.attr :locked, type: :flag, default: false
70
+ end
71
+ """
72
+ And I successfully transform the application model
73
+ Then the file "app/models/person.rb" should contain exactly:
74
+ """
75
+ class Person < ActiveRecord::Base
76
+ include DoesFlag[:locked, default: false]
77
+ has_defaults({:homepage=>"http://www.makandra.de"})
78
+
79
+ def to_s
80
+ age.to_s
81
+ end
82
+ end
83
+
84
+ """
85
+ And there should be a migration with:
86
+ """
87
+ class CreatePeople < ActiveRecord::Migration
88
+ def change
89
+ create_table :people do |t|
90
+ t.integer :age
91
+ t.string :nick
92
+ t.string :hobby
93
+ t.string :email
94
+ t.decimal :income, precision: 10, scale: 2
95
+ t.string :homepage
96
+ t.boolean :locked
97
+
98
+ t.timestamps
99
+ end
100
+ end
101
+ end
102
+
103
+ """
104
+ And the file "spec/models/person_spec.rb" should contain exactly:
105
+ """
106
+ require 'rails_helper'
107
+
108
+ describe Person do
109
+
110
+ describe '#to_s' do
111
+ it 'returns the #age attribute' do
112
+ subject.age = 778
113
+ expect(subject.to_s).to eql("778")
114
+ end
115
+ end
116
+
117
+ describe '#homepage' do
118
+
119
+ it 'has a default' do
120
+ expect( subject.homepage ).to eql("http://www.makandra.de")
121
+ end
122
+ end
123
+
124
+ describe '#locked' do
125
+
126
+ it 'has a default' do
127
+ expect( subject.locked ).to eql(false)
128
+ end
129
+ end
130
+
131
+ end
132
+
133
+ """
134
+ And the specs should pass
135
+
136
+
137
+ Scenario: Get a helpful error message when an attribute has an unknown option
138
+ When I overwrite "lib/katapult/application_model.rb" with:
139
+ """
140
+ model 'Person' do |person|
141
+ person.attr :x, invalid_option: 'here'
142
+ end
143
+ """
144
+ And I transform the application model
145
+ Then the output should contain "Katapult::Attribute does not support option :invalid_option. (Katapult::Element::UnknownOptionError)"
146
+
147
+
148
+ Scenario: Specify assignable values
149
+ When I overwrite "lib/katapult/application_model.rb" with:
150
+ """
151
+ model 'Person' do |person|
152
+ person.attr :age, type: :integer, assignable_values: 9..99
153
+ person.attr :hobby, assignable_values: %w[soccer baseball], default: 'soccer', allow_blank: true
154
+ end
155
+ """
156
+ And I successfully transform the application model
157
+ Then the file "app/models/person.rb" should contain exactly:
158
+ """
159
+ class Person < ActiveRecord::Base
160
+ assignable_values_for :age, {} do
161
+ 9..99
162
+ end
163
+ assignable_values_for :hobby, {:allow_blank=>true, :default=>"soccer"} do
164
+ ["soccer", "baseball"]
165
+ end
166
+
167
+ def to_s
168
+ age.to_s
169
+ end
170
+ end
171
+
172
+ """
173
+ And the file "spec/models/person_spec.rb" should contain exactly:
174
+ """
175
+ require 'rails_helper'
176
+
177
+ describe Person do
178
+
179
+ describe '#to_s' do
180
+ it 'returns the #age attribute' do
181
+ subject.age = 9
182
+ expect(subject.to_s).to eql("9")
183
+ end
184
+ end
185
+
186
+ describe '#age' do
187
+ it { is_expected.to allow_value(99).for(:age) }
188
+ it { is_expected.to_not allow_value(100).for(:age) }
189
+ end
190
+
191
+ describe '#hobby' do
192
+ it { is_expected.to allow_value("baseball").for(:hobby) }
193
+ it { is_expected.to_not allow_value("baseball-unassignable").for(:hobby) }
194
+
195
+ it 'has a default' do
196
+ expect( subject.hobby ).to eql("soccer")
197
+ end
198
+ end
199
+
200
+ end
201
+
202
+ """
203
+ And the specs should pass
@@ -0,0 +1,80 @@
1
+ Feature: Navigation
2
+
3
+ Background:
4
+ Given a pristine Rails application
5
+ And I install katapult
6
+ And I generate katapult basics
7
+
8
+
9
+ Scenario: Generate navigation
10
+
11
+ The navigation is rendered from all WUIs in the application model. It
12
+ consists of links to their index pages.
13
+
14
+ When I overwrite "lib/katapult/application_model.rb" with:
15
+ """
16
+ model 'Customer' do |customer|
17
+ customer.attr :name
18
+ end
19
+
20
+ wui 'Customer', model: 'Customer' do |wui|
21
+ wui.action :index
22
+ wui.action :show
23
+ wui.action :create
24
+ wui.action :update
25
+ wui.action :destroy
26
+ end
27
+
28
+ navigation 'main'
29
+ """
30
+ And I successfully transform the application model
31
+ Then the file "app/models/navigation.rb" should contain exactly:
32
+ """
33
+ class Navigation
34
+ include Navy::Description
35
+
36
+ navigation :main do
37
+ section :customers, "Customers", customers_path
38
+ end
39
+
40
+ end
41
+
42
+ """
43
+ And the file "app/views/layouts/application.html.haml" should contain:
44
+ """
45
+ = render_navigation Navigation.main
46
+ """
47
+ And the file "app/controllers/customers_controller.rb" should contain:
48
+ """
49
+ before_filter :set_section
50
+ """
51
+ And the file "app/controllers/customers_controller.rb" should contain:
52
+ """
53
+ def set_section
54
+ in_sections :customers
55
+ end
56
+ """
57
+
58
+
59
+ Scenario: Homepage (aka root route) is set automatically
60
+
61
+ The first WUI with an index action is set as home page
62
+
63
+ When I overwrite "lib/katapult/application_model.rb" with:
64
+ """
65
+ model 'Customer'
66
+ model 'Elephant'
67
+
68
+ wui 'Elephant' do |wui|
69
+ wui.action :trumpet, scope: :member, method: :post
70
+ end
71
+
72
+ wui 'Customer' do |wui|
73
+ wui.crud
74
+ end
75
+ """
76
+ And I successfully transform the application model
77
+ Then the file "config/routes.rb" should contain:
78
+ """
79
+ root 'customers#index'
80
+ """
@@ -0,0 +1,8 @@
1
+ Then(/^a db table named "(.*?)" should exist$/) do |table|
2
+ require 'sequel'
3
+ db_path = "sqlite://#{current_dir}/db/development.sqlite3"
4
+
5
+ Sequel.connect(db_path) { |db|
6
+ db.table_exists?(table)
7
+ }.should == true
8
+ end
@@ -0,0 +1,14 @@
1
+ When /^I replace "(.*?)" with "(.*?)" inside "(.*?)"$/ do |a, b, path|
2
+ in_current_dir do
3
+ content = File.read(path)
4
+ content.gsub! a, b
5
+ File.open(path, 'w') { |file| file.puts(content) }
6
+ end
7
+ end
8
+
9
+ Then /^there should be a migration with:$/ do |migration|
10
+ migrations_path = File.join(current_dir, 'db', 'migrate', '*.rb')
11
+
12
+ all_migrations = Dir.glob(migrations_path).map(&File.method(:read)).join
13
+ all_migrations.should include(migration)
14
+ end
@@ -0,0 +1,14 @@
1
+ When /^I install katapult$/ do
2
+ append_to_file 'Gemfile', "gem 'katapult', path: '../../..'"
3
+ run_simple('bin/rails generate katapult:install')
4
+ end
5
+
6
+ # This step is required for any feature because it generates config/database.yml
7
+ When /^I generate katapult basics$/ do
8
+ run_simple('bin/rails generate katapult:basics')
9
+ end
10
+
11
+ When /^I( successfully)? transform the application model$/ do |require_success|
12
+ # the second parameter would be true when not specified
13
+ run_simple('bin/rails generate katapult:transform lib/katapult/application_model.rb', !!require_success)
14
+ end
@@ -0,0 +1,44 @@
1
+ module KatapultRailsHelper
2
+
3
+ def with_aruba_timeout(timeout, &block)
4
+ original_aruba_timeout = @aruba_timeout_seconds
5
+ @aruba_timeout_seconds = timeout
6
+
7
+ block.call
8
+ ensure
9
+ @aruba_timeout_seconds = original_aruba_timeout
10
+ end
11
+
12
+ def create_cached_app(name)
13
+ job = 'Cached Rails app generation'
14
+ rails_new_command = "bundle exec rails new #{name} --skip-test-unit --skip-bundle --database mysql"
15
+
16
+ puts "#{job} started (in #{Dir.pwd})"
17
+ system(rails_new_command) or raise "#{job} failed"
18
+ puts "#{job} done."
19
+ end
20
+
21
+ def ensure_bundled(path)
22
+ Dir.chdir(path) do
23
+ Bundler.with_clean_env do
24
+ system('bundle check &> /dev/null') or system('bundle install')
25
+ end
26
+ end
27
+ end
28
+
29
+ end
30
+ World(KatapultRailsHelper)
31
+
32
+
33
+ Given /^a pristine Rails application$/ do
34
+ with_aruba_timeout(120) do
35
+ Dir.chdir('tmp') do
36
+ create_cached_app('cached_test_app') unless File.directory?('cached_test_app')
37
+ ensure_bundled('cached_test_app')
38
+ end
39
+
40
+ # copy cached app to aruba directory
41
+ FileUtils.cp_r('tmp/cached_test_app', File.join(current_dir, 'katapult_test_app'))
42
+ cd 'katapult_test_app' # Aruba::Api method
43
+ end
44
+ end
@@ -0,0 +1,7 @@
1
+ Then /^the specs should pass$/ do
2
+ run_simple('bin/rspec')
3
+ end
4
+
5
+ Then /^the features should pass$/ do
6
+ run_simple('bin/cucumber')
7
+ end
@@ -0,0 +1,16 @@
1
+ require 'aruba/cucumber'
2
+ require 'pry'
3
+
4
+ # Make sure tests use the correct katapult gem
5
+ ENV['KATAPULT_GEMFILE_OPTIONS'] = ", path: '../../..'"
6
+
7
+ Before do
8
+ @aruba_timeout_seconds = 30
9
+
10
+ unset_bundler_env_vars
11
+ run_simple 'spring stop # Clean up in case the After hook did not run'
12
+ end
13
+
14
+ After do
15
+ run_simple 'spring stop'
16
+ end
@@ -0,0 +1,319 @@
1
+ Feature: Web User Interface
2
+
3
+ Background:
4
+ Given a pristine Rails application
5
+ And I install katapult
6
+ And I generate katapult basics
7
+
8
+
9
+ Scenario: Generate a Web User Interface
10
+ When I overwrite "lib/katapult/application_model.rb" with:
11
+ """
12
+ model 'Customer' do |customer|
13
+ customer.attr :name
14
+ customer.attr :age, type: :integer
15
+
16
+ customer.attr :email
17
+ customer.attr :revenue, type: :money
18
+ customer.attr :homepage, type: :url, default: 'http://www.makandra.de'
19
+ customer.attr :locked, type: :flag, default: false
20
+ end
21
+
22
+ wui 'Customer', model: 'Customer' do |wui|
23
+ wui.crud
24
+ wui.action :get_member, method: :get, scope: :member
25
+ wui.action :post_member, method: :post, scope: :member
26
+ wui.action :get_collection, method: :get, scope: :collection
27
+ wui.action :put_collection, method: :put, scope: :collection
28
+ end
29
+ """
30
+ And I successfully transform the application model
31
+ Then the file "app/controllers/customers_controller.rb" should contain exactly:
32
+ """
33
+ class CustomersController < ApplicationController
34
+
35
+ def index
36
+ load_customers
37
+ end
38
+
39
+ def show
40
+ load_customer
41
+ end
42
+
43
+ def new
44
+ build_customer
45
+ end
46
+
47
+ def create
48
+ build_customer
49
+ save_customer or render :new
50
+ end
51
+
52
+ def edit
53
+ load_customer
54
+ build_customer
55
+ end
56
+
57
+ def update
58
+ load_customer
59
+ build_customer
60
+ save_customer or render :edit
61
+ end
62
+
63
+ def destroy
64
+ load_customer
65
+ @customer.destroy
66
+ redirect_to customers_path
67
+ end
68
+
69
+ def get_member
70
+ load_customer
71
+ end
72
+
73
+ def post_member
74
+ load_customer
75
+ redirect_to @customer
76
+ end
77
+
78
+ def get_collection
79
+ load_customers
80
+ end
81
+
82
+ def put_collection
83
+ load_customers
84
+ redirect_to customers_path
85
+ end
86
+
87
+ private
88
+
89
+ def load_customers
90
+ @customers ||= customer_scope.to_a
91
+ end
92
+
93
+ def load_customer
94
+ @customer ||= customer_scope.find(params[:id])
95
+ end
96
+
97
+ def build_customer
98
+ @customer ||= customer_scope.build
99
+ @customer.attributes = customer_params
100
+ end
101
+
102
+ def save_customer
103
+ if @customer.save
104
+ redirect_to @customer
105
+ end
106
+ end
107
+
108
+ def customer_params
109
+ customer_params = params[:customer]
110
+ customer_params ? customer_params.permit([:name, :age, :email, :revenue, :homepage, :locked]) : {}
111
+ end
112
+
113
+ def customer_scope
114
+ Customer.scoped
115
+ end
116
+
117
+ end
118
+
119
+ """
120
+ And the file "config/routes.rb" should contain:
121
+ """
122
+ resources :customers, only: [:index, :show, :new, :create, :edit, :update, :destroy] do
123
+ member do
124
+ get 'get_member'
125
+ post 'post_member'
126
+ end
127
+ collection do
128
+ get 'get_collection'
129
+ put 'put_collection'
130
+ end
131
+ end
132
+ """
133
+ And the file "app/views/customers/index.html.haml" should contain exactly:
134
+ """
135
+ %h1
136
+ Customers
137
+
138
+ .tools
139
+ = link_to 'Add customer', new_customer_path, class: 'tools__button is_primary'
140
+ = link_to 'Get Collection', get_collection_customers_path, class: 'tools__button'
141
+ = link_to 'Put Collection', put_collection_customers_path, class: 'tools__button'
142
+
143
+ - if @customers.any?
144
+ %table.items
145
+ - @customers.each do |customer|
146
+ %tr
147
+ %td
148
+ = link_to customer.to_s, customer, class: 'hyperlink'
149
+ %td
150
+ .items__actions
151
+ = link_to 'Edit', edit_customer_path(customer), class: 'items__action'
152
+ = link_to 'Destroy', customer_path(customer), method: :delete, class: 'items__action', confirm: 'Really destroy?'
153
+ = link_to 'Get Member', get_member_customer_path(customer), class: 'items__action'
154
+ = link_to 'Post Member', post_member_customer_path(customer), class: 'items__action', method: :post
155
+
156
+ - else
157
+ %p.help-block
158
+ There are no customers yet.
159
+
160
+ """
161
+ And the file "app/views/customers/show.html.haml" should contain exactly:
162
+ """
163
+ %h1
164
+ = @customer.to_s
165
+
166
+ .tools
167
+ = link_to 'All customers', customers_path, class: 'tools__button'
168
+ = link_to 'Edit', edit_customer_path(@customer), class: 'tools__button is_primary'
169
+ = link_to 'Destroy', customer_path(@customer), method: :delete, class: 'tools__button', confirm: 'Really destroy?'
170
+ = link_to 'Get Member', get_member_customer_path(@customer), class: 'tools__button'
171
+ = link_to 'Post Member', post_member_customer_path(@customer), class: 'tools__button', method: :post
172
+
173
+ %dl.values
174
+ %dt
175
+ = Customer.human_attribute_name(:name)
176
+ %dd
177
+ = @customer.name
178
+ %dt
179
+ = Customer.human_attribute_name(:age)
180
+ %dd
181
+ = @customer.age
182
+ %dt
183
+ = Customer.human_attribute_name(:email)
184
+ %dd
185
+ = mail_to @customer.email, nil, class: 'hyperlink'
186
+ %dt
187
+ = Customer.human_attribute_name(:revenue)
188
+ %dd
189
+ = @customer.revenue
190
+
191
+ %dt
192
+ = Customer.human_attribute_name(:homepage)
193
+ %dd
194
+ = link_to @customer.homepage, @customer.homepage, class: 'hyperlink'
195
+ %dt
196
+ = Customer.human_attribute_name(:locked)
197
+ %dd
198
+ = @customer.locked ? 'Yes' : 'No'
199
+
200
+ """
201
+ And the file "app/views/customers/new.html.haml" should contain exactly:
202
+ """
203
+ %h1
204
+ Add customer
205
+
206
+ = render 'form'
207
+
208
+ """
209
+ And the file "app/views/customers/edit.html.haml" should contain exactly:
210
+ """
211
+ %h1
212
+ = @customer.to_s
213
+
214
+ = render 'form'
215
+
216
+ """
217
+ And the file "app/views/customers/_form.html.haml" should contain exactly:
218
+ """
219
+ = form_for @customer do |form|
220
+
221
+ %dl.controls
222
+ %dt
223
+ = form.label :name
224
+ %dd
225
+ = form.text_field :name
226
+ %dt
227
+ = form.label :age
228
+ %dd
229
+ = form.number_field :age
230
+ %dt
231
+ = form.label :email
232
+ %dd
233
+ = form.email_field :email
234
+ %dt
235
+ = form.label :revenue
236
+ %dd
237
+ = form.number_field :revenue
238
+
239
+ %dt
240
+ = form.label :homepage
241
+ %dd
242
+ = form.url_field :homepage
243
+ %dt
244
+ = form.label :locked
245
+ %dd
246
+ = form.check_box :locked
247
+
248
+ .tools
249
+ = form.submit 'Save', class: 'tools__button is_primary'
250
+ - cancel_path = @customer.new_record? ? customers_path : customer_path(@customer)
251
+ = link_to 'Cancel', cancel_path, class: 'tools__button'
252
+
253
+ """
254
+ And the file "app/views/customers/get_member.html.haml" should contain exactly:
255
+ """
256
+ %h1
257
+ Get Member
258
+
259
+ .tools
260
+ = link_to 'All customers', customers_path, class: 'tools__button'
261
+
262
+ """
263
+ But a file named "app/views/customers/post_member.html.haml" should not exist
264
+ And the file "app/views/customers/get_collection.html.haml" should contain exactly:
265
+ """
266
+ %h1
267
+ Get Collection
268
+
269
+ .tools
270
+ = link_to 'All customers', customers_path, class: 'tools__button'
271
+
272
+ """
273
+ But a file named "app/views/customers/put_collection.html.haml" should not exist
274
+ And the file "features/customers.feature" should contain exactly:
275
+ """
276
+ Feature: Customers
277
+
278
+ Scenario: CRUD customers
279
+ Given I am on the list of customers
280
+
281
+ # create
282
+ When I follow "Add customer"
283
+ And I fill in "Name" with "name-string"
284
+ And I fill in "Age" with "778"
285
+ And I fill in "Email" with "email@example.com"
286
+ And I fill in "Revenue" with "2.21"
287
+ And I fill in "Homepage" with "homepage.example.com"
288
+ And I check "Locked"
289
+ And I press "Save"
290
+
291
+ # read
292
+ Then I should be on the page for the customer above
293
+ And I should see "name-string"
294
+ And I should see "778"
295
+ And I should see "email@example.com"
296
+ And I should see "2.21"
297
+ And I should see "homepage.example.com"
298
+ And I should see "Locked Yes"
299
+
300
+ # update
301
+ When I follow "Edit"
302
+ Then I should be on the form for the customer above
303
+ And the "Name" field should contain "name-string"
304
+ And the "Age" field should contain "778"
305
+ And the "Email" field should contain "email@example.com"
306
+ And the "Revenue" field should contain "2.21"
307
+ And the "Homepage" field should contain "homepage.example.com"
308
+ And the "Locked" checkbox should be checked
309
+
310
+ # destroy
311
+ When I go to the list of customers
312
+ Then I should see "name-string"
313
+
314
+ When I follow "Destroy"
315
+ Then I should be on the list of customers
316
+ But I should not see "name-string"
317
+
318
+ """
319
+ And the features should pass