iosgen 1.0.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 (50) hide show
  1. checksums.yaml +7 -0
  2. data/.coveralls.yml +1 -0
  3. data/.gitignore +37 -0
  4. data/.hound.yml +6 -0
  5. data/.rubocop.yml +7 -0
  6. data/Gemfile +19 -0
  7. data/Gemfile.lock +110 -0
  8. data/Guardfile +16 -0
  9. data/LICENSE +22 -0
  10. data/README.md +158 -0
  11. data/Rakefile +28 -0
  12. data/bin/iosgen +6 -0
  13. data/iosgen.gemspec +29 -0
  14. data/lib/ios_gen/base/action.rb +15 -0
  15. data/lib/ios_gen/base/base_factory.rb +73 -0
  16. data/lib/ios_gen/base/interactor.rb +15 -0
  17. data/lib/ios_gen/base/property.rb +13 -0
  18. data/lib/ios_gen/base/view_controller.rb +15 -0
  19. data/lib/ios_gen/base/view_model.rb +16 -0
  20. data/lib/ios_gen/generator/base_generator.rb +61 -0
  21. data/lib/ios_gen/generator/objc/action_formatter.rb +35 -0
  22. data/lib/ios_gen/generator/objc/interactor_formatter.rb +68 -0
  23. data/lib/ios_gen/generator/objc/objc_formatter.rb +30 -0
  24. data/lib/ios_gen/generator/objc/view_controller_formatter.rb +37 -0
  25. data/lib/ios_gen/generator/objc/view_model_formatter.rb +88 -0
  26. data/lib/ios_gen/ios_gen_thor.rb +17 -0
  27. data/lib/iosgen.rb +5 -0
  28. data/spec/ios_gen/base/action_spec.rb +50 -0
  29. data/spec/ios_gen/base/base_factory_spec.rb +238 -0
  30. data/spec/ios_gen/base/interactor_spec.rb +60 -0
  31. data/spec/ios_gen/base/property_spec.rb +26 -0
  32. data/spec/ios_gen/base/view_controller_spec.rb +18 -0
  33. data/spec/ios_gen/base/view_model_spec.rb +70 -0
  34. data/spec/ios_gen/generator/base_generator_spec.rb +84 -0
  35. data/spec/ios_gen/generator/objc/action_formatter_spec.rb +88 -0
  36. data/spec/ios_gen/generator/objc/interactor_formatter_spec.rb +79 -0
  37. data/spec/ios_gen/generator/objc/objc_formatter_spec.rb +52 -0
  38. data/spec/ios_gen/generator/objc/view_controller_formatter_spec.rb +52 -0
  39. data/spec/ios_gen/generator/objc/view_model_formatter_spec.rb +125 -0
  40. data/spec/ios_gen/generator/spec.json +58 -0
  41. data/spec/spec_helper.rb +8 -0
  42. data/templates/objc/Interactor.h.erb +11 -0
  43. data/templates/objc/Interactor.m.erb +13 -0
  44. data/templates/objc/InteractorProtocol.h.erb +9 -0
  45. data/templates/objc/UIViewController.h.erb +8 -0
  46. data/templates/objc/UIViewController.m.erb +31 -0
  47. data/templates/objc/ViewModel.h.erb +9 -0
  48. data/templates/objc/ViewModel.m.erb +13 -0
  49. data/templates/objc/ViewModelProtocol.h.erb +16 -0
  50. metadata +178 -0
