15
15
/// modifying one or more of its properties, and returning the copy. You can
16
16
/// observe recorded issues by returning them unmodified. Or you can suppress an
17
17
/// issue by either filtering it using ``Trait/filterIssues(_:)`` or returning
18
- /// `nil` from the closure passed to ``Trait/transformIssues (_:)``.
18
+ /// `nil` from the closure passed to ``Trait/compactMapIssues (_:)``.
19
19
///
20
20
/// When an instance of this trait is applied to a suite, it is recursively
21
21
/// inherited by all child suites and tests.
22
22
///
23
23
/// To add this trait to a test, use one of the following functions:
24
24
///
25
- /// - ``Trait/transformIssues (_:)``
25
+ /// - ``Trait/compactMapIssues (_:)``
26
26
/// - ``Trait/filterIssues(_:)``
27
27
@_spi ( Experimental)
28
28
public struct IssueHandlingTrait : TestTrait , SuiteTrait {
@@ -96,15 +96,26 @@ extension IssueHandlingTrait: TestScoping {
96
96
return
97
97
}
98
98
99
+ // Ignore system issues, as they are not expected to be caused by users.
100
+ if case . system = issue. kind {
101
+ oldConfiguration. eventHandler ( event, context)
102
+ return
103
+ }
104
+
99
105
// Use the original configuration's event handler when invoking the
100
- // transformer to avoid infinite recursion if the transformer itself
106
+ // handler closure to avoid infinite recursion if the handler itself
101
107
// records new issues. This means only issue handling traits whose scope
102
108
// is outside this one will be allowed to handle such issues.
103
109
let newIssue = Configuration . withCurrent ( oldConfiguration) {
104
110
handleIssue ( issue)
105
111
}
106
112
107
113
if let newIssue {
114
+ // Prohibit assigning the issue's kind to system.
115
+ if case . system = newIssue. kind {
116
+ preconditionFailure ( " Issue returned by issue handling closure cannot have kind 'system': \( newIssue) " )
117
+ }
118
+
108
119
var event = event
109
120
event. kind = . issueRecorded( newIssue)
110
121
oldConfiguration. eventHandler ( event, context)
@@ -120,31 +131,35 @@ extension Trait where Self == IssueHandlingTrait {
120
131
/// Constructs an trait that transforms issues recorded by a test.
121
132
///
122
133
/// - Parameters:
123
- /// - transformer: The closure called for each issue recorded by the test
134
+ /// - transform: A closure called for each issue recorded by the test
124
135
/// this trait is applied to. It is passed a recorded issue, and returns
125
136
/// an optional issue to replace the passed-in one.
126
137
///
127
138
/// - Returns: An instance of ``IssueHandlingTrait`` that transforms issues.
128
139
///
129
- /// The `transformer ` closure is called synchronously each time an issue is
140
+ /// The `transform ` closure is called synchronously each time an issue is
130
141
/// recorded by the test this trait is applied to. The closure is passed the
131
142
/// recorded issue, and if it returns a non-`nil` value, that will be recorded
132
143
/// instead of the original. Otherwise, if the closure returns `nil`, the
133
144
/// issue is suppressed and will not be included in the results.
134
145
///
135
- /// The `transformer ` closure may be called more than once if the test records
146
+ /// The `transform ` closure may be called more than once if the test records
136
147
/// multiple issues. If more than one instance of this trait is applied to a
137
- /// test (including via inheritance from a containing suite), the `transformer `
148
+ /// test (including via inheritance from a containing suite), the `transform `
138
149
/// closure for each instance will be called in right-to-left, innermost-to-
139
150
/// outermost order, unless `nil` is returned, which will skip invoking the
140
151
/// remaining traits' closures.
141
152
///
142
- /// Within `transformer `, you may access the current test or test case (if any)
153
+ /// Within `transform `, you may access the current test or test case (if any)
143
154
/// using ``Test/current`` ``Test/Case/current``, respectively. You may also
144
155
/// record new issues, although they will only be handled by issue handling
145
156
/// traits which precede this trait or were inherited from a containing suite.
146
- public static func transformIssues( _ transformer: @escaping @Sendable ( Issue ) -> Issue ? ) -> Self {
147
- Self ( handler: transformer)
157
+ ///
158
+ /// - Note: `transform` will never be passed an issue for which the value of
159
+ /// ``Issue/kind`` is ``Issue/Kind/system``, and may not return such an
160
+ /// issue.
161
+ public static func compactMapIssues( _ transform: @escaping @Sendable ( Issue ) -> Issue ? ) -> Self {
162
+ Self ( handler: transform)
148
163
}
149
164
150
165
/// Constructs a trait that filters issues recorded by a test.
@@ -174,6 +189,9 @@ extension Trait where Self == IssueHandlingTrait {
174
189
/// using ``Test/current`` ``Test/Case/current``, respectively. You may also
175
190
/// record new issues, although they will only be handled by issue handling
176
191
/// traits which precede this trait or were inherited from a containing suite.
192
+ ///
193
+ /// - Note: `isIncluded` will never be passed an issue for which the value of
194
+ /// ``Issue/kind`` is ``Issue/Kind/system``.
177
195
public static func filterIssues( _ isIncluded: @escaping @Sendable ( Issue ) -> Bool ) -> Self {
178
196
Self { issue in
179
197
isIncluded ( issue) ? issue : nil
0 commit comments