iosgen 1.0.0 → 1.1.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.
- 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 %>
|