iosgen 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Demo/iOSCleanArchitectureGenerator/iOSCleanArchitectureGenerator.xcodeproj/project.pbxproj +501 -0
- data/Demo/iOSCleanArchitectureGenerator/iOSCleanArchitectureGenerator.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
- data/Demo/iOSCleanArchitectureGenerator/iOSCleanArchitectureGenerator.xcodeproj/xcuserdata/fran_dev.xcuserdatad/xcschemes/iOSCleanArchitectureGenerator.xcscheme +110 -0
- data/Demo/iOSCleanArchitectureGenerator/iOSCleanArchitectureGenerator.xcodeproj/xcuserdata/fran_dev.xcuserdatad/xcschemes/xcschememanagement.plist +27 -0
- data/Demo/iOSCleanArchitectureGenerator/iOSCleanArchitectureGenerator/AppDelegate.h +17 -0
- data/Demo/iOSCleanArchitectureGenerator/iOSCleanArchitectureGenerator/AppDelegate.m +45 -0
- data/Demo/iOSCleanArchitectureGenerator/iOSCleanArchitectureGenerator/Base.lproj/LaunchScreen.xib +41 -0
- data/Demo/iOSCleanArchitectureGenerator/iOSCleanArchitectureGenerator/Base.lproj/Main.storyboard +25 -0
- data/Demo/iOSCleanArchitectureGenerator/iOSCleanArchitectureGenerator/Images.xcassets/AppIcon.appiconset/Contents.json +68 -0
- data/Demo/iOSCleanArchitectureGenerator/iOSCleanArchitectureGenerator/Info.plist +47 -0
- data/Demo/iOSCleanArchitectureGenerator/iOSCleanArchitectureGenerator/Interactors/FJBNotificationsApiInteractor.h +9 -0
- data/Demo/iOSCleanArchitectureGenerator/iOSCleanArchitectureGenerator/Interactors/FJBNotificationsApiInteractor.m +15 -0
- data/Demo/iOSCleanArchitectureGenerator/iOSCleanArchitectureGenerator/Interactors/FJBNotificationsApiInteractorProtocol.h +9 -0
- data/Demo/iOSCleanArchitectureGenerator/iOSCleanArchitectureGenerator/ViewController.h +15 -0
- data/Demo/iOSCleanArchitectureGenerator/iOSCleanArchitectureGenerator/ViewController.m +27 -0
- data/Demo/iOSCleanArchitectureGenerator/iOSCleanArchitectureGenerator/ViewControllers/FJBNotificationsViewController.h +8 -0
- data/Demo/iOSCleanArchitectureGenerator/iOSCleanArchitectureGenerator/ViewControllers/FJBNotificationsViewController.m +31 -0
- data/Demo/iOSCleanArchitectureGenerator/iOSCleanArchitectureGenerator/ViewModels/FJBNotificationsViewModel.h +9 -0
- data/Demo/iOSCleanArchitectureGenerator/iOSCleanArchitectureGenerator/ViewModels/FJBNotificationsViewModel.m +18 -0
- data/Demo/iOSCleanArchitectureGenerator/iOSCleanArchitectureGenerator/ViewModels/FJBNotificationsViewModelProtocol.h +17 -0
- data/Demo/iOSCleanArchitectureGenerator/iOSCleanArchitectureGenerator/main.m +16 -0
- data/Demo/iOSCleanArchitectureGenerator/iOSCleanArchitectureGeneratorTests/Info.plist +24 -0
- data/Demo/iOSCleanArchitectureGenerator/iOSCleanArchitectureGeneratorTests/Interactors/FJBNotificationsApiInteractorTests.m +40 -0
- data/Demo/iOSCleanArchitectureGenerator/iOSCleanArchitectureGeneratorTests/ViewModels/FJBNotificationsViewModelTests.m +50 -0
- data/Demo/iOSCleanArchitectureGenerator/iOSCleanArchitectureGeneratorTests/iOSCleanArchitectureGeneratorTests.m +40 -0
- data/README.md +37 -20
- data/bin/iosgen +1 -1
- data/iosgen.gemspec +1 -1
- data/lib/ios_gen/generator/base_generator.rb +21 -9
- data/lib/ios_gen/generator/objc/action_formatter.rb +15 -2
- data/lib/ios_gen/generator/objc/interactor_formatter.rb +16 -11
- data/lib/ios_gen/generator/objc/objc_formatter.rb +4 -0
- data/lib/ios_gen/generator/objc/view_model_formatter.rb +18 -10
- data/lib/ios_gen/generator/objc/xctestcase_formatter.rb +45 -0
- data/lib/ios_gen/ios_gen_thor.rb +2 -1
- data/spec/ios_gen/generator/base_generator_spec.rb +38 -3
- data/spec/ios_gen/generator/objc/action_formatter_spec.rb +16 -1
- data/spec/ios_gen/generator/objc/interactor_formatter_spec.rb +1 -1
- data/spec/ios_gen/generator/objc/objc_formatter_spec.rb +0 -1
- data/spec/ios_gen/generator/objc/view_model_formatter_spec.rb +0 -1
- data/spec/ios_gen/generator/objc/xctestcase_formatter_spec.rb +91 -0
- data/templates/objc/Interactor.h.erb +1 -1
- data/templates/objc/InteractorProtocol.h.erb +2 -0
- data/templates/objc/ViewModel.h.erb +1 -1
- data/templates/objc/ViewModelProtocol.h.erb +1 -0
- data/templates/objc/XCTestCase.m.erb +32 -0
- metadata +31 -2
@@ -4,8 +4,7 @@ module IOSGen
|
|
4
4
|
# Objective-C Action Formatter
|
5
5
|
class ActionFormatter
|
6
6
|
def generate_interface(action)
|
7
|
-
result = ''
|
8
|
-
result += "// #{action.description}\n" unless action.description.nil?
|
7
|
+
result = '' + add_description(action)
|
9
8
|
result += "- (#{action.return_type})"
|
10
9
|
result += parse_action_arguments(action) + ';'
|
11
10
|
result
|
@@ -17,8 +16,22 @@ module IOSGen
|
|
17
16
|
result
|
18
17
|
end
|
19
18
|
|
19
|
+
def generate_test(action)
|
20
|
+
result = add_description(action) + "\n"
|
21
|
+
result += '- (void)test'
|
22
|
+
final_name = "#{action.name}".gsub(':', '')
|
23
|
+
result += final_name + 'ShouldPass' "\n{\n"
|
24
|
+
result += " // given\n // when\n // then\n"
|
25
|
+
result += " XCTFail(@\"No implemented test\");\n}\n"
|
26
|
+
result
|
27
|
+
end
|
28
|
+
|
20
29
|
private
|
21
30
|
|
31
|
+
def add_description(action)
|
32
|
+
"// #{action.description}\n" unless action.description.nil?
|
33
|
+
end
|
34
|
+
|
22
35
|
def parse_action_arguments(action)
|
23
36
|
index = 0
|
24
37
|
final_name = "#{action.name}".gsub(':') do
|
@@ -4,7 +4,7 @@ module IOSGen
|
|
4
4
|
# Objective-C Interactor Formatter
|
5
5
|
class InteractorFormatter
|
6
6
|
# File Names Interactors
|
7
|
-
attr_reader :header_file_name, :
|
7
|
+
attr_reader :header_file_name, :impl_file_name
|
8
8
|
attr_reader :protocol_file_name
|
9
9
|
# Interactor Protocol
|
10
10
|
attr_reader :protocol_name
|
@@ -40,21 +40,15 @@ module IOSGen
|
|
40
40
|
end
|
41
41
|
|
42
42
|
def actions_header
|
43
|
-
|
44
|
-
|
45
|
-
@interactor.actions.each do |action|
|
46
|
-
actions += "#{action_formatter.generate_interface(action)}\n"
|
43
|
+
loop_actions do |formatter, action|
|
44
|
+
formatter.generate_interface(action)
|
47
45
|
end
|
48
|
-
actions.chop
|
49
46
|
end
|
50
47
|
|
51
48
|
def actions_impl
|
52
|
-
|
53
|
-
|
54
|
-
@interactor.actions.each do |action|
|
55
|
-
actions += "#{action_formatter.generate_implementation(action)}\n"
|
49
|
+
loop_actions do |formatter, action|
|
50
|
+
formatter.generate_implementation(action)
|
56
51
|
end
|
57
|
-
actions.chop
|
58
52
|
end
|
59
53
|
|
60
54
|
def generate(&block)
|
@@ -62,6 +56,17 @@ module IOSGen
|
|
62
56
|
block.call(header_file_name, 'templates/objc/Interactor.h.erb')
|
63
57
|
block.call(impl_file_name, 'templates/objc/Interactor.m.erb')
|
64
58
|
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def loop_actions
|
63
|
+
actions = ''
|
64
|
+
action_formatter = ActionFormatter.new
|
65
|
+
@interactor.actions.each do |action|
|
66
|
+
actions += "#{yield(action_formatter, action)}\n"
|
67
|
+
end
|
68
|
+
actions.chop
|
69
|
+
end
|
65
70
|
end
|
66
71
|
end
|
67
72
|
end
|
@@ -50,21 +50,15 @@ module IOSGen
|
|
50
50
|
end
|
51
51
|
|
52
52
|
def actions_header
|
53
|
-
|
54
|
-
|
55
|
-
@view_model.actions.each do |action|
|
56
|
-
actions += "#{action_formatter.generate_interface(action)}\n"
|
53
|
+
loop_actions do |formatter, action|
|
54
|
+
formatter.generate_interface(action)
|
57
55
|
end
|
58
|
-
actions.chop
|
59
56
|
end
|
60
57
|
|
61
58
|
def actions_impl
|
62
|
-
|
63
|
-
|
64
|
-
@view_model.actions.each do |action|
|
65
|
-
actions += "#{action_formatter.generate_implementation(action)}\n"
|
59
|
+
loop_actions do |formatter, action|
|
60
|
+
formatter.generate_implementation(action)
|
66
61
|
end
|
67
|
-
actions.chop
|
68
62
|
end
|
69
63
|
|
70
64
|
def generate(&block)
|
@@ -74,6 +68,11 @@ module IOSGen
|
|
74
68
|
generate_interactor(&block)
|
75
69
|
end
|
76
70
|
|
71
|
+
def generate_test(&block)
|
72
|
+
block.call(test_file_name, 'templates/objc/XCTestCase.m.erb')
|
73
|
+
generate_interactor_test(&block)
|
74
|
+
end
|
75
|
+
|
77
76
|
private
|
78
77
|
|
79
78
|
def generate_interactor(&block)
|
@@ -82,6 +81,15 @@ module IOSGen
|
|
82
81
|
@interactor_formatter.generate(&block)
|
83
82
|
end unless @view_model.interactors.nil?
|
84
83
|
end
|
84
|
+
|
85
|
+
def loop_actions
|
86
|
+
actions = ''
|
87
|
+
action_formatter = ActionFormatter.new
|
88
|
+
@view_model.actions.each do |action|
|
89
|
+
actions += "#{yield(action_formatter, action)}\n"
|
90
|
+
end
|
91
|
+
actions.chop
|
92
|
+
end
|
85
93
|
end
|
86
94
|
end
|
87
95
|
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module IOSGen
|
2
|
+
module Generator
|
3
|
+
module Objc
|
4
|
+
# Objetive-C XCTestCase Formatter
|
5
|
+
class XctestcaseFormatter
|
6
|
+
attr_accessor :object
|
7
|
+
attr_reader :file_name, :name, :actions_impl
|
8
|
+
attr_reader :class_test_name
|
9
|
+
|
10
|
+
def file_name
|
11
|
+
"#{@object.name}Tests.m" if @object.respond_to?(:name)
|
12
|
+
end
|
13
|
+
|
14
|
+
def name
|
15
|
+
"#{@object.name}Tests" if @object.respond_to?(:name)
|
16
|
+
end
|
17
|
+
|
18
|
+
def actions_impl
|
19
|
+
loop_actions do |formatter, action|
|
20
|
+
formatter.generate_test(action)
|
21
|
+
end if @object.respond_to?(:actions)
|
22
|
+
end
|
23
|
+
|
24
|
+
def class_test_name
|
25
|
+
"#{@object.name}.h" if @object.respond_to?(:name)
|
26
|
+
end
|
27
|
+
|
28
|
+
def generate(&block)
|
29
|
+
block.call(file_name, 'templates/objc/XCTestCase.m.erb')
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def loop_actions
|
35
|
+
actions = ''
|
36
|
+
action_formatter = ActionFormatter.new
|
37
|
+
@object.actions.each do |action|
|
38
|
+
actions += "#{yield(action_formatter, action)}\n"
|
39
|
+
end
|
40
|
+
actions.chop
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/ios_gen/ios_gen_thor.rb
CHANGED
@@ -7,11 +7,12 @@ class IOSGenThor < Thor
|
|
7
7
|
end
|
8
8
|
|
9
9
|
desc 'generate', 'Generate new code with spec file'
|
10
|
-
|
10
|
+
option :test, aliases: '-t', desc: 'Generate unit tests'
|
11
11
|
# method_option :languague, aliases: '-l', desc: 'objc or swift'
|
12
12
|
def generate(file_path)
|
13
13
|
puts file_path
|
14
14
|
generator = IOSGen::Generator::BaseGenerator.new(file_spec: file_path)
|
15
15
|
generator.generate
|
16
|
+
generator.generate_test if options[:test]
|
16
17
|
end
|
17
18
|
end
|
@@ -23,9 +23,9 @@ describe IOSGen::Generator::BaseGenerator do
|
|
23
23
|
|
24
24
|
end
|
25
25
|
|
26
|
-
describe '
|
26
|
+
describe 'Methods' do
|
27
27
|
|
28
|
-
describe '
|
28
|
+
describe 'Objc' do
|
29
29
|
it 'has generate method' do
|
30
30
|
expect(generator).to respond_to(:generate)
|
31
31
|
end
|
@@ -37,7 +37,7 @@ describe IOSGen::Generator::BaseGenerator do
|
|
37
37
|
file_path = File.dirname(__FILE__) + '/spec.json'
|
38
38
|
generator = described_class.new(type: :objc,
|
39
39
|
file_spec: file_path)
|
40
|
-
|
40
|
+
|
41
41
|
before(:all) do
|
42
42
|
generator.generate
|
43
43
|
end
|
@@ -78,6 +78,41 @@ describe IOSGen::Generator::BaseGenerator do
|
|
78
78
|
expect(File).to exist(file_path_protocol)
|
79
79
|
end
|
80
80
|
end
|
81
|
+
|
82
|
+
|
83
|
+
describe '#generate_test' do
|
84
|
+
it 'has a generate_test method' do
|
85
|
+
expect(generator).to respond_to(:generate_test)
|
86
|
+
end
|
87
|
+
|
88
|
+
context 'No spec file' do
|
89
|
+
end
|
90
|
+
|
91
|
+
context 'New Test files' do
|
92
|
+
file_path = File.dirname(__FILE__) + '/spec.json'
|
93
|
+
generator = described_class.new(type: :objc,
|
94
|
+
file_spec: file_path)
|
95
|
+
|
96
|
+
before(:all) do
|
97
|
+
generator.generate_test
|
98
|
+
end
|
99
|
+
|
100
|
+
after(:all) do
|
101
|
+
FileUtils.rm(File.expand_path('../../../FJBNotificationsViewModelTests.m', File.dirname(__FILE__)))
|
102
|
+
FileUtils.rm(File.expand_path('../../../FJBNotificationsApiInteractorTests.m', File.dirname(__FILE__)))
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'has to generate ViewModels unit test files' do
|
106
|
+
file_path_test = File.expand_path('../../../FJBNotificationsViewModelTests.m', File.dirname(__FILE__))
|
107
|
+
expect(File).to exist(file_path_test)
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'has to generate Interactors unit test files' do
|
111
|
+
file_path_test = File.expand_path('../../../FJBNotificationsApiInteractorTests.m', File.dirname(__FILE__))
|
112
|
+
expect(File).to exist(file_path_test)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
81
116
|
end
|
82
117
|
|
83
118
|
end
|
@@ -26,6 +26,11 @@ describe IOSGen::Generator::Objc::ActionFormatter do
|
|
26
26
|
expect(result).to eq(expected_string)
|
27
27
|
end
|
28
28
|
|
29
|
+
it 'has to generate test format' do
|
30
|
+
expected_string = "// Dismiss the ViewController when the button is tapped\n\n- (void)testdidTapOnCloseButtonShouldPass\n{\n // given\n // when\n // then\n XCTFail(@\"No implemented test\");\n}\n"
|
31
|
+
result = action_generator.generate_test(action)
|
32
|
+
expect(result).to eq(expected_string)
|
33
|
+
end
|
29
34
|
end
|
30
35
|
|
31
36
|
describe 'Actions with an argument' do
|
@@ -50,6 +55,11 @@ describe IOSGen::Generator::Objc::ActionFormatter do
|
|
50
55
|
expect(result).to eq(expected_string)
|
51
56
|
end
|
52
57
|
|
58
|
+
it 'has to generate test format' do
|
59
|
+
expected_string = "// Dismiss the ViewController when the button is tapped\n\n- (void)testdidTapOnCloseButtonShouldPass\n{\n // given\n // when\n // then\n XCTFail(@\"No implemented test\");\n}\n"
|
60
|
+
result = action_generator.generate_test(action)
|
61
|
+
expect(result).to eq(expected_string)
|
62
|
+
end
|
53
63
|
end
|
54
64
|
|
55
65
|
describe 'Actions with multiples arguments' do
|
@@ -83,6 +93,11 @@ describe IOSGen::Generator::Objc::ActionFormatter do
|
|
83
93
|
result = action_generator.generate_implementation(action)
|
84
94
|
expect(result).to eq(expected_string)
|
85
95
|
end
|
86
|
-
end
|
87
96
|
|
97
|
+
it 'has to generate test format' do
|
98
|
+
expected_string = "// Dismiss the ViewController when the button is tapped\n\n- (void)testdidTapOnCloseButtonsuccessShouldPass\n{\n // given\n // when\n // then\n XCTFail(@\"No implemented test\");\n}\n"
|
99
|
+
result = action_generator.generate_test(action)
|
100
|
+
expect(result).to eq(expected_string)
|
101
|
+
end
|
102
|
+
end
|
88
103
|
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe IOSGen::Generator::Objc::XctestcaseFormatter do
|
4
|
+
context 'Formatter with all object properties' do
|
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
|
+
view_model = ViewModel.new(description: description,
|
21
|
+
name: name,
|
22
|
+
properties: properties,
|
23
|
+
actions: actions)
|
24
|
+
|
25
|
+
formatter = described_class.new
|
26
|
+
formatter.object = view_model
|
27
|
+
|
28
|
+
describe '#Properties' do
|
29
|
+
it 'has a name' do
|
30
|
+
expect(formatter.name).to eq('FJBNotificationsViewModelTests')
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'has file_name' do
|
34
|
+
expect(formatter.file_name).to eq('FJBNotificationsViewModelTests.m')
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'has class_test_name' do
|
38
|
+
expect(formatter.class_test_name).to eq('FJBNotificationsViewModel.h')
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'has actions_impl' do
|
42
|
+
expected_string = "// Dismiss the ViewController when the button is tapped\n\n- (void)testdidTapOnCloseButtonShouldPass\n{\n // given\n // when\n // then\n XCTFail(@\"No implemented test\");\n}\n\n// Mark notification as read when the notification is selected\n\n- (void)testdidTapAtIndexPathShouldPass\n{\n // given\n // when\n // then\n XCTFail(@\"No implemented test\");\n}\n"
|
43
|
+
expect(formatter.actions_impl).to eq(expected_string)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe '#generate' do
|
48
|
+
it 'has to yield 2 times' do
|
49
|
+
expect { |b| formatter.generate(&b) }.to yield_control.exactly(1).times
|
50
|
+
end
|
51
|
+
|
52
|
+
file_names = []
|
53
|
+
templates = []
|
54
|
+
|
55
|
+
formatter.generate do |file_name, template|
|
56
|
+
file_names << file_name
|
57
|
+
templates << template
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'has to return ViewModel test file name and template' do
|
61
|
+
expect(file_names[0]).to eq(formatter.file_name)
|
62
|
+
expect(templates[0]).to eq('templates/objc/XCTestCase.m.erb')
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context 'Formatter with no properties' do
|
68
|
+
view_model = 'ViewModel.new'
|
69
|
+
|
70
|
+
formatter = described_class.new
|
71
|
+
formatter.object = view_model
|
72
|
+
|
73
|
+
describe '#Properties' do
|
74
|
+
it 'has a name' do
|
75
|
+
expect(formatter.name).to be_nil
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'has file_name' do
|
79
|
+
expect(formatter.file_name).to be_nil
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'has class_test_name' do
|
83
|
+
expect(formatter.class_test_name).to be_nil
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'has actions_impl' do
|
87
|
+
expect(formatter.actions_impl).to be_nil
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
#import "<%=@formatter.view_model_formatter.interactor_formatter.protocol_file_name%>"
|
2
2
|
|
3
|
-
@interface <%=@formatter.view_model_formatter.interactor_formatter.interactor.name%> <<%=@formatter.view_model_formatter.interactor_formatter.protocol_name%>>
|
3
|
+
@interface <%=@formatter.view_model_formatter.interactor_formatter.interactor.name%> : NSObject <<%=@formatter.view_model_formatter.interactor_formatter.protocol_name%>>
|
4
4
|
<%if @formatter.view_model_formatter.interactor_formatter.properties_header.nil?%>
|
5
5
|
// -- Properties
|
6
6
|
<%=@formatter.view_model_formatter.interactor_formatter.properties_header %>
|
@@ -1,6 +1,6 @@
|
|
1
1
|
#import "<%=@formatter.view_model_formatter.protocol_file_name%>"
|
2
2
|
|
3
|
-
@interface <%=@view_model.name %> <<%=@formatter.view_model_formatter.protocol_name%>>
|
3
|
+
@interface <%=@view_model.name %> : NSObject <<%=@formatter.view_model_formatter.protocol_name%>>
|
4
4
|
|
5
5
|
// -- Properties
|
6
6
|
<%=@formatter.view_model_formatter.properties_header %>
|