mundo-pepino 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/COPYING +339 -0
- data/History.txt +4 -0
- data/Manifest.txt +21 -0
- data/README.markdown +492 -0
- data/Rakefile +54 -0
- data/cucumber.yml +1 -0
- data/init.rb +1 -0
- data/lib/mundo_pepino.rb +241 -0
- data/lib/mundo_pepino/definitions/es_ES.rb +420 -0
- data/lib/mundo_pepino/resources_history.rb +214 -0
- data/lib/mundo_pepino/version.rb +10 -0
- data/lib/mundo_pepino/visits_history.rb +13 -0
- data/lib/mundo_pepino_es_ES.rb +2 -0
- data/mundo-pepino.gemspec +34 -0
- data/rails_generators/caracteristica/USAGE +16 -0
- data/rails_generators/caracteristica/caracteristica_generator.rb +126 -0
- data/rails_generators/caracteristica/templates/caracteristica.erb +31 -0
- data/rails_generators/mundo_pepino/USAGE +13 -0
- data/rails_generators/mundo_pepino/mundo_pepino_generator.rb +21 -0
- data/rails_generators/mundo_pepino/templates/mundo_pepino.rake +7 -0
- data/rails_generators/mundo_pepino/templates/mundo_pepino_es_ES.rb +47 -0
- metadata +107 -0
data/Rakefile
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
# gem stuff
|
2
|
+
require 'rubygems'
|
3
|
+
gem 'hoe', '>= 2.1.0'
|
4
|
+
require 'hoe'
|
5
|
+
require 'fileutils'
|
6
|
+
require 'newgem/tasks'
|
7
|
+
require 'lib/mundo_pepino/version'
|
8
|
+
|
9
|
+
Hoe.plugin :newgem
|
10
|
+
|
11
|
+
$hoe = Hoe.spec 'mundo-pepino' do
|
12
|
+
self.summary = 'MundoPepino is a set of reusable step definitions to test Rails apps with Cucumber'
|
13
|
+
self.version = MundoPepino::VERSION::STRING
|
14
|
+
self.developer 'Fernando García Samblas', 'fernando.garcia@the-cocktail.com'
|
15
|
+
self.rubyforge_name = self.name # TODO this is default value
|
16
|
+
self.extra_deps = [['string-mapper','>= 0.1.0'],
|
17
|
+
['cucumber', '>=0.3.102']]
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
|
22
|
+
# build stuff
|
23
|
+
require(File.join(File.dirname(__FILE__), 'features', 'support', 'app', 'config', 'boot'))
|
24
|
+
|
25
|
+
require 'rake'
|
26
|
+
require 'rake/testtask'
|
27
|
+
require 'rake/rdoctask'
|
28
|
+
|
29
|
+
require 'tasks/rails'
|
30
|
+
|
31
|
+
|
32
|
+
unless ARGV.any? {|a| a =~ /^gems/}
|
33
|
+
|
34
|
+
begin
|
35
|
+
require 'cucumber/rake/task'
|
36
|
+
namespace :mundo_pepino do
|
37
|
+
Cucumber::Rake::Task.new({:es_ES => 'db:test:prepare'}) do |t|
|
38
|
+
t.cucumber_opts = "--require features/support/env.rb --require features/step_definitions/mundo_pepino_es_ES.rb --format progress --language es features/es_ES"
|
39
|
+
end
|
40
|
+
|
41
|
+
desc 'Run all MundoPepino features on every supported language'
|
42
|
+
task :all => [:es_ES]
|
43
|
+
end
|
44
|
+
|
45
|
+
task :default => 'mundo_pepino:es_ES'
|
46
|
+
|
47
|
+
rescue LoadError
|
48
|
+
desc 'cucumber rake task not available (cucumber not installed)'
|
49
|
+
task :cucumber do
|
50
|
+
abort 'Cucumber rake task is not available. Be sure to install cucumber as a gem or plugin'
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
data/cucumber.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
default: --require features/support/env.rb --require features/step_definitions/mundo_pepino_es_ES.rb --language es features/es_ES/
|
data/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
$LOAD_PATH.unshift File.expand_path(File.join(File.dirname(__FILE__), 'lib'))
|
data/lib/mundo_pepino.rb
ADDED
@@ -0,0 +1,241 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__)) unless
|
2
|
+
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
3
|
+
|
4
|
+
require 'cucumber/rails/world'
|
5
|
+
require 'mundo_pepino/resources_history'
|
6
|
+
require 'mundo_pepino/visits_history'
|
7
|
+
require 'mundo_pepino/version'
|
8
|
+
|
9
|
+
require 'string-mapper'
|
10
|
+
|
11
|
+
module MundoPepino
|
12
|
+
|
13
|
+
include ResourcesHistory
|
14
|
+
include VisitsHistory
|
15
|
+
|
16
|
+
def real_value_for(v)
|
17
|
+
(v.is_a?(String) ? v.to_real_value : v )
|
18
|
+
end
|
19
|
+
|
20
|
+
def parsed_attributes(raw_attributes)
|
21
|
+
attributes = {}
|
22
|
+
raw_attributes.each do |k, v|
|
23
|
+
if k =~ /^(.+)_id$/
|
24
|
+
if polymorph = raw_attributes.delete($1 + '_type')
|
25
|
+
attributes[$1.to_sym] = polymorph.constantize.find(v.to_i)
|
26
|
+
else
|
27
|
+
attributes[$1.to_sym] = ($1.to_relation_model || $1.camelize.constantize).find(v.to_i)
|
28
|
+
end
|
29
|
+
else
|
30
|
+
attributes[k] = real_value_for(v)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
attributes
|
34
|
+
end
|
35
|
+
|
36
|
+
def create(model, raw_attributes = {})
|
37
|
+
through = raw_attributes.delete(:through)
|
38
|
+
attributes = parsed_attributes(raw_attributes)
|
39
|
+
obj = if defined?(FixtureReplacement)
|
40
|
+
self.send "create_#{model.name.underscore}", attributes
|
41
|
+
elsif defined?(Machinist)
|
42
|
+
model.make attributes
|
43
|
+
elsif defined?(Factory)
|
44
|
+
Factory(model.name.underscore.to_sym, attributes)
|
45
|
+
else
|
46
|
+
model.create! attributes
|
47
|
+
end
|
48
|
+
if(through)
|
49
|
+
create through['model'], through['attributes'].merge(model.name.underscore.to_sym => obj)
|
50
|
+
end
|
51
|
+
obj
|
52
|
+
end
|
53
|
+
|
54
|
+
def find_or_create(model_or_modelo, attributes = {}, options = {})
|
55
|
+
model = if model_or_modelo.is_a?(String)
|
56
|
+
model_or_modelo.to_model
|
57
|
+
else
|
58
|
+
model_or_modelo
|
59
|
+
end
|
60
|
+
if attributes.any?
|
61
|
+
attribs = Hash.new
|
62
|
+
attributes.each do |key, value|
|
63
|
+
if child_model = (key.to_s.to_model || key.to_s.to_relation_model)
|
64
|
+
child = add_resource(child_model, field_for(child_model, 'nombre') => value)
|
65
|
+
field_name = key.to_s.to_relation_model ? key : child_model.name.underscore
|
66
|
+
attribs["#{field_name}_id"] = child.id
|
67
|
+
else
|
68
|
+
attribs[key] = value
|
69
|
+
end
|
70
|
+
end
|
71
|
+
if ((options[:force_creation].nil? || !options[:force_creation]) &&
|
72
|
+
obj = model.find(:first, :conditions => conditions_from_attributes(attribs)))
|
73
|
+
if(through = attribs[:through])
|
74
|
+
create through['model'], through['attributes'].merge(model.name.underscore.to_sym => obj)
|
75
|
+
end
|
76
|
+
obj
|
77
|
+
else
|
78
|
+
create model, attribs
|
79
|
+
end
|
80
|
+
else
|
81
|
+
create model
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def conditions_from_attributes(attributes)
|
86
|
+
attribs = attributes.reject {|k,v| k == :through}
|
87
|
+
[attribs.keys.map{|s| "#{s}=?"}.join(' AND ')] + attribs.values
|
88
|
+
end
|
89
|
+
|
90
|
+
def names_for_simple_creation(model, number, name_or_names, options = {})
|
91
|
+
base_hash = base_hash_for(options)
|
92
|
+
if name_or_names
|
93
|
+
field = field_for(model, 'nombre')
|
94
|
+
names = name_or_names.split(/ ?, | y /)
|
95
|
+
if names.size == number
|
96
|
+
names.map { |name| base_hash.dup.merge(field => name) }
|
97
|
+
else
|
98
|
+
[base_hash.dup.merge(field => name_or_names)] * number
|
99
|
+
end
|
100
|
+
else
|
101
|
+
[base_hash] * number
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def field_for(model, campo = 'nombre')
|
106
|
+
"#{model && model.name}::#{campo}".to_field || campo.to_field
|
107
|
+
end
|
108
|
+
def shouldify(should_or_not)
|
109
|
+
affirmative = 'debo|debo ver|veo|deber[ií]a|deber[íi]a ver|leo|debo leer|deber[ií]a leer'
|
110
|
+
should_or_not =~ /^(#{affirmative})$/i ? :should : :should_not
|
111
|
+
end
|
112
|
+
|
113
|
+
def not_shouldify(should_or_not)
|
114
|
+
shouldify(should_or_not) == :should ? :should_not : :should
|
115
|
+
end
|
116
|
+
|
117
|
+
def relative_page(pagina)
|
118
|
+
if pagina =~ /la siguiente p[aá]gina|la p[aá]gina anterior/i
|
119
|
+
head, current, tail = if last_visited =~ /(.+page=)(\d+)(.*)/
|
120
|
+
[$1, $2.to_i, $3]
|
121
|
+
else
|
122
|
+
[last_visited + '?page=', 1, '']
|
123
|
+
end
|
124
|
+
(pagina =~ /siguiente/ ? current += 1 : current -= 1)
|
125
|
+
head + current.to_s + tail
|
126
|
+
else
|
127
|
+
nil
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
# Cucumber::Model::Table's hashes traduciendo nombres de campo
|
132
|
+
def translated_hashes(step_table, options = {})
|
133
|
+
base_hash = base_hash_for(options)
|
134
|
+
header = step_table[0].map do |campo|
|
135
|
+
field_for(options[:model], campo) || campo
|
136
|
+
end
|
137
|
+
step_table[1..-1].map do |row|
|
138
|
+
h = base_hash.dup
|
139
|
+
row.each_with_index do |v,n|
|
140
|
+
key = header[n]
|
141
|
+
h[key] = v
|
142
|
+
end
|
143
|
+
h
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def base_hash_for(options)
|
148
|
+
if options[:parent]
|
149
|
+
# polymorphic associations
|
150
|
+
if options[:polymorphic_as]
|
151
|
+
{ "#{options[:polymorphic_as]}_id" => options[:parent].id,
|
152
|
+
"#{options[:polymorphic_as]}_type" => options[:parent].class.name }
|
153
|
+
else
|
154
|
+
field_prefix = options[:parent].class.name.underscore
|
155
|
+
if options[:through]
|
156
|
+
{:through => {"model" => eval(options[:through].to_s.classify),
|
157
|
+
"attributes" => {"#{field_prefix}_id" => options[:parent].id}}}
|
158
|
+
else
|
159
|
+
{ "#{field_prefix}_id" => options[:parent].id }
|
160
|
+
end
|
161
|
+
end
|
162
|
+
else
|
163
|
+
{}
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
def campo_to_field(campo, model = nil)
|
168
|
+
unless campo.nil?
|
169
|
+
if field = field_for(model, campo.to_unquoted)
|
170
|
+
field
|
171
|
+
else
|
172
|
+
raise MundoPepino::FieldNotMapped.new(campo)
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
def last_mentioned_should_have_value(campo, valor)
|
178
|
+
res = last_mentioned
|
179
|
+
if child_model = campo.to_model
|
180
|
+
child = child_model.find_by_name(valor)
|
181
|
+
child_field = campo.to_field || child_model.name.underscore
|
182
|
+
(res.send child_field).should == child
|
183
|
+
elsif field = field_for(res.class, campo)
|
184
|
+
(res.send field).to_s.should == valor.to_s
|
185
|
+
else
|
186
|
+
raise FieldNotMapped.new(campo)
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
def last_mentioned_should_have_child(child, name)
|
191
|
+
if child_model = child.to_model
|
192
|
+
child = child_model.find_by_name(name)
|
193
|
+
(last_mentioned.send child_model.table_name).detect do |c|
|
194
|
+
c.id == child.id
|
195
|
+
end.should_not be_nil
|
196
|
+
else
|
197
|
+
raise ModelNotMapped.new(child)
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
def find_field_and_do_with_webrat(action, campo, options = nil)
|
202
|
+
do_with_webrat action, campo.to_unquoted.to_translated, options # a pelo (localización vía labels)
|
203
|
+
rescue Webrat::NotFoundError
|
204
|
+
field = campo_to_field(campo, last_mentioned_model)
|
205
|
+
begin
|
206
|
+
do_with_webrat action, field, options # campo traducido tal cual...
|
207
|
+
rescue Webrat::NotFoundError
|
208
|
+
if singular = last_mentioned_singular # traducido y con el modelo por delante
|
209
|
+
do_with_webrat action, singular + '_' + field.to_s, options # p.e.: user_name
|
210
|
+
else
|
211
|
+
raise
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
def do_with_webrat(action, field, options)
|
217
|
+
if options
|
218
|
+
if options[:path] and options[:content_type]
|
219
|
+
self.send action, field, options[:path], options[:content_type]
|
220
|
+
else
|
221
|
+
self.send action, field, options
|
222
|
+
end
|
223
|
+
else
|
224
|
+
self.send action, field
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
def parent_options(parent, child)
|
229
|
+
options = {:parent => parent}
|
230
|
+
# polymorphic associations
|
231
|
+
if reflections = parent.class.reflect_on_association(child.table_name.to_sym)
|
232
|
+
if reflections.options[:as]
|
233
|
+
options.merge!({:polymorphic_as => reflections.options[:as]})
|
234
|
+
elsif reflections.options[:through]
|
235
|
+
options.merge!({:through => reflections.options[:through]})
|
236
|
+
end
|
237
|
+
end
|
238
|
+
options
|
239
|
+
end
|
240
|
+
|
241
|
+
end
|
@@ -0,0 +1,420 @@
|
|
1
|
+
begin
|
2
|
+
module Cucumber::StepMethods
|
3
|
+
alias_method :Dado, :Given
|
4
|
+
alias_method :Cuando, :When
|
5
|
+
alias_method :Entonces, :Then
|
6
|
+
end
|
7
|
+
rescue
|
8
|
+
# NO NEED TO CREATE ALIASES IN post-0.2 Cucumbers
|
9
|
+
end
|
10
|
+
|
11
|
+
String.add_mapper(:real_value, {
|
12
|
+
/^verdader[oa]$/i => true,
|
13
|
+
/^fals[ao]$/i => false
|
14
|
+
}) { |value| value }
|
15
|
+
String.add_mapper :model
|
16
|
+
String.add_mapper :relation_model
|
17
|
+
String.add_mapper(:field) { |str| :name if str =~ /nombres?/ }
|
18
|
+
String.add_mapper(:url, /^la (portada|home)/i => '/') do |string|
|
19
|
+
string if string =~ /^\/.*$|^https?:\/\//i
|
20
|
+
end
|
21
|
+
|
22
|
+
String.add_mapper(:number, {
|
23
|
+
/^un[oa]?$/i => 1,
|
24
|
+
/^primer[oa]?$/i => 1,
|
25
|
+
:dos => 2,
|
26
|
+
/^segund[oa]?$/i => 2,
|
27
|
+
:tres => 3,
|
28
|
+
/^tercer[ao]/i => 3,
|
29
|
+
:cuatro => 4,
|
30
|
+
/^cuart[ao]/i => 4,
|
31
|
+
:cinco => 5,
|
32
|
+
/^quint[ao]/i => 5}) { |string| string.to_i }
|
33
|
+
String.add_mapper(:crud_action,
|
34
|
+
/^alta$/i => 'new',
|
35
|
+
/^creaci[óo]n$/i => 'new',
|
36
|
+
/^nuev(?:o|a|o\/a|a\/o)$/i => 'new',
|
37
|
+
/^cambio$/i => 'edit',
|
38
|
+
/^modificaci[oó]n(?:es)?$/i => 'edit',
|
39
|
+
/^edici[oó]n$/i => 'edit')
|
40
|
+
String.add_mapper(:month,
|
41
|
+
:enero => 'January',
|
42
|
+
:febrero => 'February',
|
43
|
+
:marzo => 'March',
|
44
|
+
:abril => 'April',
|
45
|
+
:mayo => 'May',
|
46
|
+
:junio => 'June',
|
47
|
+
:julio => 'July',
|
48
|
+
:agosto => 'August',
|
49
|
+
/^sep?tiembre$/i => 'September',
|
50
|
+
:octubre => 'October',
|
51
|
+
:noviembre => 'November',
|
52
|
+
:diciembre => 'December')
|
53
|
+
String.add_mapper(:content_type,
|
54
|
+
/\.png$/ => 'image/png',
|
55
|
+
/\.jpe?g$/ => 'image/jpg',
|
56
|
+
/\.gif$/ => 'image/gif') { |str| 'text/plain' }
|
57
|
+
String.add_mapper(:underscored) { |string| string.gsub(/ +/, '_') }
|
58
|
+
String.add_mapper(:unquoted) { |str| str =~ /^['"](.*)['"]$/ ? $1 : str}
|
59
|
+
String.add_mapper(:translated) { |str|
|
60
|
+
if str =~ /^[a-z_]+\.[a-z_]+[a-z_\.]+$/
|
61
|
+
I18n.translate(str, :default => str)
|
62
|
+
elsif str =~ /^([a-z_]+\.[a-z_]+[a-z_\.]+),(\{.+\})$/
|
63
|
+
I18n.translate($1, {:default => str}.merge(eval($2)))
|
64
|
+
else
|
65
|
+
str
|
66
|
+
end
|
67
|
+
}
|
68
|
+
|
69
|
+
|
70
|
+
|
71
|
+
numero = 'un|una|dos|tres|cuatro|cinco|\d+'
|
72
|
+
cuyo = '(?:cuy[oa]s?|que tienen? como)'
|
73
|
+
# Creación simple con nombre opcional
|
74
|
+
Dado /^(?:que tenemos )?(#{numero}) (?!.+ #{cuyo})(.+?)(?: (?:llamad[oa]s? )?['"](.+)["'])?$/i do |numero, modelo, nombre|
|
75
|
+
if model = modelo.to_unquoted.to_model
|
76
|
+
number = numero.to_number
|
77
|
+
attribs = names_for_simple_creation(model, number, nombre)
|
78
|
+
add_resource(model, attribs, :force_creation => true)
|
79
|
+
else
|
80
|
+
raise MundoPepino::ModelNotMapped.new(modelo)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
# Creación con asignación de valor en campo
|
84
|
+
Dado /^(?:que tenemos )?(#{numero}) (.+) #{cuyo} (.+?) (?:(?:es|son) (?:de )?)?['"](.+)["'](?: .+)?$/i do |numero, modelo, campo, valor|
|
85
|
+
Dado "que tenemos #{numero} #{modelo}"
|
86
|
+
Dado "que dichos #{modelo} tienen como #{campo} '#{valor}'"
|
87
|
+
end
|
88
|
+
|
89
|
+
Dado /^(?:que tenemos )?(?:el|la|los|las|el\/la|los\/las) (?:siguientes? )?(.+):$/ do |modelo, tabla|
|
90
|
+
model = modelo.to_unquoted.to_model
|
91
|
+
add_resource model, translated_hashes(tabla.raw, :model => model), :force_creation => true
|
92
|
+
end
|
93
|
+
|
94
|
+
Dado /^que (?:el|la) (.+) ['"](.+)["'] tiene como (.+) ['"](.+)["'](?: \w+)?$/ do |modelo, nombre, campo, valor|
|
95
|
+
if resource = last_mentioned_of(modelo, nombre)
|
96
|
+
if field = field_for(resource.class, campo)
|
97
|
+
resource.update_attribute field, real_value_for(valor)
|
98
|
+
pile_up resource
|
99
|
+
else
|
100
|
+
raise MundoPepino::FieldNotMapped.new(campo)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
Dado /^que dich[oa]s? (.+) tienen? como (.+) ['"](.+)["'](?:.+)?$/i do |modelo, campo, valor|
|
106
|
+
if res = last_mentioned_of(modelo)
|
107
|
+
resources, field, values = resources_array_field_and_values(res, campo, valor)
|
108
|
+
if field
|
109
|
+
resources.each_with_index do |r, i|
|
110
|
+
r.update_attribute field, real_value_for(values[i])
|
111
|
+
end
|
112
|
+
pile_up res
|
113
|
+
else
|
114
|
+
raise MundoPepino::FieldNotMapped.new(campo)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
Dado /^que dich[oa]s? (.+) tienen? (un|una|dos|tres|cuatro|cinco|\d+) (.+?)(?: (?:llamad[oa]s? )?['"](.+)["'])?$/i do |modelo_padre, numero, modelo_hijos, nombres|
|
120
|
+
if mentioned = last_mentioned_of(modelo_padre.to_unquoted)
|
121
|
+
children_model = modelo_hijos.to_unquoted.to_model
|
122
|
+
resources = (mentioned.is_a?(Array) ? mentioned : [mentioned])
|
123
|
+
resources.each do |resource|
|
124
|
+
attribs = names_for_simple_creation(children_model,
|
125
|
+
numero.to_number, nombres, parent_options(resource, children_model))
|
126
|
+
add_resource children_model, attribs, :force_creation => nombres.nil?
|
127
|
+
end
|
128
|
+
pile_up mentioned
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
Dado /^que dich[ao]s? (.+) tienen? (?:el|la|los|las) siguientes? (.+):$/i do |modelo_padre, modelo_hijos, tabla|
|
133
|
+
if mentioned = last_mentioned_of(modelo_padre.to_unquoted)
|
134
|
+
children_model = modelo_hijos.to_unquoted.to_model
|
135
|
+
resources = (mentioned.is_a?(Array) ? mentioned : [mentioned])
|
136
|
+
resources.each do |resource|
|
137
|
+
add_resource children_model,
|
138
|
+
translated_hashes(tabla.raw, parent_options(resource, children_model))
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
|
144
|
+
###############################################################################
|
145
|
+
|
146
|
+
pagina_re = '(?:p[áa]gina|portada|[íi]ndice|listado|colecci[óo]n)'
|
147
|
+
Cuando /^(?:que )?visito (?:el|la) #{pagina_re} de ([\w]+|['"][\w ]+["'])$/i do |modelo_en_crudo|
|
148
|
+
modelo = modelo_en_crudo.to_unquoted
|
149
|
+
if model = modelo.to_model
|
150
|
+
pile_up model.new
|
151
|
+
do_visit eval("#{model.table_name}_path")
|
152
|
+
elsif url = "la página de #{modelo_en_crudo}".to_url
|
153
|
+
do_visit url
|
154
|
+
else
|
155
|
+
raise MundoPepino::ModelNotMapped.new(modelo)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
Cuando /^(?:que )?visito (?:el|la) #{pagina_re} (?:del|de la) (.+) ['"](.+)["']$/i do |modelo, nombre|
|
160
|
+
if resource = last_mentioned_of(modelo, nombre)
|
161
|
+
do_visit eval("#{resource.class.name.underscore}_path(resource)")
|
162
|
+
else
|
163
|
+
raise MundoPepino::ResourceNotFound.new("model #{modelo}, name #{nombre}")
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
Cuando /^(?:que )?visito la p[áa]gina de (?!la)([\w\/]+) (?:de |de la |del )?(.+?)(?: (['"].+["']))?$/i do |accion, modelo, nombre|
|
168
|
+
action = accion.to_crud_action or raise(MundoPepino::CrudActionNotMapped.new(accion))
|
169
|
+
if action != 'new'
|
170
|
+
nombre, modelo = modelo, nil unless nombre
|
171
|
+
resource = if modelo && modelo.to_unquoted.to_model
|
172
|
+
last_mentioned_of(modelo, nombre.to_unquoted)
|
173
|
+
else
|
174
|
+
last_mentioned_called(nombre.to_unquoted)
|
175
|
+
end
|
176
|
+
if resource
|
177
|
+
do_visit eval("#{action}_#{resource.mr_singular}_path(resource)")
|
178
|
+
else
|
179
|
+
MundoPepino::ResourceNotFound.new("model #{modelo}, name #{nombre}")
|
180
|
+
end
|
181
|
+
else
|
182
|
+
model = modelo.to_unquoted.to_model or raise(MundoPepino::ModelNotMapped.new(modelo))
|
183
|
+
pile_up model.new
|
184
|
+
do_visit eval("#{action}_#{model.name.underscore}_path")
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
Cuando /^(?:que )?visito su (?:p[áa]gina|portada)$/i do
|
189
|
+
do_visit last_mentioned_url
|
190
|
+
end
|
191
|
+
|
192
|
+
negative_lookahead = '(?:la|el) \w+ del? |su p[aá]gina|su portada'
|
193
|
+
Cuando /^(?:que )?visito (?!#{negative_lookahead})(.+)$/i do |pagina|
|
194
|
+
do_visit pagina.to_unquoted.to_url
|
195
|
+
end
|
196
|
+
|
197
|
+
Cuando /^(?:que )?(?:pulso|pincho) (?:en )?el bot[oó]n (.+)$/i do |boton|
|
198
|
+
click_button(boton.to_unquoted.to_translated)
|
199
|
+
end
|
200
|
+
|
201
|
+
Cuando /^(?:que )?(?:pulso|pincho) (?:en )?el (enlace|enlace ajax|enlace con efectos) (.+)$/i do |tipo, enlace|
|
202
|
+
options = {}
|
203
|
+
options[:wait] = case tipo.downcase
|
204
|
+
when 'enlace con efectos' then :effects
|
205
|
+
when 'enlace ajax' then :ajax
|
206
|
+
else :page
|
207
|
+
end
|
208
|
+
click_link(enlace.to_unquoted.to_translated, options)
|
209
|
+
end
|
210
|
+
|
211
|
+
Cuando /^(?:que )?(?:completo|relleno) (.+) con (?:el valor )?['"](.+)["']$/i do |campo, valor|
|
212
|
+
find_field_and_do_with_webrat :fill_in, campo, :with => valor
|
213
|
+
end
|
214
|
+
|
215
|
+
Cuando /^(?:que )?(?:completo|relleno):$/i do |tabla|
|
216
|
+
tabla.raw[1..-1].each do |row|
|
217
|
+
Cuando "relleno \"#{row[0].gsub('"', '\"')}\" con \"#{row[1].gsub('"', '\"')}\""
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
Cuando /^(?:que )?elijo (?:la|el)? ?(.+) ['"](.+)["']$/i do |campo, valor|
|
222
|
+
choose(campo_to_field(campo).to_s + '_' + valor.downcase.to_underscored)
|
223
|
+
end
|
224
|
+
|
225
|
+
Cuando /^(?:que )?marco (?:la|el)? ?(.+)$/i do |campo|
|
226
|
+
find_field_and_do_with_webrat :check, campo
|
227
|
+
end
|
228
|
+
|
229
|
+
Cuando /^(?:que )?desmarco (?:la|el)? ?(.+)$/i do |campo|
|
230
|
+
find_field_and_do_with_webrat :uncheck, campo
|
231
|
+
end
|
232
|
+
|
233
|
+
Cuando /^(?:que )?adjunto el fichero ['"](.*)["'] (?:a|en) (.*)$/ do |ruta, campo|
|
234
|
+
find_field_and_do_with_webrat :attach_file, campo,
|
235
|
+
{:path => ruta, :content_type => ruta.to_content_type}
|
236
|
+
end
|
237
|
+
|
238
|
+
Cuando /^(?:que )?selecciono ["']([^"']+?)["'](?: en (?:el listado de )?(.+))?$/i do |valor, campo|
|
239
|
+
begin
|
240
|
+
if campo
|
241
|
+
select valor, :from => campo.to_unquoted.to_translated # Vía label
|
242
|
+
else
|
243
|
+
select valor
|
244
|
+
end
|
245
|
+
rescue Webrat::NotFoundError
|
246
|
+
select(valor, :from => campo_to_field(campo)) # Sin label
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
Cuando /^(?:que )?selecciono ['"]?(\d\d?) de (\w+) de (\d{4}), (\d\d?:\d\d)["']? como fecha y hora(?: (?:de )?['"]?(.+?)["']?)?$/ do |dia, mes, anio, hora, etiqueta|
|
251
|
+
# Cuando selecciono "25 de diciembre de 2008, 10:00" como fecha y hora
|
252
|
+
# Cuando selecciono 23 de noviembre de 2004, 11:20 como fecha y hora "Preferida"
|
253
|
+
# Cuando selecciono 23 de noviembre de 2004, 11:20 como fecha y hora de "Publicación"
|
254
|
+
time = Time.parse("#{mes.to_month} #{dia}, #{anio} #{hora}")
|
255
|
+
options = etiqueta ? { :from => etiqueta } : {}
|
256
|
+
select_datetime(time, options)
|
257
|
+
end
|
258
|
+
|
259
|
+
Cuando /^(?:que )?selecciono ['"]?(.*)["']? como (?:la )?hora(?: (?:(?:del?|para) (?:la |el )?)?['"]?(.+?)["']?)?$/ do |hora, etiqueta|
|
260
|
+
options = etiqueta ? { :from => etiqueta } : {}
|
261
|
+
select_time(hora, options)
|
262
|
+
end
|
263
|
+
|
264
|
+
Cuando /^(?:que )?selecciono ['"]?(\d\d?) de (\w+) de (\d{4})["']? como (?:la )?fecha(?: (?:(?:del?|para) (?:la |el )?)?['"]?(.+?)["']?)?$/ do |dia, mes, anio, etiqueta|
|
265
|
+
time = Time.parse("#{mes.to_month} #{dia}, #{anio} 12:00")
|
266
|
+
options = etiqueta ? { :from => etiqueta } : {}
|
267
|
+
select_date(time, options)
|
268
|
+
end
|
269
|
+
|
270
|
+
Cuando /^borro (?:el|la|el\/la) (.+) en (?:la )?(\w+|\d+)(?:ª|º)? posición$/ do |modelo, posicion|
|
271
|
+
pile_up modelo.to_unquoted.to_model.new
|
272
|
+
do_visit last_mentioned_url
|
273
|
+
within("table > tr:nth-child(#{posicion.to_number+1})") do
|
274
|
+
click_link "Borrar"
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
#############################################################################
|
279
|
+
veo_o_no = '(?:no )?(?:veo|debo ver|deber[ií]a ver)'
|
280
|
+
|
281
|
+
Entonces /^(#{veo_o_no}) el texto (.+)?$/i do |should, text|
|
282
|
+
eval('response.body.send(shouldify(should))') =~ /#{Regexp.escape(text.to_unquoted.to_translated)}/m
|
283
|
+
end
|
284
|
+
|
285
|
+
leo_o_no = '(?:no )?(?:leo|debo leer|deber[íi]a leer)'
|
286
|
+
Entonces /^(#{leo_o_no}) el texto (.+)?$/i do |should, text|
|
287
|
+
begin
|
288
|
+
HTML::FullSanitizer.new.sanitize(response.body).send(shouldify(should)) =~ /#{Regexp.escape(text.to_unquoted.to_translated)}/m
|
289
|
+
rescue Spec::Expectations::ExpectationNotMetError
|
290
|
+
webrat.save_and_open_page
|
291
|
+
raise
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
295
|
+
Entonces /^(#{veo_o_no}) los siguientes textos:$/i do |should, texts|
|
296
|
+
texts.raw.each do |row|
|
297
|
+
Entonces "#{should} el texto #{row[0]}"
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
301
|
+
Entonces /^(#{leo_o_no}) los siguientes textos:$/i do |should, texts|
|
302
|
+
texts.raw.each do |row|
|
303
|
+
Entonces "#{should} el texto #{row[0]}"
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
Entonces /^(#{veo_o_no}) (?:en )?(?:el selector|la etiqueta|el tag) (["'].+?['"]|[^ ]+)(?:(?: con)? el (?:valor|texto) )?["']?([^"']+)?["']?$/ do |should, tag, value |
|
308
|
+
lambda {
|
309
|
+
if value
|
310
|
+
response.should have_tag(tag.to_unquoted, /.*#{value.to_translated}.*/i)
|
311
|
+
else
|
312
|
+
response.should have_tag(tag.to_unquoted)
|
313
|
+
end
|
314
|
+
}.send(not_shouldify(should), raise_error)
|
315
|
+
end
|
316
|
+
|
317
|
+
Entonces /^(#{veo_o_no}) (?:las|los) siguientes (?:etiquetas|selectores):$/i do |should, texts|
|
318
|
+
check_contents, from_index = texts.raw[0].size == 2 ? [true, 1] : [false, 0]
|
319
|
+
texts.raw[from_index..-1].each do |row|
|
320
|
+
if check_contents
|
321
|
+
Entonces "#{should} el selector \"#{row[0]}\" con el valor \"#{row[1]}\""
|
322
|
+
else
|
323
|
+
Entonces "#{should} el selector \"#{row[0]}\""
|
324
|
+
end
|
325
|
+
end
|
326
|
+
end
|
327
|
+
|
328
|
+
|
329
|
+
|
330
|
+
Entonces /^(#{veo_o_no}) un enlace (?:a|para) (.+)?$/i do |should, pagina|
|
331
|
+
lambda {
|
332
|
+
href = relative_page(pagina) || pagina.to_unquoted.to_url
|
333
|
+
response.should have_tag('a[href=?]', href)
|
334
|
+
}.send(not_shouldify(should), raise_error)
|
335
|
+
end
|
336
|
+
|
337
|
+
|
338
|
+
Entonces /^(#{veo_o_no}) marcad[ao] (?:la casilla|el checkbox)? ?(.+)$/ do |should, campo|
|
339
|
+
field_labeled(campo.to_unquoted).send shouldify(should), be_checked
|
340
|
+
end
|
341
|
+
|
342
|
+
Entonces /^(#{veo_o_no}) (?:una|la) tabla (?:(["'].+?['"]|[^ ]+) )?con (?:el|los) (?:siguientes? )?(?:valore?s?|contenidos?):$/ do |should, table_id, valores|
|
343
|
+
table_id = "##{table_id.to_unquoted}" if table_id
|
344
|
+
shouldified = shouldify(should)
|
345
|
+
response.send shouldified, have_selector("table#{table_id}")
|
346
|
+
|
347
|
+
if have_selector("table#{table_id} tbody").matches?(response)
|
348
|
+
start_row = 1
|
349
|
+
tbody = "tbody"
|
350
|
+
else
|
351
|
+
start_row = 2
|
352
|
+
tbody = ""
|
353
|
+
end
|
354
|
+
|
355
|
+
valores.raw[1..-1].each_with_index do |row, i|
|
356
|
+
row.each_with_index do |cell, j|
|
357
|
+
response.send shouldified,
|
358
|
+
have_selector("table#{table_id} #{tbody} tr:nth-child(#{i+start_row})>td:nth-child(#{j+1})") { |td|
|
359
|
+
td.inner_text.should =~ /#{cell == '.*' ? cell : Regexp.escape((cell||"").to_translated)}/
|
360
|
+
}
|
361
|
+
end
|
362
|
+
end
|
363
|
+
end
|
364
|
+
|
365
|
+
Entonces /^(#{veo_o_no}) un formulario con (?:el|los) (?:siguientes? )?(?:campos?|elementos?):$/ do |should, elementos|
|
366
|
+
shouldified = shouldify(should)
|
367
|
+
response.send(shouldified, have_tag('form')) do
|
368
|
+
elementos.raw[1..-1].each do |row|
|
369
|
+
label, type = row[0].to_translated, row[1]
|
370
|
+
case type
|
371
|
+
when "submit":
|
372
|
+
with_tag "input[type='submit'][value='#{label}']"
|
373
|
+
when "radio":
|
374
|
+
with_tag('div') do
|
375
|
+
with_tag "label", label
|
376
|
+
with_tag "input[type='radio']"
|
377
|
+
end
|
378
|
+
when "select", "textarea":
|
379
|
+
field_labeled(label).element.name.should == type
|
380
|
+
else
|
381
|
+
field_labeled(label).element.attributes['type'].to_s.should == type
|
382
|
+
end
|
383
|
+
end
|
384
|
+
end
|
385
|
+
end
|
386
|
+
|
387
|
+
#BBDD
|
388
|
+
en_bbdd_tenemos = '(?:en (?:la )?(?:bb?dd?|base de datos) tenemos|tenemos en (?:la )?(?:bb?dd?|base de datos))'
|
389
|
+
tiene_en_bbdd = '(?:tiene en (?:la )?bbdd|en (?:la )?bbdd tiene|tiene en (?:la )?base de datos|en (?:la )?base de datos tiene)'
|
390
|
+
Entonces /^#{en_bbdd_tenemos} (un|una|dos|tres|cuatro|cinco|\d+) ([^ ]+)(?: (?:llamad[oa]s? )?['"](.+)["'])?$/ do |numero, modelo, nombre|
|
391
|
+
model = modelo.to_unquoted.to_model
|
392
|
+
conditions = if nombre
|
393
|
+
{:conditions => [ "#{field_for(model, 'nombre')}=?", nombre ]}
|
394
|
+
else
|
395
|
+
{}
|
396
|
+
end
|
397
|
+
resources = model.find(:all, conditions)
|
398
|
+
resources.size.should == numero.to_number
|
399
|
+
if resources.size > 0
|
400
|
+
pile_up (resources.size == 1 ? resources.first : resources)
|
401
|
+
end
|
402
|
+
end
|
403
|
+
|
404
|
+
Entonces /^(?:el|la) (.+) "(.+)" #{tiene_en_bbdd} como (.+) "(.+)"(?: \w+)?$/ do |modelo, nombre, campo, valor|
|
405
|
+
add_resource_from_database(modelo, nombre)
|
406
|
+
last_mentioned_should_have_value(campo, valor.to_real_value)
|
407
|
+
end
|
408
|
+
|
409
|
+
Entonces /^#{tiene_en_bbdd} como (.+) "(.+)"(?: \w+)?$/ do |campo, valor|
|
410
|
+
last_mentioned_should_have_value(campo, valor.to_real_value)
|
411
|
+
end
|
412
|
+
|
413
|
+
Entonces /^(?:el|la) (.+) "(.+)" #{tiene_en_bbdd} una? (.+) "(.+)"$/ do |padre, nombre_del_padre, hijo, nombre_del_hijo|
|
414
|
+
add_resource_from_database(padre, nombre_del_padre)
|
415
|
+
last_mentioned_should_have_child(hijo, nombre_del_hijo)
|
416
|
+
end
|
417
|
+
|
418
|
+
Entonces /^#{tiene_en_bbdd} una? (.+) "(.+)"$/ do |hijo, nombre_del_hijo|
|
419
|
+
last_mentioned_should_have_child(hijo, nombre_del_hijo)
|
420
|
+
end
|