factory_boy 1.0.5 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +68 -31
- data/lib/blank_slate.rb +3 -0
- data/lib/plant.rb +37 -46
- data/lib/query.rb +44 -0
- data/lib/reflection.rb +40 -0
- data/lib/selector.rb +181 -0
- data/lib/setup.rb +13 -22
- data/lib/stubber.rb +164 -21
- data/test/Rakefile.rb +11 -0
- data/test/app/models/address.rb +9 -0
- data/test/app/models/customer.rb +3 -0
- data/test/app/models/profile.rb +2 -0
- data/test/app/models/user.rb +7 -0
- data/test/databases.rake.rb +513 -0
- data/test/db/migrate/20101230223546_create_users.rb.rb +14 -0
- data/test/db/migrate/20101230223547_create_profiles.rb +15 -0
- data/test/db/migrate/20101230223548_create_customers.rb +11 -0
- data/test/db/migrate/20101230223549_create_addresses.rb +13 -0
- data/test/db/schema.rb +41 -0
- data/test/help_test.rb +15 -5
- data/test/plants.rb +5 -5
- data/test/test_basic_queries.rb +36 -0
- data/test/test_plant_definition.rb +129 -0
- data/test/test_plants_ids.rb +16 -0
- data/test/test_queries_on_has_many_association.rb +51 -0
- data/test/test_queries_on_has_one_association.rb +45 -0
- data/test/test_queries_on_model_attributes.rb +59 -0
- data/test/test_queries_with_like.rb +22 -0
- data/test/test_queries_with_limit.rb +28 -0
- data/test/test_queries_with_named_scope.rb +18 -0
- data/test/test_queries_with_order.rb +17 -0
- data/test/test_queries_with_ranges.rb +21 -0
- data/test/test_selector_condition.rb +26 -0
- data/test/test_stubbing.rb +43 -0
- metadata +60 -22
- data/test/models/adress.rb +0 -12
- data/test/models/customer.rb +0 -7
- data/test/models/profile.rb +0 -8
- data/test/models/user.rb +0 -8
- data/test/plant_tests.rb +0 -115
- data/test/test_plant.rb +0 -7
- data/test/test_plant_with_active_support.rb +0 -8
@@ -0,0 +1,15 @@
|
|
1
|
+
class CreateProfiles < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :profiles do |t|
|
4
|
+
t.references :user
|
5
|
+
t.string :password
|
6
|
+
t.boolean :checked
|
7
|
+
t.decimal :height
|
8
|
+
t.float :salary
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.down
|
13
|
+
drop_table :profiles
|
14
|
+
end
|
15
|
+
end
|
data/test/db/schema.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
# This file is auto-generated from the current state of the database. Instead
|
2
|
+
# of editing this file, please use the migrations feature of Active Record to
|
3
|
+
# incrementally modify your database, and then regenerate this schema definition.
|
4
|
+
#
|
5
|
+
# Note that this schema.rb definition is the authoritative source for your
|
6
|
+
# database schema. If you need to create the application database on another
|
7
|
+
# system, you should be using db:schema:load, not running all the migrations
|
8
|
+
# from scratch. The latter is a flawed and unsustainable approach (the more migrations
|
9
|
+
# you'll amass, the slower it'll run and the greater likelihood for issues).
|
10
|
+
#
|
11
|
+
# It's strongly recommended to check this file into your version control system.
|
12
|
+
|
13
|
+
ActiveRecord::Schema.define(:version => 20101230223549) do
|
14
|
+
|
15
|
+
create_table "addresses", :force => true do |t|
|
16
|
+
t.integer "user_id"
|
17
|
+
t.string "street"
|
18
|
+
t.integer "number"
|
19
|
+
end
|
20
|
+
|
21
|
+
create_table "customers", :force => true do |t|
|
22
|
+
t.string "name"
|
23
|
+
end
|
24
|
+
|
25
|
+
create_table "profiles", :force => true do |t|
|
26
|
+
t.integer "user_id"
|
27
|
+
t.string "password"
|
28
|
+
t.boolean "checked"
|
29
|
+
t.decimal "height"
|
30
|
+
t.float "salary"
|
31
|
+
end
|
32
|
+
|
33
|
+
create_table "users", :force => true do |t|
|
34
|
+
t.string "name"
|
35
|
+
t.integer "age"
|
36
|
+
t.boolean "male"
|
37
|
+
t.datetime "created_at"
|
38
|
+
t.datetime "updated_at"
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
data/test/help_test.rb
CHANGED
@@ -2,9 +2,19 @@ Object.const_set("RAILS_ROOT", File.join(File.dirname(__FILE__), '../') )
|
|
2
2
|
|
3
3
|
require 'rubygems'
|
4
4
|
require 'test/unit'
|
5
|
-
|
6
|
-
require '
|
7
|
-
require 'models/profile'
|
8
|
-
require 'models/customer'
|
5
|
+
gem 'activerecord', version='3.0.1'
|
6
|
+
require 'active_record'
|
9
7
|
|
10
|
-
require '
|
8
|
+
require 'app/models/address'
|
9
|
+
require 'app/models/user'
|
10
|
+
require 'app/models/profile'
|
11
|
+
require 'app/models/customer'
|
12
|
+
|
13
|
+
require 'plant'
|
14
|
+
|
15
|
+
require 'mocha'
|
16
|
+
|
17
|
+
ActiveRecord::Base.establish_connection(
|
18
|
+
:adapter => "sqlite3",
|
19
|
+
:database => File.join(File.dirname(__FILE__), "db/test.sqlite3")
|
20
|
+
)
|
data/test/plants.rb
CHANGED
@@ -6,16 +6,16 @@ Plant.define :profile do |profile|
|
|
6
6
|
profile.password = "BREIZH!"
|
7
7
|
end
|
8
8
|
|
9
|
-
Plant.define :
|
10
|
-
|
11
|
-
|
9
|
+
Plant.define :address do |address|
|
10
|
+
address.number = 17
|
11
|
+
address.street = "rue royale"
|
12
12
|
end
|
13
13
|
|
14
14
|
Plant.define :user do |user|
|
15
15
|
user.name = "Zorro"
|
16
16
|
user.age = 800
|
17
|
-
user.profile = Plant
|
18
|
-
user.
|
17
|
+
user.profile = Plant(:profile)
|
18
|
+
user.addresses = [Plant(:address)]
|
19
19
|
end
|
20
20
|
|
21
21
|
Plant.define :customer do |customer|
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'help_test'
|
2
|
+
|
3
|
+
class TestBasicQueries < ActiveSupport::TestCase
|
4
|
+
|
5
|
+
|
6
|
+
def test_should_stubs_find_whith_option_first_and_with_class_method_first
|
7
|
+
user = Plant(:user)
|
8
|
+
assert_equal user, User.find(:first)
|
9
|
+
assert_equal user, User.first
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_should_stubs_find_whith_option_all_and_with_class_method_last
|
13
|
+
user_1, user_2 = [Plant(:user), Plant(:user)]
|
14
|
+
assert_equal user_2, User.find(:last)
|
15
|
+
assert_equal user_2, User.last
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_should_stubs_find_whith_option_last_and_with_class_method_all
|
19
|
+
users = [Plant(:user), Plant(:user)]
|
20
|
+
assert_equal users, User.find(:all)
|
21
|
+
assert_equal users, User.all
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_should_find_by_id
|
25
|
+
user = Plant(:user)
|
26
|
+
|
27
|
+
assert_equal user, User.find(user.id)
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_should_find_by_ids
|
31
|
+
user_1, user_2 = [Plant(:user), Plant(:user)]
|
32
|
+
|
33
|
+
assert_equal [user_1, user_2], User.find(user_1.id, user_2.id)
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
@@ -0,0 +1,129 @@
|
|
1
|
+
require 'help_test'
|
2
|
+
|
3
|
+
class TestPlantDefinition < ActiveSupport::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
assert_plants_are_destroyed_before_each_test
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_simple_definition_of_plant
|
10
|
+
assert customer = Plant(:customer)
|
11
|
+
assert_nil customer.name
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_definition_should_assign_attributes_and_values
|
15
|
+
user = Plant(:user)
|
16
|
+
|
17
|
+
assert_equal "Zorro", user.name
|
18
|
+
assert_equal 800, user.age
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_mocha_is_not_overidden_with_plant_setup
|
22
|
+
Plant(:customer)
|
23
|
+
Plant.expects(:pool).once
|
24
|
+
Plant(:user)
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_instanciation_of_a_plant_with_hash_for_assigning_attributes_values
|
28
|
+
address = Plant(:address)
|
29
|
+
user = Plant(:user, :name => "Marie", :addresses => [address])
|
30
|
+
|
31
|
+
assert_equal "Marie", user.name
|
32
|
+
assert_equal address, user.addresses.first
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_definition_with_class_option
|
36
|
+
Plant.define :marie, :class => User do |marie|
|
37
|
+
marie.name = "Marie"
|
38
|
+
marie.addresses = [Plant(:address, :street => "Rue de Brest")]
|
39
|
+
end
|
40
|
+
|
41
|
+
marie = Plant(:marie)
|
42
|
+
assert_equal "Marie", marie.name
|
43
|
+
assert_equal "Rue de Brest", marie.addresses.first.street
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_plants_are_reloaded_only_when_a_plant_is_instanciated
|
47
|
+
assert_equal 0, Plant.plants.size
|
48
|
+
Plant(:user)
|
49
|
+
assert_equal 4, Plant.plants.size
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_definition_of_a_plant_with_dependent_attribute
|
53
|
+
Plant.define :user do |user|
|
54
|
+
user.name = "Marie"
|
55
|
+
user.addresses = [Plant(:address, :street => "Rue de #{user.name}")]
|
56
|
+
end
|
57
|
+
|
58
|
+
assert_equal "Rue de Marie", Plant(:user).addresses.first.street
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_plant_sequences
|
62
|
+
Plant.reload
|
63
|
+
assert_equal "incognito1@kantena.com", Plant.next(:email)
|
64
|
+
assert_equal "incognito2@kantena.com", Plant.next(:email)
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_should_set_foreign_key_values_for_has_many_associations
|
68
|
+
joe, bob = joe_and_bob[:users]
|
69
|
+
|
70
|
+
assert_equal joe.id, joe.addresses.first.user_id
|
71
|
+
assert_equal bob.id, bob.addresses.first.user_id
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_should_set_foreign_key_values_for_has_one_associations
|
75
|
+
joe, bob = joe_and_bob[:users]
|
76
|
+
|
77
|
+
assert_equal joe.id, joe.profile.user_id
|
78
|
+
assert_equal bob.id, bob.profile.user_id
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_creation_of_two_plants_of_same_class_should_keep_each_object_safe
|
82
|
+
joe, bob = joe_and_bob[:users]
|
83
|
+
|
84
|
+
assert_equal "Joe", joe.name
|
85
|
+
assert_equal "Bob", bob.name
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_creation_of_two_plants_of_same_class_should_keep_has_one_associations_safe
|
89
|
+
users = joe_and_bob
|
90
|
+
joe, bob, profile_1, profile_2 = users[:users], users[:profiles]
|
91
|
+
|
92
|
+
assert_equal profile_1, joe.profile
|
93
|
+
assert_equal profile_2, bob.profile
|
94
|
+
end
|
95
|
+
|
96
|
+
def test_creation_of_two_plants_of_same_class_should_keep_has_many_associations_safe
|
97
|
+
users = joe_and_bob
|
98
|
+
joe, bob = users[:users]
|
99
|
+
address_1, address_2 = users[:addresses]
|
100
|
+
|
101
|
+
assert_equal [address_1], joe.addresses
|
102
|
+
assert_equal [address_2], bob.addresses
|
103
|
+
end
|
104
|
+
|
105
|
+
|
106
|
+
private
|
107
|
+
|
108
|
+
def assert_plants_are_destroyed_before_each_test
|
109
|
+
assert_equal({}, Plant.plants)
|
110
|
+
assert_equal({}, Plant.all)
|
111
|
+
assert_equal({}, Plant.send(:class_variable_get, :@@sequences))
|
112
|
+
assert_equal 0, Plant.send(:class_variable_get, :@@id)
|
113
|
+
end
|
114
|
+
|
115
|
+
def joe_and_bob
|
116
|
+
address_1 = Plant(:address, :street => '40 rue de PenMarch')
|
117
|
+
address_2 = Plant(:address, :street => '25 Bd du Guilvinec')
|
118
|
+
|
119
|
+
profile_1 = Plant(:profile, :password => 'azerty')
|
120
|
+
profile_2 = Plant(:profile, :password => 'qwerty')
|
121
|
+
|
122
|
+
joe = Plant(:user, :name => 'Joe', :addresses => [address_1], :profile => profile_1)
|
123
|
+
bob = Plant(:user, :name => 'Bob', :addresses => [address_2], :profile => profile_2)
|
124
|
+
|
125
|
+
|
126
|
+
{:users => [joe, bob], :addresses => [address_1, address_2], :profiles => [profile_1, profile_2]}
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'help_test'
|
2
|
+
|
3
|
+
class TestPlantsIds < ActiveSupport::TestCase
|
4
|
+
|
5
|
+
def test_each_plant_should_have_unique_id
|
6
|
+
ids = []
|
7
|
+
1.upto(10) do |n|
|
8
|
+
user = Plant(:user)
|
9
|
+
profile = Plant(:profile)
|
10
|
+
address = Plant(:address)
|
11
|
+
ids += [user.id, profile.id, address.id]
|
12
|
+
end
|
13
|
+
assert_equal ids, ids.uniq
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'help_test'
|
2
|
+
|
3
|
+
class TestQueriesOnHasManyAssociation < ActiveSupport::TestCase
|
4
|
+
|
5
|
+
def test_queries_with_conditions_on_has_many_association_with_equality_operator
|
6
|
+
addresses = [Plant(:address, :street => '21 Jump Street'), Plant(:address, :street => 'Rue des Lilas')]
|
7
|
+
joe = Plant(:user, :name => 'Joe', :age => 30, :addresses => addresses)
|
8
|
+
|
9
|
+
assert_equal([joe], User.where(:name => 'Joe').where("addresses.street = '21 Jump Street'").joins(:addresses))
|
10
|
+
assert_equal([], User.where(:name => 'Joe').where("addresses.street = '20 Jump Street'").joins(:addresses))
|
11
|
+
assert_equal([joe], User.where("addresses.street = '21 Jump Street'").joins(:addresses))
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_queries_with_conditions_on_has_many_association_with_non_equality_operator
|
15
|
+
addresses = [Plant(:address, :street => '21 Jump Street'), Plant(:address, :street => 'Rue des Lilas')]
|
16
|
+
joe = Plant(:user, :name => 'Joe', :age => 30, :addresses => addresses)
|
17
|
+
|
18
|
+
assert_equal([], User.where("addresses.street != '21 Jump Street'").joins(:addresses))
|
19
|
+
assert_equal([joe], User.where("addresses.street <> '20 Jump Street'").joins(:addresses))
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_queries_with_conditions_on_has_many_association_with_inequality_operators
|
23
|
+
addresses = [Plant(:address, :street => 'a'), Plant(:address, :street => 'b')]
|
24
|
+
joe = Plant(:user, :name => 'Joe', :age => 30, :addresses => addresses)
|
25
|
+
|
26
|
+
assert_equal([], User.where("addresses.street > 'b' ").joins(:addresses))
|
27
|
+
assert_equal([], User.where("addresses.street < 'a' ").joins(:addresses))
|
28
|
+
assert_equal([joe], User.where("addresses.street <= 'b' ").joins(:addresses))
|
29
|
+
assert_equal([joe], User.where("addresses.street >= 'b' ").joins(:addresses))
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_queries_with_conditions_on_has_many_association_with_like_predicate
|
34
|
+
joe = Plant(:user, :name => 'Joe', :addresses => [Plant(:address, :street => 'azb')])
|
35
|
+
bob = Plant(:user, :name => 'Bob', :addresses => [Plant(:address, :street => 'azc')])
|
36
|
+
|
37
|
+
assert_equal([joe, bob], User.where("addresses.street like ?", 'az%').joins(:addresses))
|
38
|
+
assert_equal([joe], User.where("addresses.street like ?", 'azb').joins(:addresses))
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_queries_on_association_proxy
|
43
|
+
address_1, address_2 = [Plant(:address, :street => '21 Jump Street'), Plant(:address, :street => 'Rue des Lilas')]
|
44
|
+
joe = Plant(:user, :name => 'Joe', :addresses => [address_1, address_2])
|
45
|
+
|
46
|
+
assert_equal [address_1], joe.addresses.where(:street => '21 Jump Street')
|
47
|
+
assert_equal [], joe.addresses.where(:street => '210 Jump Street')
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'help_test'
|
2
|
+
|
3
|
+
class TestQueriesOnHasOneAssociation < ActiveSupport::TestCase
|
4
|
+
|
5
|
+
def test_should_stubs_find_with_where_conditions_on_has_one_association
|
6
|
+
profile = Plant(:profile, :password => 'azerty')
|
7
|
+
joe = Plant(:user, :name => 'Joe', :age => 30, :profile => profile)
|
8
|
+
|
9
|
+
assert_equal [joe], User.where(:name => 'Joe').where("profiles.password = 'azerty'")
|
10
|
+
assert_equal [joe], User.where(:name => 'Joe').where("profiles.password = 'azerty'").joins(:profile)
|
11
|
+
assert_equal [joe], User.where(:name => 'Joe').where("profiles.password = 'azerty'").includes(:profile)
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_should_handle_nil_has_one_association
|
15
|
+
joe = Plant(:user, :name => 'Joe', :age => 30, :profile => nil)
|
16
|
+
|
17
|
+
assert_equal [], User.where(:name => 'Joe').where("profiles.password = 'azerty'")
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_should_stubs_find_with_where_conditions_on_has_one_association_with_inequality_operators
|
21
|
+
profile = Plant(:profile, :password => 'a')
|
22
|
+
joe = Plant(:user, :name => 'Joe', :profile => profile)
|
23
|
+
|
24
|
+
assert_equal [joe], User.where(:name => 'Joe').where("profiles.password >= 'a'")
|
25
|
+
assert_equal [], User.where(:name => 'Joe').where("profiles.password > 'a'")
|
26
|
+
assert_equal [], User.where(:name => 'Joe').where("profiles.password < 'a'")
|
27
|
+
assert_equal [], User.where(:name => 'Joe').where("profiles.password != 'a'")
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_should_stubs_find_with_where_conditions_on_has_one_association_with_boolean_condition
|
31
|
+
profile = Plant(:profile, :checked => false)
|
32
|
+
joe = Plant(:user, :name => 'Joe', :profile => profile)
|
33
|
+
|
34
|
+
assert_equal [joe], User.where("profiles.checked = '0'")
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_queries_with_float_and_decimal
|
38
|
+
profile = Plant(:profile, :height => 1.75, :salary => 2000.23)
|
39
|
+
joe = Plant(:user, :name => 'Joe', :profile => profile)
|
40
|
+
|
41
|
+
assert_equal [joe], User.where('profiles.height = 1.75')
|
42
|
+
assert_equal [joe], User.where('profiles.salary = 2000.23')
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'help_test'
|
2
|
+
|
3
|
+
class TestQueriesOnModelAttributes < ActiveSupport::TestCase
|
4
|
+
|
5
|
+
attr_accessor :joe, :bob
|
6
|
+
|
7
|
+
def setup
|
8
|
+
@joe = Plant(:user, :name => 'Joe', :age => 30, :male => true)
|
9
|
+
@bob = Plant(:user, :name => 'Bob', :age => 31, :male => true)
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_stubbed_find_should_return_empty_array_if_none_object_matches_conditions
|
13
|
+
Plant.destroy
|
14
|
+
assert_equal [], User.where(:name => 'Joe')
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_queries_with_conditions_on_attributes
|
18
|
+
assert_equal [joe], User.where(:name => 'Joe')
|
19
|
+
assert_equal [joe], User.where("users.name = 'Joe'")
|
20
|
+
assert_equal [joe], User.where("name = 'Joe'")
|
21
|
+
assert_equal [joe], User.where(:name => 'Joe', :age => 30)
|
22
|
+
assert_equal [joe], User.where("users.name = 'Joe' or users.age = 30")
|
23
|
+
assert_equal [bob], User.where("name = 'Bob' and age = 31")
|
24
|
+
assert_equal [joe, bob], User.where("age = 30 or age = 31")
|
25
|
+
assert_equal [joe, bob], User.where("(age = 30 and name = 'Joe') or (age = 31 and name = 'Bob')")
|
26
|
+
assert_equal [joe, bob], User.where("age <= 31")
|
27
|
+
assert_equal [], User.where("age > 31")
|
28
|
+
assert_equal [joe], User.where("name = ?", 'Joe')
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_queries_with_dynamics_finders_methods
|
32
|
+
assert_equal joe, User.find_by_name('Joe')
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_should_handle_chained_where_clauses
|
36
|
+
assert_equal [joe], User.where(:age => 30).where(:name => 'Joe')
|
37
|
+
users = User.where(:age => 30)
|
38
|
+
assert_equal([joe], users.where(:name => 'Joe'))
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_queries_with_boolean_conditions
|
42
|
+
assert_equal [joe, bob], User.where(:male => true)
|
43
|
+
assert_equal [], User.where(:male => false)
|
44
|
+
assert_equal [joe, bob], User.where("users.male = '1'")
|
45
|
+
assert_equal [joe, bob], User.where("male = '1'")
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_queries_with_sql_is_null_and_is_not_null
|
49
|
+
joe.name = nil
|
50
|
+
|
51
|
+
assert_equal [joe], User.where(:name => nil)
|
52
|
+
assert_equal [joe], User.where('name is null')
|
53
|
+
|
54
|
+
assert_equal [bob], User.where('name is not null')
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
|
59
|
+
end
|