diff --git a/README.md b/README.md index 47b2458..f1f1f4f 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,8 @@ Options available include: | ```--model``` | Divide by test target model | | ```--os``` | Divide by test target operating system | | ```--test-plan-config``` | Divide by test run configuration | +| ```--language``` | Divide by test language | +| ```--region``` | Divide by test region | | ```--test``` | Divide by test | See ```xcparse screenshots --help``` for a full-listing diff --git a/Sources/xcparse/AttachmentsCommand.swift b/Sources/xcparse/AttachmentsCommand.swift index f0e0579..0028768 100644 --- a/Sources/xcparse/AttachmentsCommand.swift +++ b/Sources/xcparse/AttachmentsCommand.swift @@ -23,6 +23,8 @@ struct AttachmentsCommand: Command { var divideByOS: OptionArgument var divideByTestRun: OptionArgument var divideByTestPlanConfig: OptionArgument + var divideByLanguage: OptionArgument + var divideByRegion: OptionArgument var divideByTest: OptionArgument var utiWhitelist: OptionArgument<[String]> @@ -40,6 +42,8 @@ struct AttachmentsCommand: Command { divideByOS = subparser.add(option: "--os", shortName: nil, kind: Bool.self, usage: "Divide attachments by OS") divideByTestRun = subparser.add(option: "--test-run", shortName: nil, kind: Bool.self, usage: "Deprecated. Use --test-plan-config") divideByTestPlanConfig = subparser.add(option: "--test-plan-config", shortName: nil, kind: Bool.self, usage: "Divide attachments by test plan configuration") + divideByLanguage = subparser.add(option: "--language", shortName: nil, kind: Bool.self, usage: "Divide attachments by test language") + divideByRegion = subparser.add(option: "--region", shortName: nil, kind: Bool.self, usage: "Divide attachments by test region") divideByTest = subparser.add(option: "--test", shortName: nil, kind: Bool.self, usage: "Divide attachments by test") utiWhitelist = subparser.add(option: "--uti", shortName: nil, kind: [String].self, strategy: .upToNextOption, @@ -79,6 +83,8 @@ struct AttachmentsCommand: Command { divideByTargetModel: arguments.get(self.divideByModel) ?? false, divideByTargetOS: arguments.get(self.divideByOS) ?? false, divideByTestPlanConfig: arguments.get(self.divideByTestPlanConfig) ?? (arguments.get(self.divideByTestRun) ?? false), + divideByLanguage: arguments.get(self.divideByLanguage) ?? false, + divideByRegion: arguments.get(self.divideByRegion) ?? false, divideByTest: arguments.get(self.divideByTest) ?? false) if let allowedUTIsToExport = arguments.get(self.utiWhitelist) { options.attachmentFilter = { diff --git a/Sources/xcparse/ScreenshotsCommand.swift b/Sources/xcparse/ScreenshotsCommand.swift index c81ea50..16d038e 100644 --- a/Sources/xcparse/ScreenshotsCommand.swift +++ b/Sources/xcparse/ScreenshotsCommand.swift @@ -24,6 +24,8 @@ struct ScreenshotsCommand: Command { var divideByOS: OptionArgument var divideByTestRun: OptionArgument var divideByTestPlanConfig: OptionArgument + var divideByLanguage: OptionArgument + var divideByRegion: OptionArgument var divideByTest: OptionArgument var testStatusWhitelist: OptionArgument<[String]> @@ -42,6 +44,8 @@ struct ScreenshotsCommand: Command { divideByOS = subparser.add(option: "--os", shortName: nil, kind: Bool.self, usage: "Divide screenshots by OS") divideByTestRun = subparser.add(option: "--test-run", shortName: nil, kind: Bool.self, usage: "Deprecated. Use --test-plan-config") divideByTestPlanConfig = subparser.add(option: "--test-plan-config", shortName: nil, kind: Bool.self, usage: "Divide attachments by test plan configuration") + divideByLanguage = subparser.add(option: "--language", shortName: nil, kind: Bool.self, usage: "Divide attachments by test language") + divideByRegion = subparser.add(option: "--region", shortName: nil, kind: Bool.self, usage: "Divide attachments by test region") divideByTest = subparser.add(option: "--test", shortName: nil, kind: Bool.self, usage: "Divide screenshots by test") testStatusWhitelist = subparser.add(option: "--test-status", shortName: nil, kind: [String].self, strategy: .upToNextOption, @@ -81,6 +85,8 @@ struct ScreenshotsCommand: Command { divideByTargetModel: arguments.get(self.divideByModel) ?? false, divideByTargetOS: arguments.get(self.divideByOS) ?? false, divideByTestPlanConfig: arguments.get(self.divideByTestPlanConfig) ?? (arguments.get(self.divideByTestRun) ?? false), + divideByLanguage: arguments.get(self.divideByLanguage) ?? false, + divideByRegion: arguments.get(self.divideByRegion) ?? false, divideByTest: arguments.get(self.divideByTest) ?? false, attachmentFilter: { return UTTypeConformsTo($0.uniformTypeIdentifier as CFString, "public.image" as CFString) diff --git a/Sources/xcparse/XCPParser.swift b/Sources/xcparse/XCPParser.swift index 48e1807..9e78ea3 100644 --- a/Sources/xcparse/XCPParser.swift +++ b/Sources/xcparse/XCPParser.swift @@ -72,6 +72,8 @@ struct AttachmentExportOptions { var divideByTargetModel: Bool = false var divideByTargetOS: Bool = false var divideByTestPlanConfig: Bool = false + var divideByLanguage: Bool = false + var divideByRegion: Bool = false var divideByTest: Bool = false var xcresulttoolCompatability = XCResultToolCompatability() @@ -141,6 +143,31 @@ struct AttachmentExportOptions { } } + func screenshotDirectoryURL(_ testableSummary: ActionTestableSummary, forBaseURL baseURL: Foundation.URL) -> Foundation.URL { + var languageRegionDirectoryName: String? = nil + + let testLanguage = testableSummary.testLanguage ?? "System Language" + let testRegion = testableSummary.testRegion ?? "System Region" + if self.divideByLanguage == true, self.divideByRegion == true { + languageRegionDirectoryName = "\(testLanguage) (\(testRegion))" + } else if self.divideByLanguage == true { + languageRegionDirectoryName = testLanguage + } else if self.divideByRegion == true { + languageRegionDirectoryName = testRegion + } + + if let folderName = languageRegionDirectoryName { + if self.xcresulttoolCompatability.supportsUnicodeExportPaths != true { + let asciiFolderName = folderName.lossyASCIIString() ?? folderName + return baseURL.appendingPathComponent(asciiFolderName, isDirectory: true) + } else { + return baseURL.appendingPathComponent(folderName, isDirectory: true) + } + } else { + return baseURL + } + } + func screenshotDirectoryURL(_ testSummary: ActionTestSummary, forBaseURL baseURL: Foundation.URL) -> Foundation.URL { guard let summaryIdentifier = testSummary.identifier else { return baseURL @@ -242,25 +269,33 @@ class XCPParser { } let testableSummaries = testPlanRun.testableSummaries - let testableSummariesToTestActivity = testableSummaries.flatMap { $0.flattenedTestSummaryMap(withXCResult: xcresult) } - for (testableSummary, childActivitySummaries) in testableSummariesToTestActivity { - if options.testSummaryFilter(testableSummary) == false { + for testableSummary in testableSummaries { + let testableSummaryScreenshotDirectoryURL = options.screenshotDirectoryURL(testableSummary, forBaseURL: testPlanRunScreenshotURL) + if testableSummaryScreenshotDirectoryURL.createDirectoryIfNecessary() != true { continue } - let filteredChildActivities = childActivitySummaries.filter(options.activitySummaryFilter) - let filteredAttachments = filteredChildActivities.flatMap { $0.attachments.filter(options.attachmentFilter) } - - let testableSummaryScreenshotURL = options.screenshotDirectoryURL(testableSummary, forBaseURL: testPlanRunScreenshotURL) - if testableSummaryScreenshotURL.createDirectoryIfNecessary(createIntermediates: true) != true { - continue + let testableSummariesToTestActivity = testableSummary.flattenedTestSummaryMap(withXCResult: xcresult) + for (testSummary, childActivitySummaries) in testableSummariesToTestActivity { + if options.testSummaryFilter(testSummary) == false { + continue + } + + let filteredChildActivities = childActivitySummaries.filter(options.activitySummaryFilter) + let filteredAttachments = filteredChildActivities.flatMap { $0.attachments.filter(options.attachmentFilter) } + + let testSummaryScreenshotURL = options.screenshotDirectoryURL(testSummary, forBaseURL: testableSummaryScreenshotDirectoryURL) + if testSummaryScreenshotURL.createDirectoryIfNecessary(createIntermediates: true) != true { + continue + } + + // Now that we know what we want to export, save it to the dictionary so we can have all the exports + // done at once with one progress bar per URL + var existingAttachmentsForURL = exportURLsToAttachments[testSummaryScreenshotURL.path] ?? [] + existingAttachmentsForURL.append(contentsOf: filteredAttachments) + exportURLsToAttachments[testSummaryScreenshotURL.path] = existingAttachmentsForURL } - // Now that we know what we want to export, save it to the dictionary so we can have all the exports - // done at once with one progress bar per URL - var existingAttachmentsForURL = exportURLsToAttachments[testableSummaryScreenshotURL.path] ?? [] - existingAttachmentsForURL.append(contentsOf: filteredAttachments) - exportURLsToAttachments[testableSummaryScreenshotURL.path] = existingAttachmentsForURL } } }