iosgen 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/Demo/iOSCleanArchitectureGenerator/iOSCleanArchitectureGenerator.xcodeproj/project.pbxproj +501 -0
  3. data/Demo/iOSCleanArchitectureGenerator/iOSCleanArchitectureGenerator.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
  4. data/Demo/iOSCleanArchitectureGenerator/iOSCleanArchitectureGenerator.xcodeproj/xcuserdata/fran_dev.xcuserdatad/xcschemes/iOSCleanArchitectureGenerator.xcscheme +110 -0
  5. data/Demo/iOSCleanArchitectureGenerator/iOSCleanArchitectureGenerator.xcodeproj/xcuserdata/fran_dev.xcuserdatad/xcschemes/xcschememanagement.plist +27 -0
  6. data/Demo/iOSCleanArchitectureGenerator/iOSCleanArchitectureGenerator/AppDelegate.h +17 -0
  7. data/Demo/iOSCleanArchitectureGenerator/iOSCleanArchitectureGenerator/AppDelegate.m +45 -0
  8. data/Demo/iOSCleanArchitectureGenerator/iOSCleanArchitectureGenerator/Base.lproj/LaunchScreen.xib +41 -0
  9. data/Demo/iOSCleanArchitectureGenerator/iOSCleanArchitectureGenerator/Base.lproj/Main.storyboard +25 -0
  10. data/Demo/iOSCleanArchitectureGenerator/iOSCleanArchitectureGenerator/Images.xcassets/AppIcon.appiconset/Contents.json +68 -0
  11. data/Demo/iOSCleanArchitectureGenerator/iOSCleanArchitectureGenerator/Info.plist +47 -0
  12. data/Demo/iOSCleanArchitectureGenerator/iOSCleanArchitectureGenerator/Interactors/FJBNotificationsApiInteractor.h +9 -0
  13. data/Demo/iOSCleanArchitectureGenerator/iOSCleanArchitectureGenerator/Interactors/FJBNotificationsApiInteractor.m +15 -0
  14. data/Demo/iOSCleanArchitectureGenerator/iOSCleanArchitectureGenerator/Interactors/FJBNotificationsApiInteractorProtocol.h +9 -0
  15. data/Demo/iOSCleanArchitectureGenerator/iOSCleanArchitectureGenerator/ViewController.h +15 -0
  16. data/Demo/iOSCleanArchitectureGenerator/iOSCleanArchitectureGenerator/ViewController.m +27 -0
  17. data/Demo/iOSCleanArchitectureGenerator/iOSCleanArchitectureGenerator/ViewControllers/FJBNotificationsViewController.h +8 -0
  18. data/Demo/iOSCleanArchitectureGenerator/iOSCleanArchitectureGenerator/ViewControllers/FJBNotificationsViewController.m +31 -0
  19. data/Demo/iOSCleanArchitectureGenerator/iOSCleanArchitectureGenerator/ViewModels/FJBNotificationsViewModel.h +9 -0
  20. data/Demo/iOSCleanArchitectureGenerator/iOSCleanArchitectureGenerator/ViewModels/FJBNotificationsViewModel.m +18 -0
  21. data/Demo/iOSCleanArchitectureGenerator/iOSCleanArchitectureGenerator/ViewModels/FJBNotificationsViewModelProtocol.h +17 -0
  22. data/Demo/iOSCleanArchitectureGenerator/iOSCleanArchitectureGenerator/main.m +16 -0
  23. data/Demo/iOSCleanArchitectureGenerator/iOSCleanArchitectureGeneratorTests/Info.plist +24 -0
  24. data/Demo/iOSCleanArchitectureGenerator/iOSCleanArchitectureGeneratorTests/Interactors/FJBNotificationsApiInteractorTests.m +40 -0
  25. data/Demo/iOSCleanArchitectureGenerator/iOSCleanArchitectureGeneratorTests/ViewModels/FJBNotificationsViewModelTests.m +50 -0
  26. data/Demo/iOSCleanArchitectureGenerator/iOSCleanArchitectureGeneratorTests/iOSCleanArchitectureGeneratorTests.m +40 -0
  27. data/README.md +37 -20
  28. data/bin/iosgen +1 -1
  29. data/iosgen.gemspec +1 -1
  30. data/lib/ios_gen/generator/base_generator.rb +21 -9
  31. data/lib/ios_gen/generator/objc/action_formatter.rb +15 -2
  32. data/lib/ios_gen/generator/objc/interactor_formatter.rb +16 -11
  33. data/lib/ios_gen/generator/objc/objc_formatter.rb +4 -0
  34. data/lib/ios_gen/generator/objc/view_model_formatter.rb +18 -10
  35. data/lib/ios_gen/generator/objc/xctestcase_formatter.rb +45 -0
  36. data/lib/ios_gen/ios_gen_thor.rb +2 -1
  37. data/spec/ios_gen/generator/base_generator_spec.rb +38 -3
  38. data/spec/ios_gen/generator/objc/action_formatter_spec.rb +16 -1
  39. data/spec/ios_gen/generator/objc/interactor_formatter_spec.rb +1 -1
  40. data/spec/ios_gen/generator/objc/objc_formatter_spec.rb +0 -1
  41. data/spec/ios_gen/generator/objc/view_model_formatter_spec.rb +0 -1
  42. data/spec/ios_gen/generator/objc/xctestcase_formatter_spec.rb +91 -0
  43. data/templates/objc/Interactor.h.erb +1 -1
  44. data/templates/objc/InteractorProtocol.h.erb +2 -0
  45. data/templates/objc/ViewModel.h.erb +1 -1
  46. data/templates/objc/ViewModelProtocol.h.erb +1 -0
  47. data/templates/objc/XCTestCase.m.erb +32 -0
  48. 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, :_impl_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