@@ -0,0 +1,84 @@
1
+ require 'spec_helper'
2
+
3
+ describe IOSGen::Generator::BaseGenerator do
4
+
5
+ file_path = File.dirname(__FILE__) + '/spec.json'
6
+ generator = described_class.new(type: :objc,
7
+ file_spec: file_path)
8
+
9
+ describe '#Intialize' do
10
+ it 'has to be a generator' do
11
+ expect(generator).to be_a described_class
12
+ end
13
+ end
14
+
15
+ describe '#Properties' do
16
+ it 'has a formatter' do
17
+ expect(generator.formatter).to be_a IOSGen::Generator::Objc::Formatter
18
+ end
19
+
20
+ it 'has ViewModel' do
21
+ expect(generator.view_model).to be_a ViewModel
22
+ end
23
+
24
+ end
25
+
26
+ describe '#Methods' do
27
+
28
+ describe '#Objc' do
29
+ it 'has generate method' do
30
+ expect(generator).to respond_to(:generate)
31
+ end
32
+
33
+ context 'No spec file' do
34
+ end
35
+
36
+ context 'New files' do
37
+ file_path = File.dirname(__FILE__) + '/spec.json'
38
+ generator = described_class.new(type: :objc,
39
+ file_spec: file_path)
40
+ puts file_path
41
+ before(:all) do
42
+ generator.generate
43
+ end
44
+
45
+ after(:all) do
46
+ FileUtils.rm(File.expand_path('../../../FJBNotificationsViewController.h', File.dirname(__FILE__)))
47
+ FileUtils.rm(File.expand_path('../../../FJBNotificationsViewController.m', File.dirname(__FILE__)))
48
+ FileUtils.rm(File.expand_path('../../../FJBNotificationsViewModel.h', File.dirname(__FILE__)))
49
+ FileUtils.rm(File.expand_path('../../../FJBNotificationsViewModel.m', File.dirname(__FILE__)))
50
+ FileUtils.rm(File.expand_path('../../../FJBNotificationsViewModelProtocol.h', File.dirname(__FILE__)))
51
+ FileUtils.rm(File.expand_path('../../../FJBNotificationsApiInteractor.h', File.dirname(__FILE__)))
52
+ FileUtils.rm(File.expand_path('../../../FJBNotificationsApiInteractor.m', File.dirname(__FILE__)))
53
+ FileUtils.rm(File.expand_path('../../../FJBNotificationsApiInteractorProtocol.h', File.dirname(__FILE__)))
54
+ end
55
+
56
+ it 'has to generate ViewController files' do
57
+ file_path_header = File.expand_path('../../../FJBNotificationsViewController.h', File.dirname(__FILE__))
58
+ file_path_impl = File.expand_path('../../../FJBNotificationsViewController.m', File.dirname(__FILE__))
59
+ expect(File).to exist(file_path_header)
60
+ expect(File).to exist(file_path_impl)
61
+ end
62
+
63
+ it 'has to generate ViewModels files' do
64
+ file_path_header = File.expand_path('../../../FJBNotificationsViewModel.h', File.dirname(__FILE__))
65
+ file_path_impl = File.expand_path('../../../FJBNotificationsViewModel.m', File.dirname(__FILE__))
66
+ file_path_protocol = File.expand_path('../../../FJBNotificationsViewModelProtocol.h', File.dirname(__FILE__))
67
+ expect(File).to exist(file_path_header)
68
+ expect(File).to exist(file_path_impl)
69
+ expect(File).to exist(file_path_protocol)
70
+ end
71
+
72
+ it 'has to generate Interactors files' do
73
+ file_path_header = File.expand_path('../../../FJBNotificationsApiInteractor.h', File.dirname(__FILE__))
74
+ file_path_impl = File.expand_path('../../../FJBNotificationsApiInteractor.m', File.dirname(__FILE__))
75
+ file_path_protocol = File.expand_path('../../../FJBNotificationsApiInteractorProtocol.h', File.dirname(__FILE__))
76
+ expect(File).to exist(file_path_header)
77
+ expect(File).to exist(file_path_impl)
78
+ expect(File).to exist(file_path_protocol)
79
+ end
80
+ end
81
+ end
82
+
83
+ end
84
+ end
@@ -0,0 +1,88 @@
1
+ require 'spec_helper'
2
+
3
+ describe IOSGen::Generator::Objc::ActionFormatter do
4
+
5
+ describe 'Action without arguments' do
6
+
7
+ action_json = '{
8
+ "description": "Dismiss the ViewController when the button is tapped",
9
+ "return_type": "void",
10
+ "name": "didTapOnCloseButton"
11
+ }'
12
+
13
+ hash = JSON.parse(action_json)
14
+ action = BaseFactory.new.parse_action(hash)
15
+ action_generator = described_class.new
16
+
17
+ it 'has to generate interface format' do
18
+ expected_string = "// Dismiss the ViewController when the button is tapped\n- (void)didTapOnCloseButton;"
19
+ result = action_generator.generate_interface(action)
20
+ expect(result).to eq(expected_string)
21
+ end
22
+
23
+ it 'has to generate implementation format' do
24
+ expected_string = "- (void)didTapOnCloseButton\n{\n}"
25
+ result = action_generator.generate_implementation(action)
26
+ expect(result).to eq(expected_string)
27
+ end
28
+
29
+ end
30
+
31
+ describe 'Actions with an argument' do
32
+
33
+ action = Action.new(description: 'Dismiss the ViewController when the button is tapped',
34
+ name: 'didTapOnCloseButton:',
35
+ return_type: 'void',
36
+ arguments: [Property.new(type: 'UIButton *',
37
+ name: 'closeButton')])
38
+
39
+ action_generator = described_class.new
40
+
41
+ it 'has to generate interface format' do
42
+ expected_string = "// Dismiss the ViewController when the button is tapped\n- (void)didTapOnCloseButton:(UIButton *)closeButton;"
43
+ result = action_generator.generate_interface(action)
44
+ expect(result).to eq(expected_string)
45
+ end
46
+
47
+ it 'has to generate implementation format' do
48
+ expected_string = "- (void)didTapOnCloseButton:(UIButton *)closeButton\n{\n}"
49
+ result = action_generator.generate_implementation(action)
50
+ expect(result).to eq(expected_string)
51
+ end
52
+
53
+ end
54
+
55
+ describe 'Actions with multiples arguments' do
56
+
57
+ action_json = '{
58
+ "description": "Dismiss the ViewController when the button is tapped",
59
+ "return_type": "void",
60
+ "name": "didTapOnCloseButton:success:",
61
+ "arguments": [{
62
+ "type" : "UIButton *",
63
+ "name" : "closeButton"
64
+ },
65
+ {
66
+ "type" : "BOOL",
67
+ "name" : "success"
68
+ }]
69
+ }'
70
+
71
+ hash = JSON.parse(action_json)
72
+ action = BaseFactory.new.parse_action(hash)
73
+ action_generator = described_class.new
74
+
75
+ it 'has to generate interface format' do
76
+ expected_string = "// Dismiss the ViewController when the button is tapped\n- (void)didTapOnCloseButton:(UIButton *)closeButton success:(BOOL)success;"
77
+ result = action_generator.generate_interface(action)
78
+ expect(result).to eq(expected_string)
79
+ end
80
+
81
+ it 'has to generate implementation format' do
82
+ expected_string = "- (void)didTapOnCloseButton:(UIButton *)closeButton success:(BOOL)success\n{\n}"
83
+ result = action_generator.generate_implementation(action)
84
+ expect(result).to eq(expected_string)
85
+ end
86
+ end
87
+
88
+ end
@@ -0,0 +1,79 @@
1
+ require 'spec_helper'
2
+
3
+ describe IOSGen::Generator::Objc::InteractorFormatter do
4
+
5
+ interactor = Interactor.new(description: 'Api Interactions required by Notification ViewModel',
6
+ name: 'FJBNotificationsApiInteractor',
7
+ actions: [Action.new(description: 'Perform API request to mark a notification as read',
8
+ return_type: 'void',
9
+ name: 'markNotificationAsRead:onCompletionBlock:',
10
+ arguments: [Property.new(type: 'NSString *',
11
+ name: 'notificationId'),
12
+ Property.new(type: '^()',
13
+ name: 'completionBlock')
14
+ ])])
15
+
16
+ formatter = described_class.new
17
+ formatter.interactor = interactor
18
+
19
+ describe 'Properties' do
20
+ it 'has header_file_name' do
21
+ expect(formatter.header_file_name).to eq('FJBNotificationsApiInteractor.h')
22
+ end
23
+
24
+ it 'has impl_file_name' do
25
+ expect(formatter.impl_file_name).to eq('FJBNotificationsApiInteractor.m')
26
+ end
27
+
28
+ it 'has protocol_file_name' do
29
+ expect(formatter.protocol_file_name).to eq('FJBNotificationsApiInteractorProtocol.h')
30
+ end
31
+
32
+ it 'has protocol_name' do
33
+ expect(formatter.protocol_name).to eq('FJBNotificationsApiInteractorProtocol')
34
+ end
35
+
36
+ it 'has properties_header' do
37
+ expect(formatter.properties_header).to eq('')
38
+ end
39
+
40
+ it 'has actions_header' do
41
+ expected_string = "// Perform API request to mark a notification as read\n- (void)markNotificationAsRead:(NSString *)notificationId onCompletionBlock:(^())completionBlock;"
42
+ expect(formatter.actions_header).to eq(expected_string)
43
+ end
44
+
45
+ it 'has actions_impl' do
46
+ expected_string = "- (void)markNotificationAsRead:(NSString *)notificationId onCompletionBlock:(^())completionBlock\n{\n}"
47
+ expect(formatter.actions_impl).to eq(expected_string)
48
+ end
49
+ end
50
+
51
+ describe 'Generate' do
52
+ it 'has to yield 3 times' do
53
+ expect { |b| formatter.generate(&b) }.to yield_control.exactly(3).times
54
+ end
55
+
56
+ file_names = []
57
+ templates = []
58
+
59
+ formatter.generate do |file_name, template|
60
+ file_names << file_name
61
+ templates << template
62
+ end
63
+
64
+ it 'has to return protocol file name and template' do
65
+ expect(file_names[0]).to eq(formatter.protocol_file_name)
66
+ expect(templates[0]).to eq('templates/objc/InteractorProtocol.h.erb')
67
+ end
68
+
69
+ it 'has to return header file name and template' do
70
+ expect(file_names[1]).to eq(formatter.header_file_name)
71
+ expect(templates[1]).to eq('templates/objc/Interactor.h.erb')
72
+ end
73
+
74
+ it 'has to return implementation file name and template' do
75
+ expect(file_names[2]).to eq(formatter.impl_file_name)
76
+ expect(templates[2]).to eq('templates/objc/Interactor.m.erb')
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,52 @@
1
+ require 'spec_helper'
2
+
3
+ describe IOSGen::Generator::Objc::Formatter do
4
+
5
+ description = 'State of NotificationViewController and perform bussiness logic'
6
+
7
+ name = 'FJBNotificationsViewModel'
8
+
9
+ properties = [Property.new(type: 'NSIndexPath *', name: 'selectedIndexPath')]
10
+
11
+ actions = [Action.new(description: 'Dismiss the ViewController when the button is tapped',
12
+ return_type: 'void',
13
+ name: 'didTapOnCloseButton'),
14
+ Action.new(description: 'Mark notification as read when the notification is selected',
15
+ return_type: 'void',
16
+ name: 'didTapAtIndexPath:',
17
+ arguments: [Property.new(type: 'NSIndexPath *',
18
+ name: 'indexPath')])]
19
+
20
+ interactors = [Interactor.new(description: 'Api Interactions required by Notification ViewModel',
21
+ name: 'FJBNotificationsApiInteractor',
22
+ actions: [Action.new(description: 'Perform API request to mark a notification as read',
23
+ return_type: 'void',
24
+ name: 'markNotificationAsRead:onCompletionBlock:',
25
+ arguments: [Property.new(type: 'NSString',
26
+ name: 'notificationId'),
27
+ Property.new(type: '^()',
28
+ name: 'completionBlock')
29
+ ])])]
30
+ view_model = ViewModel.new(description: description,
31
+ name: name,
32
+ properties: properties,
33
+ actions: actions,
34
+ interactors: interactors)
35
+
36
+ name_view_controller = 'FJBNotificationViewController'
37
+ description_view_controller = 'ViewController to display notifications'
38
+
39
+ view_controller = ViewController.new(name: name_view_controller,
40
+ description: description_view_controller)
41
+
42
+ formatter = described_class.new
43
+ formatter.view_model = view_model
44
+ formatter.view_controller = view_controller
45
+
46
+ describe '#generate' do
47
+ it 'has to yield 8 times' do
48
+ expect { |b| formatter.generate(&b) }.to yield_control.exactly(8).times
49
+ end
50
+ end
51
+
52
+ end
@@ -0,0 +1,52 @@
1
+ require 'spec_helper'
2
+
3
+ include IOSGen::Generator::Objc
4
+
5
+ describe IOSGen::Generator::Objc::ViewControllerFormatter do
6
+
7
+ name = 'FJBNotificationViewController'
8
+ description = 'ViewController to display notifications'
9
+ view_controller = ViewController.new(name: name,
10
+ description: description)
11
+ formatter = described_class.new
12
+ formatter.view_controller = view_controller
13
+
14
+ describe 'Properties' do
15
+ it 'has header_file_name' do
16
+ expect(formatter.header_file_name).to eq('FJBNotificationViewController.h')
17
+ end
18
+
19
+ it 'has impl_file_name' do
20
+ expect(formatter.impl_file_name).to eq('FJBNotificationViewController.m')
21
+ end
22
+
23
+ it 'has a view_model_formatter' do
24
+ expect(formatter.view_model_formatter).to be_a ViewModelFormatter
25
+ end
26
+ end
27
+
28
+ describe '#generate' do
29
+
30
+ it 'has to yield 2 times' do
31
+ expect { |b| formatter.generate(&b) }.to yield_control.exactly(2).times
32
+ end
33
+
34
+ file_names = []
35
+ templates = []
36
+
37
+ formatter.generate do |file_name, template|
38
+ file_names << file_name
39
+ templates << template
40
+ end
41
+
42
+ it 'has to return header file name and template' do
43
+ expect(file_names[0]).to eq(formatter.header_file_name)
44
+ expect(templates[0]).to eq('templates/objc/UIViewController.h.erb')
45
+ end
46
+
47
+ it 'has to return implementation file name and template' do
48
+ expect(file_names[1]).to eq(formatter.impl_file_name)
49
+ expect(templates[1]).to eq('templates/objc/UIViewController.m.erb')
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,125 @@
1
+ require 'spec_helper'
2
+
3
+ describe IOSGen::Generator::Objc::ViewModelFormatter do
4
+
5
+ description = 'State of NotificationViewController and perform bussiness logic'
6
+
7
+ name = 'FJBNotificationsViewModel'
8
+
9
+ properties = [Property.new(type: 'NSIndexPath *', name: 'selectedIndexPath')]
10
+
11
+ actions = [Action.new(description: 'Dismiss the ViewController when the button is tapped',
12
+ return_type: 'void',
13
+ name: 'didTapOnCloseButton'),
14
+ Action.new(description: 'Mark notification as read when the notification is selected',
15
+ return_type: 'void',
16
+ name: 'didTapAtIndexPath:',
17
+ arguments: [Property.new(type: 'NSIndexPath *',
18
+ name: 'indexPath')])]
19
+
20
+ interactors = [Interactor.new(description: 'Api Interactions required by Notification ViewModel',
21
+ name: 'FJBNotificationsApiInteractor',
22
+ actions: [Action.new(description: 'Perform API request to mark a notification as read',
23
+ return_type: 'void',
24
+ name: 'markNotificationAsRead:onCompletionBlock:',
25
+ arguments: [Property.new(type: 'NSString',
26
+ name: 'notificationId'),
27
+ Property.new(type: '^()',
28
+ name: 'completionBlock')
29
+ ])])]
30
+
31
+ view_model = ViewModel.new(description: description,
32
+ name: name,
33
+ properties: properties,
34
+ actions: actions,
35
+ interactors: interactors)
36
+
37
+ formatter = described_class.new
38
+ formatter.view_model = view_model
39
+
40
+ describe '#Properties ViewModel' do
41
+
42
+ it 'has properties_header' do
43
+ expected_string = '@property (nonatomic, strong) NSIndexPath *selectedIndexPath;'
44
+ expect(formatter.properties_header).to eq(expected_string)
45
+ end
46
+
47
+ it 'has actions_header' do
48
+ expected_string1 = "// Dismiss the ViewController when the button is tapped\n- (void)didTapOnCloseButton;\n"
49
+ expected_string2 = "// Mark notification as read when the notification is selected\n- (void)didTapAtIndexPath:(NSIndexPath *)indexPath;"
50
+ expected_string = expected_string1 + expected_string2
51
+ expect(formatter.actions_header).to eq(expected_string)
52
+ end
53
+
54
+ it 'has actions_impl' do
55
+ expected_string = "- (void)didTapOnCloseButton\n{\n}\n- (void)didTapAtIndexPath:(NSIndexPath *)indexPath\n{\n}"
56
+ expect(formatter.actions_impl).to eq(expected_string)
57
+ end
58
+
59
+ it 'has header_file_name' do
60
+ expect(formatter.header_file_name).to eq('FJBNotificationsViewModel.h')
61
+ end
62
+
63
+ it 'has impl_file_name' do
64
+ expect(formatter.impl_file_name).to eq('FJBNotificationsViewModel.m')
65
+ end
66
+
67
+ it 'has protocol_name' do
68
+ expect(formatter.protocol_name).to eq('FJBNotificationsViewModelProtocol')
69
+ end
70
+
71
+ it 'has protocol_file_name' do
72
+ expect(formatter.protocol_file_name).to eq('FJBNotificationsViewModelProtocol.h')
73
+ end
74
+
75
+ it 'has protocol_delegate' do
76
+ expect(formatter.protocol_delegate).to eq('FJBNotificationsViewModelProtocolDelegate')
77
+ end
78
+ end
79
+
80
+ describe '#generate' do
81
+
82
+ it 'has to yield 6 times' do
83
+ expect { |b| formatter.generate(&b) }.to yield_control.exactly(6).times
84
+ end
85
+
86
+ file_names = []
87
+ templates = []
88
+
89
+ formatter.generate do |file_name, template|
90
+ file_names << file_name
91
+ templates << template
92
+ end
93
+
94
+ it 'has to return protocol file name and template' do
95
+ expect(file_names[0]).to eq(formatter.protocol_file_name)
96
+ expect(templates[0]).to eq('templates/objc/ViewModelProtocol.h.erb')
97
+ end
98
+
99
+ it 'has to return header file name and template' do
100
+ expect(file_names[1]).to eq(formatter.header_file_name)
101
+ expect(templates[1]).to eq('templates/objc/ViewModel.h.erb')
102
+ end
103
+
104
+ it 'has to return implementation file name and template' do
105
+ expect(file_names[2]).to eq(formatter.impl_file_name)
106
+ expect(templates[2]).to eq('templates/objc/ViewModel.m.erb')
107
+ end
108
+
109
+ it 'has to return interactor protocol file name and template' do
110
+ expect(file_names[3]).to eq(formatter.interactor_formatter.protocol_file_name)
111
+ expect(templates[3]).to eq('templates/objc/InteractorProtocol.h.erb')
112
+ end
113
+
114
+ it 'has to return interactor header file name and template' do
115
+ expect(file_names[4]).to eq(formatter.interactor_formatter.header_file_name)
116
+ expect(templates[4]).to eq('templates/objc/Interactor.h.erb')
117
+ end
118
+
119
+ it 'has to return interactor implementation file name and template' do
120
+ expect(file_names[5]).to eq(formatter.interactor_formatter.impl_file_name)
121
+ expect(templates[5]).to eq('templates/objc/Interactor.m.erb')
122
+ end
123
+
124
+ end
125
+ end