Skip to content

Commit bdf1895

Browse files
tinder-SamMarshalltinder-cfullertinder-garricnahapetian
authored
Added the implementation logic to create Plugin tests alongside a plugin (#580)
* Added a tests template for Plugin * Update Sources/NodesXcodeTemplatesGenerator/Resources/Stencils/PluginTests.stencil Co-authored-by: Christopher Fuller <[email protected]> * Update Sources/NodesXcodeTemplatesGenerator/Resources/Stencils/PluginTests.stencil Co-authored-by: Christopher Fuller <[email protected]> * Added override test * addressing comments * Update Sources/NodesXcodeTemplatesGenerator/Resources/Stencils/PluginTests.stencil * Added Implementation For Plugin Tests * Addressing comments * Deleted unused stecils * regened snapshots * Update Tests/NodesXcodeTemplatesGeneratorTests/Support/TestFactories.swift Co-authored-by: Garric Nahapetian <[email protected]> * Update Tests/NodesXcodeTemplatesGeneratorTests/Support/TestFactories.swift Co-authored-by: Garric Nahapetian <[email protected]> * Added Nimble config * Added a tests template for Plugins (#579) * Added a tests template for Plugin * Update Sources/NodesXcodeTemplatesGenerator/Resources/Stencils/PluginTests.stencil Co-authored-by: Christopher Fuller <[email protected]> * Update Sources/NodesXcodeTemplatesGenerator/Resources/Stencils/PluginTests.stencil Co-authored-by: Christopher Fuller <[email protected]> * Added override test * addressing comments * Update Sources/NodesXcodeTemplatesGenerator/Resources/Stencils/PluginTests.stencil * Update Sources/NodesXcodeTemplatesGenerator/Resources/Stencils/PluginTests.stencil * Update Sources/NodesXcodeTemplatesGenerator/Resources/Stencils/PluginTests.stencil Co-authored-by: Christopher Fuller <[email protected]> * Update Sources/NodesXcodeTemplatesGenerator/Resources/Stencils/PluginTests.stencil Co-authored-by: Garric Nahapetian <[email protected]> * Update Sources/NodesXcodeTemplatesGenerator/Resources/Stencils/PluginTests.stencil Co-authored-by: Christopher Fuller <[email protected]> * Update Sources/NodesXcodeTemplatesGenerator/Resources/Stencils/PluginTests.stencil Co-authored-by: Christopher Fuller <[email protected]> --------- Co-authored-by: Christopher Fuller <[email protected]> Co-authored-by: Garric Nahapetian <[email protected]> * Update Sources/NodesXcodeTemplatesGenerator/Resources/Stencils/PluginTests.stencil Co-authored-by: Garric Nahapetian <[email protected]> * Regened Snapshots * Update Tests/NodesXcodeTemplatesGeneratorTests/StencilRendererTests.swift Co-authored-by: Christopher Fuller <[email protected]> * Update Tests/NodesXcodeTemplatesGeneratorTests/StencilRendererTests.swift Co-authored-by: Christopher Fuller <[email protected]> * Update Sources/NodesXcodeTemplatesGenerator/XcodeTemplates/PluginNodeXcodeTemplate.swift Co-authored-by: Christopher Fuller <[email protected]> * addressing comments --------- Co-authored-by: Christopher Fuller <[email protected]> Co-authored-by: Garric Nahapetian <[email protected]> Co-authored-by: Garric Nahapetian <[email protected]>
1 parent 643cec8 commit bdf1895

25 files changed

+357
-26
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
{{ file_header }}
2+
3+
#warning("Manually move this test file to the corresponding test target then delete this warning.")
4+
{% if plugin_tests_imports %}
5+
6+
{% for import in plugin_tests_imports %}
7+
import {{ import }}
8+
{% endfor %}
9+
{% endif %}
10+
11+
@MainActor
12+
final class {{ plugin_name }}PluginTests: XCTestCase {
13+
14+
private var plugin: {{ plugin_name }}PluginImp!
15+
16+
override func setUp() {
17+
super.setUp()
18+
plugin = {{ plugin_name }}PluginImp(componentFactory: injectComponent {
19+
{{ plugin_name }}PluginComponent(parent: $0)
20+
} with: {
21+
let dependency: {{ plugin_name }}PluginDependencyMock = .init()
22+
// dependency.<dependencyName> = <dependencyName>Mock
23+
return dependency
24+
})
25+
}
26+
27+
override func tearDown() {
28+
plugin = nil
29+
super.tearDown()
30+
}
31+
32+
func testPluginIsNotEnabled() {
33+
{% if is_nimble_enabled %}
34+
expect { self.plugin.create() } == nil
35+
{% else %}
36+
XCTAssertNil(plugin.create())
37+
{% endif %}
38+
}
39+
40+
func testOverride() {
41+
{% if is_nimble_enabled %}
42+
expect { self.plugin.override() } != nil
43+
{% else %}
44+
XCTAssertNotNil(plugin.override())
45+
{% endif %}
46+
}
47+
}

Sources/NodesXcodeTemplatesGenerator/StencilContexts/PluginStencilContext.swift

+18-4
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ public struct PluginStencilContext: StencilContext {
88
private let pluginName: String
99
private let returnType: String?
1010
private let pluginImports: [String]
11+
private let pluginTestsImports: [String]
1112
private let isPeripheryCommentEnabled: Bool
13+
private let isNimbleEnabled: Bool
1214

1315
internal var dictionary: [String: Any] {
1416
let dictionary: [String: Any]
@@ -18,14 +20,18 @@ public struct PluginStencilContext: StencilContext {
1820
"plugin_name": pluginName,
1921
"return_type": returnType,
2022
"plugin_imports": pluginImports,
21-
"is_periphery_comment_enabled": isPeripheryCommentEnabled
23+
"plugin_tests_imports": pluginTestsImports,
24+
"is_periphery_comment_enabled": isPeripheryCommentEnabled,
25+
"is_nimble_enabled": isNimbleEnabled
2226
]
2327
} else {
2428
dictionary = [
2529
"file_header": fileHeader,
2630
"plugin_name": pluginName,
2731
"plugin_imports": pluginImports,
28-
"is_periphery_comment_enabled": isPeripheryCommentEnabled
32+
"plugin_tests_imports": pluginTestsImports,
33+
"is_periphery_comment_enabled": isPeripheryCommentEnabled,
34+
"is_nimble_enabled": isNimbleEnabled
2935
]
3036
}
3137
return dictionary
@@ -35,26 +41,34 @@ public struct PluginStencilContext: StencilContext {
3541
fileHeader: String,
3642
pluginName: String,
3743
pluginImports: Set<String>,
38-
isPeripheryCommentEnabled: Bool
44+
pluginTestsImports: Set<String>,
45+
isPeripheryCommentEnabled: Bool,
46+
isNimbleEnabled: Bool
3947
) {
4048
self.fileHeader = fileHeader
4149
self.pluginName = pluginName
4250
self.returnType = nil
4351
self.pluginImports = pluginImports.sortedImports()
52+
self.pluginTestsImports = pluginTestsImports.sortedImports()
4453
self.isPeripheryCommentEnabled = isPeripheryCommentEnabled
54+
self.isNimbleEnabled = isNimbleEnabled
4555
}
4656

4757
public init(
4858
fileHeader: String,
4959
pluginName: String,
5060
returnType: String,
5161
pluginImports: Set<String>,
52-
isPeripheryCommentEnabled: Bool
62+
pluginTestsImports: Set<String>,
63+
isPeripheryCommentEnabled: Bool,
64+
isNimbleEnabled: Bool
5365
) {
5466
self.fileHeader = fileHeader
5567
self.pluginName = pluginName
5668
self.returnType = returnType
5769
self.pluginImports = pluginImports.sortedImports()
70+
self.pluginTestsImports = pluginTestsImports.sortedImports()
5871
self.isPeripheryCommentEnabled = isPeripheryCommentEnabled
72+
self.isNimbleEnabled = isNimbleEnabled
5973
}
6074
}

Sources/NodesXcodeTemplatesGenerator/StencilRenderer.swift

+10-6
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public final class StencilRenderer {
1616
) throws -> [String: String] {
1717
let node: StencilTemplate.Node = .init(for: .variation(for: kind))
1818
let stencils: [StencilTemplate] = node.stencils(includeTests: includeTests)
19-
return try renderNode(stencils: stencils, with: context.dictionary)
19+
return try render(stencils: stencils, with: context.dictionary)
2020
}
2121

2222
public func renderNodeViewInjected(
@@ -25,7 +25,7 @@ public final class StencilRenderer {
2525
) throws -> [String: String] {
2626
let nodeViewInjected: StencilTemplate.NodeViewInjected = .init()
2727
let stencils: [StencilTemplate] = nodeViewInjected.stencils(includeTests: includeTests)
28-
return try renderNode(stencils: stencils, with: context.dictionary)
28+
return try render(stencils: stencils, with: context.dictionary)
2929
}
3030

3131
public func renderNodePreset(
@@ -39,11 +39,15 @@ public final class StencilRenderer {
3939
stencils = StencilTemplate.NodeViewInjected()
4040
.stencils(includeState: false, includeTests: false)
4141
}
42-
return try renderNode(stencils: stencils, with: context.dictionary)
42+
return try render(stencils: stencils, with: context.dictionary)
4343
}
4444

45-
public func renderPlugin(context: PluginStencilContext) throws -> String {
46-
try render(.plugin, with: context.dictionary)
45+
public func renderPlugin(
46+
context: PluginStencilContext,
47+
includeTests: Bool
48+
) throws -> [String: String] {
49+
let stencils: [StencilTemplate] = includeTests ? [.plugin, .pluginTests] : [.plugin]
50+
return try render(stencils: stencils, with: context.dictionary)
4751
}
4852

4953
public func renderPluginList(context: PluginListStencilContext) throws -> String {
@@ -65,7 +69,7 @@ public final class StencilRenderer {
6569
return try environment.renderTemplate(name: stencil.name, context: context)
6670
}
6771

68-
private func renderNode(stencils: [StencilTemplate], with context: [String: Any]) throws -> [String: String] {
72+
private func render(stencils: [StencilTemplate], with context: [String: Any]) throws -> [String: String] {
6973
try Dictionary(uniqueKeysWithValues: stencils.map { stencil in
7074
try (stencil.name, render(stencil, with: context))
7175
})

Sources/NodesXcodeTemplatesGenerator/StencilTemplate.swift

+7-2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ public enum StencilTemplate: Equatable, CustomStringConvertible {
2020
case analyticsTests
2121
case contextTests
2222
case flowTests
23+
case pluginTests
2324
case viewControllerTests(Variation)
2425
case viewStateFactoryTests
2526

@@ -192,6 +193,8 @@ public enum StencilTemplate: Equatable, CustomStringConvertible {
192193
return "ContextTests"
193194
case .flowTests:
194195
return "FlowTests"
196+
case .pluginTests:
197+
return "PluginTests"
195198
case .viewControllerTests:
196199
return "ViewControllerTests"
197200
case .viewStateFactoryTests:
@@ -206,7 +209,7 @@ public enum StencilTemplate: Equatable, CustomStringConvertible {
206209
return description
207210
case let .builder(variation), let .viewController(variation):
208211
return description.appending(variation.rawValue)
209-
case .analyticsTests, .contextTests, .flowTests, .viewStateFactoryTests:
212+
case .analyticsTests, .contextTests, .flowTests, .pluginTests, .viewStateFactoryTests:
210213
return description
211214
case let .viewControllerTests(variation):
212215
return description.appending(variation.rawValue)
@@ -219,7 +222,7 @@ public enum StencilTemplate: Equatable, CustomStringConvertible {
219222
return imports(config: config)
220223
case .viewController:
221224
return imports(config: config).union([uiFramework.import])
222-
case .analyticsTests, .contextTests, .flowTests, .viewControllerTests, .viewStateFactoryTests:
225+
case .analyticsTests, .contextTests, .flowTests, .pluginTests, .viewControllerTests, .viewStateFactoryTests:
223226
return imports(config: config)
224227
}
225228
}
@@ -239,6 +242,8 @@ public enum StencilTemplate: Equatable, CustomStringConvertible {
239242
return baseWithNodes.union(config.reactiveImports).union(config.dependencyInjectionImports)
240243
case .analyticsTests, .contextTests, .flowTests, .viewStateFactoryTests:
241244
return config.baseTestImports
245+
case .pluginTests:
246+
return config.baseTestImports.union(["NodesTesting"])
242247
case .viewControllerTests:
243248
return config.baseTestImports.union(config.reactiveImports)
244249
}

Sources/NodesXcodeTemplatesGenerator/XcodeTemplates/PluginNodeXcodeTemplate.swift

+6-2
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,16 @@ internal struct PluginNodeXcodeTemplate: XcodeTemplate {
1818

1919
internal init(config: Config) {
2020
let plugin: StencilTemplate = .plugin
21-
stencils = [plugin]
21+
let pluginTests: StencilTemplate = .pluginTests
22+
let additional: [StencilTemplate] = config.isTestTemplatesGenerationEnabled ? [pluginTests] : []
23+
stencils = [plugin] + additional
2224
stencilContext = PluginStencilContext(
2325
fileHeader: config.fileHeader,
2426
pluginName: Self.variable(Self.productName),
2527
pluginImports: plugin.imports(config: config),
26-
isPeripheryCommentEnabled: config.isPeripheryCommentEnabled
28+
pluginTestsImports: pluginTests.imports(config: config),
29+
isPeripheryCommentEnabled: config.isPeripheryCommentEnabled,
30+
isNimbleEnabled: config.isNimbleEnabled
2731
)
2832
}
2933
}

Sources/NodesXcodeTemplatesGenerator/XcodeTemplates/PluginXcodeTemplate.swift

+6-2
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,17 @@ internal struct PluginXcodeTemplate: XcodeTemplate {
2121

2222
internal init(config: Config) {
2323
let plugin: StencilTemplate = .plugin
24-
stencils = [plugin]
24+
let pluginTests: StencilTemplate = .pluginTests
25+
let additional: [StencilTemplate] = config.isTestTemplatesGenerationEnabled ? [pluginTests] : []
26+
stencils = [plugin] + additional
2527
stencilContext = PluginStencilContext(
2628
fileHeader: config.fileHeader,
2729
pluginName: Self.variable(Self.productName),
2830
returnType: Self.variable("returnType"),
2931
pluginImports: plugin.imports(config: config),
30-
isPeripheryCommentEnabled: config.isPeripheryCommentEnabled
32+
pluginTestsImports: pluginTests.imports(config: config),
33+
isPeripheryCommentEnabled: config.isPeripheryCommentEnabled,
34+
isNimbleEnabled: config.isNimbleEnabled
3135
)
3236
}
3337
}

Tests/NodesXcodeTemplatesGeneratorTests/StencilRendererTests.swift

+18-6
Original file line numberDiff line numberDiff line change
@@ -143,20 +143,32 @@ final class StencilRendererTests: XCTestCase, TestFactories {
143143
}
144144

145145
func testRenderPlugin() throws {
146+
let stencilRenderer: StencilRenderer = .init()
146147
try mockCounts.forEach { count in
147148
let context: PluginStencilContext = givenPluginStencilContext(mockCount: count)
148-
assertSnapshot(of: try StencilRenderer().renderPlugin(context: context),
149-
as: .lines,
150-
named: "mockCount-\(count)")
149+
let templates: [String: String] = try stencilRenderer
150+
.renderPlugin(context: context, includeTests: true)
151+
expect(templates.keys.sorted()) == ["Plugin", "PluginTests"]
152+
templates.forEach { name, template in
153+
assertSnapshot(of: template,
154+
as: .lines,
155+
named: "\(name)-mockCount-\(count)")
156+
}
151157
}
152158
}
153159

154160
func testRenderPluginWithoutReturnType() throws {
161+
let stencilRenderer: StencilRenderer = .init()
155162
try mockCounts.forEach { count in
156163
let context: PluginStencilContext = givenPluginStencilContextWithoutReturnType(mockCount: count)
157-
assertSnapshot(of: try StencilRenderer().renderPlugin(context: context),
158-
as: .lines,
159-
named: "mockCount-\(count)")
164+
let templates: [String: String] = try stencilRenderer
165+
.renderPlugin(context: context, includeTests: true)
166+
expect(templates.keys.sorted()) == ["Plugin", "PluginTests"]
167+
templates.forEach { name, template in
168+
assertSnapshot(of: template,
169+
as: .lines,
170+
named: "\(name)-mockCount-\(count)")
171+
}
160172
}
161173
}
162174

Tests/NodesXcodeTemplatesGeneratorTests/StencilTemplateTests.swift

+7
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ final class StencilTemplateTests: XCTestCase, TestFactories {
6868
expect(name) == "ContextTests"
6969
case .flowTests:
7070
expect(name) == "FlowTests"
71+
case .pluginTests:
72+
expect(name) == "PluginTests"
7173
case .viewControllerTests:
7274
expect(name) == "ViewControllerTests"
7375
case .viewStateFactoryTests:
@@ -107,6 +109,8 @@ final class StencilTemplateTests: XCTestCase, TestFactories {
107109
expect(filename) == "ContextTests"
108110
case .flowTests:
109111
expect(filename) == "FlowTests"
112+
case .pluginTests:
113+
expect(filename) == "PluginTests"
110114
case let .viewControllerTests(variation):
111115
expect(filename) == "ViewControllerTests\(variation == .swiftUI ? "-SwiftUI" : "")"
112116
case .viewStateFactoryTests:
@@ -197,6 +201,8 @@ final class StencilTemplateTests: XCTestCase, TestFactories {
197201
expect(imports) == ["Nodes", "<baseImport>", "<reactiveImport>", "<dependencyInjectionImport>"]
198202
case .contextTests, .analyticsTests, .viewStateFactoryTests, .flowTests:
199203
expect(imports) == ["<baseTestImport>"]
204+
case .pluginTests:
205+
expect(imports) == ["NodesTesting", "<baseTestImport>"]
200206
case .viewControllerTests:
201207
expect(imports) == ["<baseTestImport>", "<reactiveImport>"]
202208
}
@@ -224,6 +230,7 @@ extension StencilTemplate {
224230
.analyticsTests,
225231
.contextTests,
226232
.flowTests,
233+
.pluginTests,
227234
.viewControllerTests(.default),
228235
.viewControllerTests(.swiftUI),
229236
.viewStateFactoryTests

Tests/NodesXcodeTemplatesGeneratorTests/Support/TestFactories.swift

+6-2
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,9 @@ extension TestFactories {
181181
pluginName: "<pluginName>",
182182
returnType: "<returnType>",
183183
pluginImports: .mock(with: "pluginImport", count: mockCount),
184-
isPeripheryCommentEnabled: mockCount > 0
184+
pluginTestsImports: .mock(with: "pluginTestsImport", count: mockCount),
185+
isPeripheryCommentEnabled: mockCount > 0,
186+
isNimbleEnabled: mockCount > 0
185187
)
186188
}
187189

@@ -190,7 +192,9 @@ extension TestFactories {
190192
fileHeader: "<fileHeader>",
191193
pluginName: "<pluginName>",
192194
pluginImports: .mock(with: "pluginImport", count: mockCount),
193-
isPeripheryCommentEnabled: mockCount > 0
195+
pluginTestsImports: .mock(with: "pluginTestsImport", count: mockCount),
196+
isPeripheryCommentEnabled: mockCount > 0,
197+
isNimbleEnabled: mockCount > 0
194198
)
195199
}
196200

Tests/NodesXcodeTemplatesGeneratorTests/__Snapshots__/StencilContextsTests/testPluginStencilContext.1.txt

+8-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1-
5 key/value pairs
1+
7 key/value pairs
22
▿ (2 elements)
33
- key: "file_header"
44
- value: "<fileHeader>"
5+
▿ (2 elements)
6+
- key: "is_nimble_enabled"
7+
- value: true
58
▿ (2 elements)
69
- key: "is_periphery_comment_enabled"
710
- value: true
@@ -12,6 +15,10 @@
1215
▿ (2 elements)
1316
- key: "plugin_name"
1417
- value: "<pluginName>"
18+
▿ (2 elements)
19+
- key: "plugin_tests_imports"
20+
▿ value: 1 element
21+
- "<pluginTestsImport>"
1522
▿ (2 elements)
1623
- key: "return_type"
1724
- value: "<returnType>"

Tests/NodesXcodeTemplatesGeneratorTests/__Snapshots__/StencilContextsTests/testPluginStencilContextWithoutReturnType.1.txt

+8-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1-
4 key/value pairs
1+
6 key/value pairs
22
▿ (2 elements)
33
- key: "file_header"
44
- value: "<fileHeader>"
5+
▿ (2 elements)
6+
- key: "is_nimble_enabled"
7+
- value: true
58
▿ (2 elements)
69
- key: "is_periphery_comment_enabled"
710
- value: true
@@ -12,3 +15,7 @@
1215
▿ (2 elements)
1316
- key: "plugin_name"
1417
- value: "<pluginName>"
18+
▿ (2 elements)
19+
- key: "plugin_tests_imports"
20+
▿ value: 1 element
21+
- "<pluginTestsImport>"

0 commit comments

Comments
 (0)