formotion 0.0.3 → 0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -1
- data/CHANGELOG.md +10 -0
- data/Gemfile +6 -0
- data/LIST_OF_ROW_TYPES.md +163 -0
- data/NEW_ROW_TYPES.md +73 -0
- data/README.md +11 -14
- data/Rakefile +6 -0
- data/app/app_delegate.rb +22 -0
- data/examples/KitchenSink/Rakefile +1 -1
- data/examples/KitchenSink/app/app_delegate.rb +50 -2
- data/examples/Login/.gitignore +5 -0
- data/examples/Login/Rakefile +9 -0
- data/examples/Login/app/app_delegate.rb +16 -0
- data/examples/Login/app/login_controller.rb +47 -0
- data/examples/Login/app/user_controller.rb +38 -0
- data/examples/Login/spec/main_spec.rb +9 -0
- data/lib/formotion.rb +7 -1
- data/lib/formotion/{form.rb → form/form.rb} +0 -0
- data/lib/formotion/{form_delegate.rb → form/form_delegate.rb} +10 -15
- data/lib/formotion/patch/object.rb +9 -0
- data/lib/formotion/patch/ui_action_sheet.rb +27 -0
- data/lib/formotion/patch/ui_text_view.rb +122 -0
- data/lib/formotion/patch/ui_text_view_placeholder.rb +65 -0
- data/lib/formotion/{row.rb → row/row.rb} +37 -27
- data/lib/formotion/row/row_cell_builder.rb +28 -0
- data/lib/formotion/row_type/base.rb +41 -0
- data/lib/formotion/row_type/check_row.rb +30 -0
- data/lib/formotion/row_type/date_row.rb +61 -0
- data/lib/formotion/row_type/email_row.rb +11 -0
- data/lib/formotion/row_type/image_row.rb +99 -0
- data/lib/formotion/row_type/number_row.rb +11 -0
- data/lib/formotion/row_type/options_row.rb +24 -0
- data/lib/formotion/row_type/phone_row.rb +11 -0
- data/lib/formotion/row_type/row_type.rb +21 -0
- data/lib/formotion/row_type/slider_row.rb +43 -0
- data/lib/formotion/row_type/static_row.rb +6 -0
- data/lib/formotion/row_type/string_row.rb +112 -0
- data/lib/formotion/row_type/submit_row.rb +34 -0
- data/lib/formotion/row_type/switch_row.rb +19 -0
- data/lib/formotion/row_type/text_row.rb +76 -0
- data/lib/formotion/{section.rb → section/section.rb} +3 -0
- data/lib/formotion/version.rb +1 -1
- data/spec/form_spec.rb +5 -4
- data/spec/functional/character_spec.rb +70 -0
- data/spec/functional/check_row_spec.rb +42 -0
- data/spec/functional/date_row_spec.rb +63 -0
- data/spec/functional/image_row_spec.rb +82 -0
- data/spec/functional/options_row_spec.rb +27 -0
- data/spec/functional/slider_row_spec.rb +27 -0
- data/spec/functional/submit_row_spec.rb +30 -0
- data/spec/functional/switch_row_spec.rb +28 -0
- data/spec/functional/text_row_spec.rb +60 -0
- data/spec/row_type/check_spec.rb +27 -0
- data/spec/row_type/date_spec.rb +69 -0
- data/spec/row_type/email_spec.rb +22 -0
- data/spec/row_type/image_spec.rb +43 -0
- data/spec/row_type/number_spec.rb +22 -0
- data/spec/row_type/options_spec.rb +37 -0
- data/spec/row_type/phone_spec.rb +22 -0
- data/spec/row_type/slider_spec.rb +47 -0
- data/spec/row_type/static_spec.rb +15 -0
- data/spec/row_type/string_spec.rb +52 -0
- data/spec/row_type/submit_spec.rb +28 -0
- data/spec/row_type/switch_spec.rb +27 -0
- data/spec/row_type/text_spec.rb +41 -0
- data/spec/support/ui_control_wrap_extension.rb +7 -0
- metadata +88 -9
- data/lib/formotion/row_cell_builder.rb +0 -168
- data/lib/formotion/row_type.rb +0 -33
@@ -0,0 +1,27 @@
|
|
1
|
+
describe "FormController/SliderRow" do
|
2
|
+
tests Formotion::FormController
|
3
|
+
|
4
|
+
# By default, `tests` uses @controller.init
|
5
|
+
# this isn't ideal for our case, so override.
|
6
|
+
def controller
|
7
|
+
row_settings = {
|
8
|
+
title: "Slider",
|
9
|
+
key: :slider,
|
10
|
+
type: :slider,
|
11
|
+
range: (1..100),
|
12
|
+
value: 1
|
13
|
+
}
|
14
|
+
@form ||= Formotion::Form.new(
|
15
|
+
sections: [{
|
16
|
+
rows:[row_settings]
|
17
|
+
}])
|
18
|
+
|
19
|
+
@controller ||= Formotion::FormController.alloc.initWithForm(@form)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should change row value when sliding" do
|
23
|
+
@form.sections[0].rows[0].value.should == 1
|
24
|
+
drag("Slider Slider", :from => :left)
|
25
|
+
@form.sections[0].rows[0].value.should == 100
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
describe "FormController/SubmitRow" do
|
2
|
+
tests Formotion::FormController
|
3
|
+
|
4
|
+
# By default, `tests` uses @controller.init
|
5
|
+
# this isn't ideal for our case, so override.
|
6
|
+
def controller
|
7
|
+
row_settings = {
|
8
|
+
title: "Submit",
|
9
|
+
type: :submit
|
10
|
+
}
|
11
|
+
@form ||= Formotion::Form.new(
|
12
|
+
sections: [{
|
13
|
+
rows:[row_settings]
|
14
|
+
}])
|
15
|
+
|
16
|
+
@controller ||= Formotion::FormController.alloc.initWithForm(@form)
|
17
|
+
end
|
18
|
+
|
19
|
+
def submit_row
|
20
|
+
@form.sections.first.rows.first
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should call .submit when tapped" do
|
24
|
+
@form.on_submit do
|
25
|
+
@submitted = true
|
26
|
+
end
|
27
|
+
tap("Submit")
|
28
|
+
@submitted.should == true
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
describe "FormController/SwitchRow" do
|
2
|
+
tests Formotion::FormController
|
3
|
+
|
4
|
+
# By default, `tests` uses @controller.init
|
5
|
+
# this isn't ideal for our case, so override.
|
6
|
+
def controller
|
7
|
+
row_settings = {
|
8
|
+
title: "Switch",
|
9
|
+
key: :switch,
|
10
|
+
type: :switch,
|
11
|
+
value: false
|
12
|
+
}
|
13
|
+
@form ||= Formotion::Form.new(
|
14
|
+
sections: [{
|
15
|
+
rows:[row_settings]
|
16
|
+
}])
|
17
|
+
|
18
|
+
@controller ||= Formotion::FormController.alloc.initWithForm(@form)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should change row value when tapped" do
|
22
|
+
tap("Switch Switch")
|
23
|
+
@form.sections[0].rows[0].value.should == true
|
24
|
+
|
25
|
+
tap("Switch Switch")
|
26
|
+
@form.sections[0].rows[0].value.should == false
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
describe "FormController/TextRow" do
|
2
|
+
tests Formotion::FormController
|
3
|
+
|
4
|
+
# By default, `tests` uses @controller.init
|
5
|
+
# this isn't ideal for our case, so override.
|
6
|
+
def controller
|
7
|
+
row_settings = {
|
8
|
+
title: "Text",
|
9
|
+
key: :text,
|
10
|
+
type: :text
|
11
|
+
}
|
12
|
+
@form ||= Formotion::Form.new(
|
13
|
+
sections: [{
|
14
|
+
rows:[row_settings]
|
15
|
+
}])
|
16
|
+
|
17
|
+
@controller ||= Formotion::FormController.alloc.initWithForm(@form)
|
18
|
+
end
|
19
|
+
|
20
|
+
def text_row
|
21
|
+
@form.sections.first.rows.first
|
22
|
+
end
|
23
|
+
|
24
|
+
after do
|
25
|
+
text_row.object.dismissKeyboard
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should pop open the keyboard when tapped" do
|
29
|
+
@notif = App.notification_center.observe UIKeyboardDidShowNotification do |notification|
|
30
|
+
@did_show = true
|
31
|
+
end
|
32
|
+
tap("Text")
|
33
|
+
wait 1 do
|
34
|
+
@did_show.should == true
|
35
|
+
App.notification_center.unobserve @notif
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should close the keyboard when tapped again" do
|
40
|
+
@notif = App.notification_center.observe UIKeyboardDidHideNotification do |notification|
|
41
|
+
@did_hide = true
|
42
|
+
end
|
43
|
+
|
44
|
+
tap("Text")
|
45
|
+
wait 1 do
|
46
|
+
tap("Text")
|
47
|
+
wait 1 do
|
48
|
+
@did_hide.should == true
|
49
|
+
App.notification_center.unobserve @notif
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should change value of row when typing" do
|
55
|
+
tap("Text")
|
56
|
+
text_row.object.field.text = "Hello"
|
57
|
+
text_row.object.field.delegate.textViewDidChange(text_row.object.field)
|
58
|
+
text_row.value.should == "Hello"
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
describe "Check Row" do
|
2
|
+
before do
|
3
|
+
row_settings = {
|
4
|
+
title: "Check",
|
5
|
+
key: :check,
|
6
|
+
type: :check,
|
7
|
+
}
|
8
|
+
@row = Formotion::Row.new(row_settings)
|
9
|
+
@row.reuse_identifier = 'test'
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should initialize with correct settings" do
|
13
|
+
@row.object.class.should == Formotion::RowType::CheckRow
|
14
|
+
end
|
15
|
+
|
16
|
+
# Value
|
17
|
+
it "should be unchecked by default" do
|
18
|
+
cell = @row.make_cell
|
19
|
+
cell.accessoryType.should == UITableViewCellAccessoryNone
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should be checked when true" do
|
23
|
+
@row.value = true
|
24
|
+
cell = @row.make_cell
|
25
|
+
cell.accessoryType.should == UITableViewCellAccessoryCheckmark
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
MILLENIUM = 946684672
|
2
|
+
TIME_ZONE = NSTimeZone.timeZoneWithName "Europe/Paris"
|
3
|
+
|
4
|
+
describe "Date Row" do
|
5
|
+
before do
|
6
|
+
row_settings = {
|
7
|
+
title: "Date",
|
8
|
+
key: :date,
|
9
|
+
type: :date,
|
10
|
+
}
|
11
|
+
@row = Formotion::Row.new(row_settings)
|
12
|
+
@row.reuse_identifier = 'test'
|
13
|
+
@row.object.formatter.timeZone = TIME_ZONE
|
14
|
+
@row.object.picker.timeZone = TIME_ZONE
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should initialize with correct settings" do
|
18
|
+
@row.object.class.should == Formotion::RowType::DateRow
|
19
|
+
end
|
20
|
+
|
21
|
+
# Value
|
22
|
+
it "should have no value by default" do
|
23
|
+
cell = @row.make_cell
|
24
|
+
|
25
|
+
@row.text_field.text.should == nil
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should use custom value" do
|
29
|
+
@row.value = MILLENIUM
|
30
|
+
cell = @row.make_cell
|
31
|
+
|
32
|
+
|
33
|
+
@row.text_field.text.should == '1/1/00'
|
34
|
+
end
|
35
|
+
|
36
|
+
# Picker
|
37
|
+
it "should build date picker" do
|
38
|
+
@row.object.picker.class.should == UIDatePicker
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should update value when date is picked" do
|
42
|
+
cell = @row.make_cell
|
43
|
+
|
44
|
+
@row.object.picker.date = NSDate.dateWithTimeIntervalSince1970(MILLENIUM)
|
45
|
+
@row.object.picker.trigger UIControlEventValueChanged
|
46
|
+
|
47
|
+
@row.value.should == MILLENIUM
|
48
|
+
@row.text_field.text.should == '1/1/00'
|
49
|
+
end
|
50
|
+
|
51
|
+
# Formats
|
52
|
+
{
|
53
|
+
:short => '1/1/00',
|
54
|
+
:medium => 'Jan 1, 2000',
|
55
|
+
:long => 'January 1, 2000',
|
56
|
+
:full => 'Saturday, January 1, 2000'
|
57
|
+
}.each do |format, expected_output|
|
58
|
+
|
59
|
+
it "should display date in full format" do
|
60
|
+
@row.value = MILLENIUM
|
61
|
+
@row.format = format
|
62
|
+
@row.object.instance_variable_set("@formatter", nil)
|
63
|
+
@row.object.formatter.timeZone = TIME_ZONE
|
64
|
+
cell = @row.make_cell
|
65
|
+
|
66
|
+
@row.text_field.text.should == expected_output
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
describe "Email Row" do
|
2
|
+
before do
|
3
|
+
row_settings = {
|
4
|
+
title: "Email",
|
5
|
+
key: :email,
|
6
|
+
type: :email,
|
7
|
+
}
|
8
|
+
@row = Formotion::Row.new(row_settings)
|
9
|
+
@row.reuse_identifier = 'test'
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should initialize with correct settings" do
|
13
|
+
@row.object.class.should == Formotion::RowType::EmailRow
|
14
|
+
end
|
15
|
+
|
16
|
+
# Keyboard
|
17
|
+
it "should use email keyboard" do
|
18
|
+
cell = @row.make_cell
|
19
|
+
@row.text_field.keyboardType.should == UIKeyboardTypeEmailAddress
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
describe "Image Row" do
|
2
|
+
before do
|
3
|
+
row_settings = {
|
4
|
+
title: "Photo",
|
5
|
+
key: :photo,
|
6
|
+
type: :image
|
7
|
+
}
|
8
|
+
@row = Formotion::Row.new(row_settings)
|
9
|
+
@row.reuse_identifier = 'test'
|
10
|
+
|
11
|
+
|
12
|
+
@row.instance_eval do
|
13
|
+
def form
|
14
|
+
@form ||= Object.new.tap do |o|
|
15
|
+
def o.reload_data
|
16
|
+
# do nothing for tests
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should build cell with an image view" do
|
24
|
+
cell = @row.make_cell
|
25
|
+
image_view = cell.viewWithTag(Formotion::RowType::ImageRow::IMAGE_VIEW_TAG)
|
26
|
+
image_view.nil?.should == false
|
27
|
+
image_view.class.should == UIImageView
|
28
|
+
image_view.image.nil?.should == true
|
29
|
+
cell.accessoryView.class.should == UIButton
|
30
|
+
end
|
31
|
+
|
32
|
+
# Value
|
33
|
+
it "should change row properties when row gets a value" do
|
34
|
+
cell = @row.make_cell
|
35
|
+
|
36
|
+
@row.value = UIImage.alloc.init
|
37
|
+
|
38
|
+
@row.rowHeight.should > 44
|
39
|
+
image_view = cell.viewWithTag(Formotion::RowType::ImageRow::IMAGE_VIEW_TAG)
|
40
|
+
image_view.image.nil?.should == false
|
41
|
+
cell.accessoryView.nil?.should == true
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
describe "Number Row" do
|
2
|
+
before do
|
3
|
+
row_settings = {
|
4
|
+
title: "Number",
|
5
|
+
key: :number,
|
6
|
+
type: :number,
|
7
|
+
}
|
8
|
+
@row = Formotion::Row.new(row_settings)
|
9
|
+
@row.reuse_identifier = 'test'
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should initialize with correct settings" do
|
13
|
+
@row.object.class.should == Formotion::RowType::NumberRow
|
14
|
+
end
|
15
|
+
|
16
|
+
# Keyboard
|
17
|
+
it "should use decimal keyboard" do
|
18
|
+
cell = @row.make_cell
|
19
|
+
@row.text_field.keyboardType.should == UIKeyboardTypeDecimalPad
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
describe "Options Row" do
|
2
|
+
before do
|
3
|
+
row_settings = {
|
4
|
+
title: "Options",
|
5
|
+
key: :options,
|
6
|
+
type: :options,
|
7
|
+
items: ['First', 'Second']
|
8
|
+
}
|
9
|
+
@row = Formotion::Row.new(row_settings)
|
10
|
+
@row.reuse_identifier = 'test'
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should initialize with correct settings" do
|
14
|
+
@row.object.class.should == Formotion::RowType::OptionsRow
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should build cell with segmented control" do
|
18
|
+
cell = @row.make_cell
|
19
|
+
cell.accessoryView.class.should == UISegmentedControl
|
20
|
+
end
|
21
|
+
|
22
|
+
# Value
|
23
|
+
it "should select default value" do
|
24
|
+
cell = @row.make_cell
|
25
|
+
|
26
|
+
cell.accessoryView.selectedSegmentIndex.should == -1
|
27
|
+
@row.value.should == nil
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should select custom value" do
|
31
|
+
@row.value = 'Second'
|
32
|
+
cell = @row.make_cell
|
33
|
+
|
34
|
+
cell.accessoryView.selectedSegmentIndex.should == 1
|
35
|
+
@row.value.should == 'Second'
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
describe "Phone Row" do
|
2
|
+
before do
|
3
|
+
row_settings = {
|
4
|
+
title: "Phone",
|
5
|
+
key: :phone,
|
6
|
+
type: :phone,
|
7
|
+
}
|
8
|
+
@row = Formotion::Row.new(row_settings)
|
9
|
+
@row.reuse_identifier = 'test'
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should initialize with correct settings" do
|
13
|
+
@row.object.class.should == Formotion::RowType::PhoneRow
|
14
|
+
end
|
15
|
+
|
16
|
+
# Keyboard
|
17
|
+
it "should use phone keyboard" do
|
18
|
+
cell = @row.make_cell
|
19
|
+
@row.text_field.keyboardType.should == UIKeyboardTypePhonePad
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
describe "Slider Row" do
|
2
|
+
before do
|
3
|
+
row_settings = {
|
4
|
+
title: "Slider",
|
5
|
+
key: :slider,
|
6
|
+
type: :slider,
|
7
|
+
range: (1..100)
|
8
|
+
}
|
9
|
+
@row = Formotion::Row.new(row_settings)
|
10
|
+
@row.reuse_identifier = 'test'
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should initialize with correct settings" do
|
14
|
+
@row.object.class.should == Formotion::RowType::SliderRow
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should build cell with slider" do
|
18
|
+
cell = @row.make_cell
|
19
|
+
cell.accessoryView.class.should == UISlider
|
20
|
+
end
|
21
|
+
|
22
|
+
# Value
|
23
|
+
it "should set custom value" do
|
24
|
+
@row.value = 50
|
25
|
+
cell = @row.make_cell
|
26
|
+
|
27
|
+
cell.accessoryView.value.should == 50
|
28
|
+
@row.value.should == 50
|
29
|
+
end
|
30
|
+
|
31
|
+
# Range
|
32
|
+
it "should use default range" do
|
33
|
+
@row.range = nil
|
34
|
+
cell = @row.make_cell
|
35
|
+
|
36
|
+
cell.accessoryView.minimumValue.should == 1
|
37
|
+
cell.accessoryView.maximumValue.should == 10
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should use custom range values" do
|
41
|
+
@row.range = (50..100)
|
42
|
+
cell = @row.make_cell
|
43
|
+
|
44
|
+
cell.accessoryView.minimumValue.should == 50
|
45
|
+
cell.accessoryView.maximumValue.should == 100
|
46
|
+
end
|
47
|
+
end
|