From ea601804f508442c60ec0f9eebfa747802cfeabd Mon Sep 17 00:00:00 2001 From: Nick Entin Date: Mon, 12 Jul 2021 01:40:53 -0700 Subject: [PATCH] Add highlights summary to bug report attachment --- Aardvark.xcodeproj/project.pbxproj | 2 - AardvarkMailUI.podspec | 1 - .../BugReporting/ARKBugReportAttachment.swift | 10 ++- .../LogStoreAttachmentGenerator.swift | 36 +++++++-- Sources/AardvarkMailUI/ARKEmailBugReporter.h | 4 +- Sources/AardvarkMailUI/ARKEmailBugReporter.m | 76 ++++++++----------- .../ARKEmailBugReporter_Testing.h | 26 ------- .../ARKEmailBugReporterTests.m | 71 ----------------- .../LogStoreAttachmentGeneratorTests.swift | 74 ++++++++++++++++++ 9 files changed, 146 insertions(+), 154 deletions(-) delete mode 100644 Sources/AardvarkMailUI/ARKEmailBugReporter_Testing.h diff --git a/Aardvark.xcodeproj/project.pbxproj b/Aardvark.xcodeproj/project.pbxproj index 3a340ffe..69218f04 100644 --- a/Aardvark.xcodeproj/project.pbxproj +++ b/Aardvark.xcodeproj/project.pbxproj @@ -227,7 +227,6 @@ EA98B9031D4BEAFC00B3A390 /* ARKScreenshotViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ARKScreenshotViewController.m; sourceTree = ""; }; EA98B9311D4BEB6E00B3A390 /* ARKDefaultLogFormatter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ARKDefaultLogFormatter.h; sourceTree = ""; }; EA98B9321D4BEB6E00B3A390 /* ARKDefaultLogFormatter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ARKDefaultLogFormatter.m; sourceTree = ""; }; - EA98B9331D4BEB6E00B3A390 /* ARKEmailBugReporter_Testing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ARKEmailBugReporter_Testing.h; sourceTree = ""; }; EA98B9341D4BEB6E00B3A390 /* ARKEmailBugReporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ARKEmailBugReporter.h; sourceTree = ""; }; EA98B9351D4BEB6E00B3A390 /* ARKEmailBugReporter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ARKEmailBugReporter.m; sourceTree = ""; }; EA98B9361D4BEB6E00B3A390 /* ARKLogFormatter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ARKLogFormatter.h; sourceTree = ""; }; @@ -381,7 +380,6 @@ 3D90DEB720AA9B19006D4924 /* ARKEmailBugReportConfiguration_Protected.h */, 3D6E2D0C20868335007B8013 /* ARKEmailBugReportConfiguration.m */, EA98B9341D4BEB6E00B3A390 /* ARKEmailBugReporter.h */, - EA98B9331D4BEB6E00B3A390 /* ARKEmailBugReporter_Testing.h */, EA98B9351D4BEB6E00B3A390 /* ARKEmailBugReporter.m */, 3DA5BF392556602000B6D148 /* AardvarkMailUI.h */, 3DA5BF3A2556602000B6D148 /* Info.plist */, diff --git a/AardvarkMailUI.podspec b/AardvarkMailUI.podspec index 83a0c9b1..dc2f1b04 100644 --- a/AardvarkMailUI.podspec +++ b/AardvarkMailUI.podspec @@ -11,7 +11,6 @@ Pod::Spec.new do |s| s.ios.deployment_target = '14.0' s.source_files = 'Sources/AardvarkMailUI/**/*.{h,m,swift}' - s.private_header_files = 'Sources/AardvarkMailUI/**/*_Testing.h', 'Sources/AardvarkMailUI/PrivateCategories/*.h' s.dependency 'Aardvark', '~> 5.0.0' end diff --git a/Sources/Aardvark/BugReporting/ARKBugReportAttachment.swift b/Sources/Aardvark/BugReporting/ARKBugReportAttachment.swift index 099e61e7..3cea67ae 100644 --- a/Sources/Aardvark/BugReporting/ARKBugReportAttachment.swift +++ b/Sources/Aardvark/BugReporting/ARKBugReportAttachment.swift @@ -20,10 +20,16 @@ public final class ARKBugReportAttachment: NSObject { // MARK: - Life Cycle - @objc public init(fileName: String, data: Data, dataMIMEType: String) { + @objc public init( + fileName: String, + data: Data, + dataMIMEType: String, + highlightsSummary: String? = nil + ) { self.fileName = fileName self.data = data self.dataMIMEType = dataMIMEType + self.highlightsSummary = highlightsSummary } // MARK: - Public Properties @@ -43,4 +49,6 @@ public final class ARKBugReportAttachment: NSObject { /// MIME types are as specified by the IANA: . @objc public let dataMIMEType: String + @objc public let highlightsSummary: String? + } diff --git a/Sources/Aardvark/BugReporting/LogStoreAttachmentGenerator.swift b/Sources/Aardvark/BugReporting/LogStoreAttachmentGenerator.swift index fe9140ce..0de6c823 100644 --- a/Sources/Aardvark/BugReporting/LogStoreAttachmentGenerator.swift +++ b/Sources/Aardvark/BugReporting/LogStoreAttachmentGenerator.swift @@ -43,12 +43,14 @@ public final class LogStoreAttachmentGenerator: NSObject { /// - parameter messageFormatter: The formatter used to format messages in the logs attachment. /// - parameter includeLatestScreenshot: Whether an attachment should be generated for the last screenshot in the /// log store, if one exists. + /// - parameter numberOfErrorsInHighlights: The number of errors to include in the highlights for the log store. /// - parameter completionQueue: The queue on which the completion should be called. /// - parameter completion: The completion to be called once the attachments have been generated. public static func attachments( for logStore: ARKLogStore, messageFormatter: ARKLogFormatter = ARKDefaultLogFormatter(), includeLatestScreenshot: Bool, + numberOfErrorsInHighlights: UInt = 3, completionQueue: DispatchQueue, completion: @escaping (Attachments) -> Void ) { @@ -63,7 +65,8 @@ public final class LogStoreAttachmentGenerator: NSObject { let logsAttachment = attachment( for: logMessages, using: messageFormatter, - logStoreName: logStore.name + logStoreName: logStore.name, + numberOfErrorsInHighlights: numberOfErrorsInHighlights ) completionQueue.async { @@ -107,11 +110,13 @@ public final class LogStoreAttachmentGenerator: NSObject { /// - parameter logMessages: The log messages to be included in the attachment. /// - parameter logFormatter: The formatter with which to format the log messages. /// - parameter logStoreName: The name of the log store from which the logs were collected. - @objc(attachmentForLogMessages:usingLogFormatter:logStoreName:) + /// - parameter numberOfErrorsInHighlights: The number of errors to include in the highlights for the log store. + @objc(attachmentForLogMessages:usingLogFormatter:logStoreName:numberOfErrorsInHighlights:) public static func attachment( for logMessages: [ARKLogMessage], using logFormatter: ARKLogFormatter = ARKDefaultLogFormatter(), - logStoreName: String? + logStoreName: String?, + numberOfErrorsInHighlights: UInt = 3 ) -> ARKBugReportAttachment? { guard !logMessages.isEmpty else { return nil @@ -124,10 +129,19 @@ public final class LogStoreAttachmentGenerator: NSObject { let fileName = logsFileName(for: logStoreName, fileType: "txt") + let recentErrorSummary = logMessages + .lazy + .reversed() + .filter { $0.type == .error } + .prefix(Int(numberOfErrorsInHighlights)) + .map { $0.text } + .joined(separator: "\n") + return ARKBugReportAttachment( fileName: fileName, data: formattedLogData, - dataMIMEType: "text/plain" + dataMIMEType: "text/plain", + highlightsSummary: recentErrorSummary.isEmpty ? nil : recentErrorSummary ) } @@ -138,11 +152,12 @@ public final class LogStoreAttachmentGenerator: NSObject { /// - parameter logFormatter: The formatter with which to format the log messages. /// - parameter logStoreName: The name of the log store from which the logs were collected. /// - parameter completion: A completion handler that retuns void, and is passed an optional attachment. - @objc(attachmentForLogMessages:usingLogFormatter:logStoreName:completion:) + @objc(attachmentForLogMessages:usingLogFormatter:logStoreName:numberOfErrorsInHighlights:completion:) public static func attachment( for logMessages: [ARKLogMessage], using logFormatter: ARKLogFormatter = ARKDefaultLogFormatter(), logStoreName: String?, + numberOfErrorsInHighlights: UInt = 3, completion: @escaping @convention(block)(ARKBugReportAttachment?) -> Void ) -> Void { guard !logMessages.isEmpty else { @@ -160,10 +175,19 @@ public final class LogStoreAttachmentGenerator: NSObject { let fileName = logsFileName(for: logStoreName, fileType: "txt") + let recentErrorSummary = logMessages + .lazy + .reversed() + .filter { $0.type == .error } + .prefix(Int(numberOfErrorsInHighlights)) + .map { $0.text } + .joined(separator: "\n") + let attachment = ARKBugReportAttachment( fileName: fileName, data: formattedLogData, - dataMIMEType: "text/plain" + dataMIMEType: "text/plain", + highlightsSummary: recentErrorSummary.isEmpty ? nil : recentErrorSummary ) DispatchQueue.main.async { diff --git a/Sources/AardvarkMailUI/ARKEmailBugReporter.h b/Sources/AardvarkMailUI/ARKEmailBugReporter.h index ee2bce2d..056e84ec 100644 --- a/Sources/AardvarkMailUI/ARKEmailBugReporter.h +++ b/Sources/AardvarkMailUI/ARKEmailBugReporter.h @@ -103,9 +103,9 @@ typedef void (^ARKEmailBugReporterCustomPromptCompletionBlock)(ARKEmailBugReport @property (nonatomic) BOOL attachesViewHierarchyDescription; /// Returns an attachment containing the log messages. Defaults to a plain text attachment containing each log message formatted using the bug reporter's `logFormatter`. -- (nullable ARKBugReportAttachment *)attachmentForLogMessages:(nonnull NSArray *)logMessages inLogStoreNamed:(nonnull NSString *)logStoreName __attribute__((deprecated("Use the async version of this method that takes a completion handler: attachmentForLogMessages:inLogStoreNamed:completion: instead."))); +- (nullable ARKBugReportAttachment *)attachmentForLogMessages:(nonnull NSArray *)logMessages inLogStoreNamed:(nonnull NSString *)logStoreName numberOfErrorsInHighlights:(NSUInteger)numberOfErrorsInHighlights __attribute__((deprecated("Use the async version of this method that takes a completion handler: attachmentForLogMessages:inLogStoreNamed:completion: instead."))); /// Returns an attachment containing the log messages to a completion handler. Defaults to a plain text attachment containing each log message formatted using the bug reporter's `logFormatter`. -- (void) attachmentForLogMessages:(nonnull NSArray *)logMessages inLogStoreNamed:(nonnull NSString *)logStoreName completion: (ARKAttachmentGeneratorCompletionBlock _Nonnull) completionHandler; +- (void) attachmentForLogMessages:(nonnull NSArray *)logMessages inLogStoreNamed:(nonnull NSString *)logStoreName numberOfErrorsInHighlights:(NSUInteger)numberOfErrorsInHighlights completion: (ARKAttachmentGeneratorCompletionBlock _Nonnull) completionHandler; @end diff --git a/Sources/AardvarkMailUI/ARKEmailBugReporter.m b/Sources/AardvarkMailUI/ARKEmailBugReporter.m index b52dd7ed..428c4a2f 100644 --- a/Sources/AardvarkMailUI/ARKEmailBugReporter.m +++ b/Sources/AardvarkMailUI/ARKEmailBugReporter.m @@ -19,7 +19,6 @@ @import MessageUI; #import "ARKEmailBugReporter.h" -#import "ARKEmailBugReporter_Testing.h" #import "ARKEmailBugReportConfiguration.h" #import "ARKEmailBugReportConfiguration_Protected.h" @@ -171,17 +170,19 @@ - (NSArray *)logStores; #pragma mark - Public Methods -- (ARKBugReportAttachment *)attachmentForLogMessages:(NSArray *)logMessages inLogStoreNamed:(NSString *)logStoreName; +- (ARKBugReportAttachment *)attachmentForLogMessages:(NSArray *)logMessages inLogStoreNamed:(NSString *)logStoreName numberOfErrorsInHighlights:(NSUInteger)numberOfErrorsInHighlights; { return [ARKLogStoreAttachmentGenerator attachmentForLogMessages:logMessages usingLogFormatter:self.logFormatter - logStoreName:logStoreName]; + logStoreName:logStoreName + numberOfErrorsInHighlights:numberOfErrorsInHighlights]; } -- (void)attachmentForLogMessages:(nonnull NSArray *)logMessages inLogStoreNamed:(nonnull NSString *)logStoreName completion:(ARKAttachmentGeneratorCompletionBlock _Nonnull)completionHandler { +- (void)attachmentForLogMessages:(nonnull NSArray *)logMessages inLogStoreNamed:(nonnull NSString *)logStoreName numberOfErrorsInHighlights:(NSUInteger)numberOfErrorsInHighlights completion:(ARKAttachmentGeneratorCompletionBlock _Nonnull)completionHandler { [ARKLogStoreAttachmentGenerator attachmentForLogMessages:logMessages usingLogFormatter:self.logFormatter logStoreName:logStoreName + numberOfErrorsInHighlights:numberOfErrorsInHighlights completion:^(ARKBugReportAttachment *attachment) { dispatch_async(dispatch_get_main_queue(), ^{ completionHandler(attachment); @@ -278,12 +279,17 @@ - (void)_createBugReportWithConfiguration:(ARKEmailBugReportConfiguration *)conf [logStoresToLogMessagesMap setObject:logMessages forKey:logStore]; dispatch_group_enter(logStoreRetrievalDispatchGroup); - [self attachmentForLogMessages:logMessages inLogStoreNamed:[logStore name] completion:^(ARKBugReportAttachment * _Nullable attachment) { - if (attachment != NULL) { - [logStoresToLogMessagesAttachmentMap setObject:attachment forKey:logStore]; - } - dispatch_group_leave(logStoreRetrievalDispatchGroup); - }]; + [self attachmentForLogMessages:logMessages + inLogStoreNamed:[logStore name] + numberOfErrorsInHighlights:[MFMailComposeViewController canSendMail] + ? self.numberOfRecentErrorLogsToIncludeInEmailBodyWhenAttachmentsAreAvailable + : self.numberOfRecentErrorLogsToIncludeInEmailBodyWhenAttachmentsAreUnavailable + completion:^(ARKBugReportAttachment * _Nullable attachment) { + if (attachment != NULL) { + [logStoresToLogMessagesAttachmentMap setObject:attachment forKey:logStore]; + } + dispatch_group_leave(logStoreRetrievalDispatchGroup); + }]; dispatch_group_leave(logStoreRetrievalDispatchGroup); }]; @@ -321,20 +327,15 @@ - (void)_createBugReportWithConfiguration:(ARKEmailBugReportConfiguration *)conf fileName:logsAttachment.fileName]; } - NSMutableString *const emailBodyForLogStore = [NSMutableString new]; - BOOL appendToEmailBody = NO; + if (logsAttachment.highlightsSummary.length) { + NSMutableString *const emailBodyForLogStore = [NSMutableString new]; - if (logStore.name.length) { - [emailBodyForLogStore appendFormat:@"%@:\n", logStore.name]; - } + if (logStore.name.length) { + [emailBodyForLogStore appendFormat:@"%@:\n", logStore.name]; + } - NSString *const recentErrorLogs = [self _recentErrorLogMessagesAsPlainText:logMessages count:self.numberOfRecentErrorLogsToIncludeInEmailBodyWhenAttachmentsAreAvailable]; - if (recentErrorLogs.length) { - [emailBodyForLogStore appendFormat:@"%@\n", recentErrorLogs]; - appendToEmailBody = YES; - } + [emailBodyForLogStore appendFormat:@"%@\n", logsAttachment.highlightsSummary]; - if (appendToEmailBody) { [emailBody appendString:emailBodyForLogStore]; } } @@ -348,6 +349,10 @@ - (void)_createBugReportWithConfiguration:(ARKEmailBugReportConfiguration *)conf for (ARKBugReportAttachment *attachment in configuration.additionalAttachments) { [self.mailComposeViewController addAttachmentData:attachment.data mimeType:attachment.dataMIMEType fileName:attachment.fileName]; + + if (attachment.highlightsSummary.length) { + [emailBody appendFormat:@"\n%@\n", attachment.highlightsSummary]; + } } [self.mailComposeViewController setMessageBody:emailBody isHTML:NO]; @@ -360,8 +365,11 @@ - (void)_createBugReportWithConfiguration:(ARKEmailBugReportConfiguration *)conf NSMutableString *const emailBody = [self _prefilledEmailBodyWithEmailBodyAdditions:emailBodyAdditions]; for (ARKLogStore *logStore in logStores) { - NSArray *const logMessages = [logStoresToLogMessagesMap objectForKey:logStore]; - [emailBody appendFormat:@"%@\n", [self _recentErrorLogMessagesAsPlainText:logMessages count:self.numberOfRecentErrorLogsToIncludeInEmailBodyWhenAttachmentsAreUnavailable]]; + ARKBugReportAttachment *const logsAttachment = [logStoresToLogMessagesAttachmentMap objectForKey:logStore]; + + if (logsAttachment.highlightsSummary.length) { + [emailBody appendFormat:@"%@\n", logsAttachment.highlightsSummary]; + } } NSURL *const composeEmailURL = [self _emailURLWithRecipients:@[self.bugReportRecipientEmailAddress] CC:@"" subject:configuration.prefilledEmailSubject body:emailBody]; @@ -420,28 +428,6 @@ - (NSMutableString *)_prefilledEmailBodyWithEmailBodyAdditions:(nullable NSDicti return prefilledEmailBodyWithEmailBodyAdditions; } -- (NSString *)_recentErrorLogMessagesAsPlainText:(NSArray *)logMessages count:(NSUInteger)errorLogsToInclude; -{ - NSMutableString *recentErrorLogs = [NSMutableString new]; - NSUInteger failuresFound = 0; - for (ARKLogMessage *log in [logMessages reverseObjectEnumerator]) { - if(log.type == ARKLogTypeError) { - [recentErrorLogs appendFormat:@"%@\n", log]; - - if(++failuresFound >= errorLogsToInclude) { - break; - } - } - } - - if (recentErrorLogs.length > 0 ) { - // Remove the final newline and create an immutable string. - return [recentErrorLogs stringByReplacingCharactersInRange:NSMakeRange(recentErrorLogs.length - 1, 1) withString:@""]; - } else { - return @""; - } -} - - (NSURL *)_emailURLWithRecipients:(NSArray *)recipients CC:(NSString *)CCLine subject:(NSString *)subjectLine body:(NSString *)bodyText; { NSString *const defaultPrefix = @"mailto:"; diff --git a/Sources/AardvarkMailUI/ARKEmailBugReporter_Testing.h b/Sources/AardvarkMailUI/ARKEmailBugReporter_Testing.h deleted file mode 100644 index d03dc822..00000000 --- a/Sources/AardvarkMailUI/ARKEmailBugReporter_Testing.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// Copyright 2014 Square, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -//    http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -@import Foundation; - -#import - - -@interface ARKEmailBugReporter () - -- (nonnull NSString *)_recentErrorLogMessagesAsPlainText:(nonnull NSArray *)logMessages count:(NSUInteger)errorLogsToInclude; - -@end diff --git a/Sources/AardvarkMailUITests/ARKEmailBugReporterTests.m b/Sources/AardvarkMailUITests/ARKEmailBugReporterTests.m index 116d7bb1..cb542c8d 100644 --- a/Sources/AardvarkMailUITests/ARKEmailBugReporterTests.m +++ b/Sources/AardvarkMailUITests/ARKEmailBugReporterTests.m @@ -18,7 +18,6 @@ @import XCTest; #import "ARKEmailBugReporter.h" -#import "ARKEmailBugReporter_Testing.h" #import "ARKDataArchive.h" #import "ARKDataArchive_Testing.h" @@ -63,76 +62,6 @@ - (void)setUp; #pragma mark - Behavior Tests -- (void)test_recentErrorLogMessagesAsPlainText_countRespected; -{ - NSMutableArray *numbers = [NSMutableArray new]; - for (int i = 0; i < self.logStore.maximumLogMessageCount; i++) { - [numbers addObject:@(i)]; - } - - // Concurrently add all of the logs. - [numbers enumerateObjectsWithOptions:NSEnumerationConcurrent usingBlock:^(NSNumber *number, NSUInteger idx, BOOL *stop) { - ARKLogWithType(ARKLogTypeError, nil, @"%@", number); - }]; - - NSUInteger const numberOfRecentErrorLogs = 5; - XCTestExpectation *expectation = [self expectationWithDescription:NSStringFromSelector(_cmd)]; - [self.logStore retrieveAllLogMessagesWithCompletionHandler:^(NSArray *logMessages) { - NSString *recentErrorLogs = [self.bugReporter _recentErrorLogMessagesAsPlainText:logMessages count:numberOfRecentErrorLogs]; - XCTAssertEqual([recentErrorLogs componentsSeparatedByString:@"\n"].count, numberOfRecentErrorLogs); - - [expectation fulfill]; - }]; - - [self waitForExpectationsWithTimeout:5.0 handler:nil]; -} - -- (void)test_recentErrorLogMessagesAsPlainText_returnsNilIfNoErrorLogsPresent; -{ - NSUInteger const numberOfRecentErrorLogs = 5; - XCTestExpectation *expectation = [self expectationWithDescription:NSStringFromSelector(_cmd)]; - [self.logStore retrieveAllLogMessagesWithCompletionHandler:^(NSArray *logMessages) { - __block NSString *recentErrorLogs = [self.bugReporter _recentErrorLogMessagesAsPlainText:logMessages count:numberOfRecentErrorLogs]; - - XCTAssertEqualObjects(recentErrorLogs, @""); - - ARKLog(@"This is not an error"); - - [self.logStore retrieveAllLogMessagesWithCompletionHandler:^(NSArray *logMessages) { - recentErrorLogs = [self.bugReporter _recentErrorLogMessagesAsPlainText:logMessages count:numberOfRecentErrorLogs]; - - XCTAssertEqualObjects(recentErrorLogs, @""); - - [expectation fulfill]; - }]; - }]; - - [self waitForExpectationsWithTimeout:5.0 handler:nil]; -} - -- (void)test_recentErrorLogMessagesAsPlainText_returnsNilIfRecentErrorLogsIsZero; -{ - NSUInteger const numberOfRecentErrorLogs = 0; - XCTestExpectation *expectation = [self expectationWithDescription:NSStringFromSelector(_cmd)]; - [self.logStore retrieveAllLogMessagesWithCompletionHandler:^(NSArray *logMessages) { - __block NSString *recentErrorLogs = [self.bugReporter _recentErrorLogMessagesAsPlainText:logMessages count:numberOfRecentErrorLogs]; - - XCTAssertEqualObjects(recentErrorLogs, @""); - - ARKLog(@"This is not an error"); - - [self.logStore retrieveAllLogMessagesWithCompletionHandler:^(NSArray *logMessages) { - recentErrorLogs = [self.bugReporter _recentErrorLogMessagesAsPlainText:logMessages count:numberOfRecentErrorLogs]; - - XCTAssertEqualObjects(recentErrorLogs, @""); - - [expectation fulfill]; - }]; - }]; - - [self waitForExpectationsWithTimeout:5.0 handler:nil]; -} - - (void)test_addLogStores_enforcesARKLogStoreClass; { XCTAssertEqualObjects(self.bugReporter.logStores, @[self.logStore]); diff --git a/Sources/AardvarkTests/LogStoreAttachmentGeneratorTests.swift b/Sources/AardvarkTests/LogStoreAttachmentGeneratorTests.swift index 6b05babf..fe8aedbf 100644 --- a/Sources/AardvarkTests/LogStoreAttachmentGeneratorTests.swift +++ b/Sources/AardvarkTests/LogStoreAttachmentGeneratorTests.swift @@ -68,6 +68,80 @@ final class LogStoreAttachmentGeneratorTests: XCTestCase { ) } + func testLogMessageAttachmentHighlightsUseErrorMessages() { + let logMessages = [ + ARKLogMessage(text: "Message A", image: nil, type: .default, parameters: [:], userInfo: nil), + ARKLogMessage(text: "Message B", image: nil, type: .error, parameters: [:], userInfo: nil), + ARKLogMessage(text: "Message C", image: nil, type: .default, parameters: [:], userInfo: nil), + ARKLogMessage(text: "Message D", image: nil, type: .error, parameters: [:], userInfo: nil), + ] + + let attachment = LogStoreAttachmentGenerator.attachment( + for: logMessages, + using: TestFormatter(), + logStoreName: nil + ) + + XCTAssertEqual( + attachment?.highlightsSummary, + """ + Message D + Message B + """ + ) + } + + func testLogMessageAttachmentHighlightsCountRespected() { + let logMessages = [ + ARKLogMessage(text: "Message A", image: nil, type: .error, parameters: [:], userInfo: nil), + ARKLogMessage(text: "Message B", image: nil, type: .error, parameters: [:], userInfo: nil), + ARKLogMessage(text: "Message C", image: nil, type: .error, parameters: [:], userInfo: nil), + ] + + let attachment = LogStoreAttachmentGenerator.attachment( + for: logMessages, + using: TestFormatter(), + logStoreName: nil, + numberOfErrorsInHighlights: 2 + ) + + XCTAssertEqual( + attachment?.highlightsSummary, + """ + Message C + Message B + """ + ) + } + + func testLogMessageAttachmentHighlightsAreNilIfNoErrorLogsPresent() { + let logMessages = [ + ARKLogMessage(text: "Message A", image: nil, type: .default, parameters: [:], userInfo: nil), + ARKLogMessage(text: "Message B", image: nil, type: .default, parameters: [:], userInfo: nil), + ARKLogMessage(text: "Message C", image: nil, type: .default, parameters: [:], userInfo: nil), + ] + + let attachment = LogStoreAttachmentGenerator.attachment(for: logMessages, logStoreName: nil) + + XCTAssertNil(attachment?.highlightsSummary) + } + + func testLogMessageAttachmentHighlightsAreNilIfCountIsZero() { + let logMessages = [ + ARKLogMessage(text: "Message A", image: nil, type: .error, parameters: [:], userInfo: nil), + ARKLogMessage(text: "Message B", image: nil, type: .error, parameters: [:], userInfo: nil), + ARKLogMessage(text: "Message C", image: nil, type: .error, parameters: [:], userInfo: nil), + ] + + let attachment = LogStoreAttachmentGenerator.attachment( + for: logMessages, + logStoreName: nil, + numberOfErrorsInHighlights: 0 + ) + + XCTAssertNil(attachment?.highlightsSummary) + } + // MARK: - Tests - Screenshot Attachment func testScreenshotAttachmentName() throws {