- actions = ''
44
- action_formatter = ActionFormatter.new
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
- actions = ''
53
- action_formatter = ActionFormatter.new
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
@@ -24,6 +24,10 @@ module IOSGen
24
24
  @view_controller_formatter.generate(&block)
25
25
  @view_model_formatter.generate(&block)
26
26
  end
27
+
28
+ def generate_test(&block)
29
+ @view_model_formatter.generate_test(&block)
30
+ end
27
31
  end
28
32
  end
29
33
  end
@@ -50,21 +50,15 @@ module IOSGen
50
50
  end
51
51
 
52
52
  def actions_header
53
- actions = ''
54
- action_formatter = ActionFormatter.new
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
- actions = ''
63
- action_formatter = ActionFormatter.new
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
@@ -7,11 +7,12 @@ class IOSGenThor < Thor
7
7
  end
8
8
 
9
9
  desc 'generate', 'Generate new code with spec file'
10
- # method_option :destination, aliases: '-d', desc: 'destination path'
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 '#Methods' do
26
+ describe 'Methods' do
27
27
 
28
- describe '#Objc' do
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
- puts file_path
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
@@ -48,7 +48,7 @@ describe IOSGen::Generator::Objc::InteractorFormatter do
48
48
  end
49
49
  end
50
50
 
51
- describe 'Generate' do
51
+ describe '#generate' do
52
52
  it 'has to yield 3 times' do
53
53
  expect { |b| formatter.generate(&b) }.to yield_control.exactly(3).times
54
54
  end
@@ -48,5 +48,4 @@ describe IOSGen::Generator::Objc::Formatter do
48
48
  expect { |b| formatter.generate(&b) }.to yield_control.exactly(8).times
49
49
  end
50
50
  end
51
-
52
51
  end
@@ -120,6 +120,5 @@ describe IOSGen::Generator::Objc::ViewModelFormatter do
120
120
  expect(file_names[5]).to eq(formatter.interactor_formatter.impl_file_name)
121
121
  expect(templates[5]).to eq('templates/objc/Interactor.m.erb')
122
122
  end
123
-
124
123
  end
125
124
  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,3 +1,5 @@
1
+ #import <Foundation/Foundation.h>
2
+
1
3
  @protocol <%=@formatter.view_model_formatter.interactor_formatter.protocol_name%> <NSObject>
2
4
  <%if @formatter.view_model_formatter.interactor_formatter.properties_header.nil?%>
3
5
  // -- Properties
@@ -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 %>