diff --git a/.github/workflows/screenshots.yml b/.github/workflows/screenshots.yml new file mode 100644 index 00000000000..7bea49f1284 --- /dev/null +++ b/.github/workflows/screenshots.yml @@ -0,0 +1,57 @@ +name: Screenshot automation +on: + push: + branches: + - 'screenshots/*' + +jobs: + screenshot-automation: + name: Screenshot automation + runs-on: macos-latest + steps: + - name: Checkout sources + uses: actions/checkout@v2 + + - name: Decrypt AuthKey file + run: cd ./fastlane/envfiles && ./decrypt_secrets.sh + env: + AUTH_KEY_FILE_DECRYPTKEY: ${{ secrets.AUTH_KEY_FILE_DECRYPTKEY }} + + - uses: actions/cache@v2 + id: cache-carthage + with: + path: ~/Carthage + key: ${{ runner.os }}-carthage-${{ hashFiles('Cartfile.resolved') }} + env: + GITHUB_ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Install sentry-cli + run: curl -sL https://sentry.io/get-cli/ | bash + + - name: Install Dependencies + run: gem install bundler:1.17.3 && bundle install + + - name: Prepare xcodeproj + run: sh scripts/setup.sh + env: + GITHUB_ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Run Fastlane snapshot + run: bundle exec fastlane perform_snapshots + env: + GITHUB_ACCESS_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} + FASTLANE_USER: ${{ secrets.FASTLANE_USER }} + FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD: ${{ secrets.FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD }} + MATCH_GIT_BASIC_AUTHORIZATION: ${{ secrets.MATCH_GIT_BASIC_AUTHORIZATION }} + MATCH_GIT_URL: ${{ secrets.MATCH_GIT_URL }} + MATCH_KEYCHAIN_PASSWORD: ${{ secrets.MATCH_KEYCHAIN_PASSWORD }} + MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} + PILOT_APPLE_ID: ${{ secrets.PILOT_APPLE_ID }} + SPACESHIP_CONNECT_API_ISSUER_ID: ${{ secrets.SPACESHIP_CONNECT_API_ISSUER_ID }} + SPACESHIP_CONNECT_API_KEY_ID: ${{ secrets.SPACESHIP_CONNECT_API_KEY_ID }} + SPACESHIP_CONNECT_API_KEY_FILEPATH: envfiles/AuthKey_KDAUTTM76R.p8 + CI_RELEASE: true + - uses: actions/upload-artifact@v2 + with: + name: screenshots + path: fastlane/screenshots/ # or path/to/artifact diff --git a/Snapshots/SnapshotHelper.swift b/Snapshots/SnapshotHelper.swift index aaa2a9a9234..25f8e5e4a21 100644 --- a/Snapshots/SnapshotHelper.swift +++ b/Snapshots/SnapshotHelper.swift @@ -38,22 +38,13 @@ func snapshot(_ name: String, timeWaitingForIdle timeout: TimeInterval = 20) { } enum SnapshotError: Error, CustomDebugStringConvertible { - case cannotDetectUser - case cannotFindHomeDirectory case cannotFindSimulatorHomeDirectory - case cannotAccessSimulatorHomeDirectory(String) case cannotRunOnPhysicalDevice var debugDescription: String { switch self { - case .cannotDetectUser: - return "Couldn't find Snapshot configuration files - can't detect current user " - case .cannotFindHomeDirectory: - return "Couldn't find Snapshot configuration files - can't detect `Users` dir" case .cannotFindSimulatorHomeDirectory: return "Couldn't find simulator home location. Please, check SIMULATOR_HOST_HOME env variable." - case .cannotAccessSimulatorHomeDirectory(let simulatorHostHome): - return "Can't prepare environment. Simulator home location is inaccessible. Does \(simulatorHostHome) exist?" case .cannotRunOnPhysicalDevice: return "Can't use Snapshot on a physical device." } @@ -75,7 +66,7 @@ open class Snapshot: NSObject { Snapshot.waitForAnimations = waitForAnimations do { - let cacheDir = try pathPrefix() + let cacheDir = try getCacheDirectory() Snapshot.cacheDirectory = cacheDir setLanguage(app) setLocale(app) @@ -174,6 +165,12 @@ open class Snapshot: NSObject { } let screenshot = XCUIScreen.main.screenshot() + #if os(iOS) + let image = XCUIDevice.shared.orientation.isLandscape ? fixLandscapeOrientation(image: screenshot.image) : screenshot.image + #else + let image = screenshot.image + #endif + guard var simulator = ProcessInfo().environment["SIMULATOR_DEVICE_NAME"], let screenshotsDir = screenshotsDirectory else { return } do { @@ -183,7 +180,11 @@ open class Snapshot: NSObject { simulator = regex.stringByReplacingMatches(in: simulator, range: range, withTemplate: "") let path = screenshotsDir.appendingPathComponent("\(simulator)-\(name).png") - try screenshot.pngRepresentation.write(to: path) + #if swift(<5.0) + UIImagePNGRepresentation(image)?.write(to: path, options: .atomic) + #else + try image.pngData()?.write(to: path, options: .atomic) + #endif } catch let error { NSLog("Problem writing screenshot: \(name) to \(screenshotsDir)/\(simulator)-\(name).png") NSLog(error.localizedDescription) @@ -191,6 +192,19 @@ open class Snapshot: NSObject { #endif } + class func fixLandscapeOrientation(image: UIImage) -> UIImage { + if #available(iOS 10.0, *) { + let format = UIGraphicsImageRendererFormat() + format.scale = image.scale + let renderer = UIGraphicsImageRenderer(size: image.size, format: format) + return renderer.image { context in + image.draw(in: CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height)) + } + } else { + return image + } + } + class func waitForLoadingIndicatorToDisappear(within timeout: TimeInterval) { #if os(tvOS) return @@ -206,40 +220,28 @@ open class Snapshot: NSObject { _ = XCTWaiter.wait(for: [networkLoadingIndicatorDisappeared], timeout: timeout) } - class func pathPrefix() throws -> URL? { - let homeDir: URL + class func getCacheDirectory() throws -> URL { + let cachePath = "Library/Caches/tools.fastlane" // on OSX config is stored in /Users//Library // and on iOS/tvOS/WatchOS it's in simulator's home dir #if os(OSX) - guard let user = ProcessInfo().environment["USER"] else { - throw SnapshotError.cannotDetectUser - } - - guard let usersDir = FileManager.default.urls(for: .userDirectory, in: .localDomainMask).first else { - throw SnapshotError.cannotFindHomeDirectory + let homeDir = URL(fileURLWithPath: NSHomeDirectory()) + return homeDir.appendingPathComponent(cachePath) + #elseif arch(i386) || arch(x86_64) || arch(arm64) + guard let simulatorHostHome = ProcessInfo().environment["SIMULATOR_HOST_HOME"] else { + throw SnapshotError.cannotFindSimulatorHomeDirectory } - - homeDir = usersDir.appendingPathComponent(user) + let homeDir = URL(fileURLWithPath: simulatorHostHome) + return homeDir.appendingPathComponent(cachePath) #else - #if arch(i386) || arch(x86_64) - guard let simulatorHostHome = ProcessInfo().environment["SIMULATOR_HOST_HOME"] else { - throw SnapshotError.cannotFindSimulatorHomeDirectory - } - guard let homeDirUrl = URL(string: simulatorHostHome) else { - throw SnapshotError.cannotAccessSimulatorHomeDirectory(simulatorHostHome) - } - homeDir = URL(fileURLWithPath: homeDirUrl.path) - #else - throw SnapshotError.cannotRunOnPhysicalDevice - #endif + throw SnapshotError.cannotRunOnPhysicalDevice #endif - return homeDir.appendingPathComponent("Library/Caches/tools.fastlane") } } private extension XCUIElementAttributes { var isNetworkLoadingIndicator: Bool { - if hasWhiteListedIdentifier { return false } + if hasAllowListedIdentifier { return false } let hasOldLoadingIndicatorSize = frame.size == CGSize(width: 10, height: 20) let hasNewLoadingIndicatorSize = frame.size.width.isBetween(46, and: 47) && frame.size.height.isBetween(2, and: 3) @@ -247,10 +249,10 @@ private extension XCUIElementAttributes { return hasOldLoadingIndicatorSize || hasNewLoadingIndicatorSize } - var hasWhiteListedIdentifier: Bool { - let whiteListedIdentifiers = ["GeofenceLocationTrackingOn", "StandardLocationTrackingOn"] + var hasAllowListedIdentifier: Bool { + let allowListedIdentifiers = ["GeofenceLocationTrackingOn", "StandardLocationTrackingOn"] - return whiteListedIdentifiers.contains(identifier) + return allowListedIdentifiers.contains(identifier) } func isStatusBar(_ deviceWidth: CGFloat) -> Bool { @@ -300,4 +302,4 @@ private extension CGFloat { // Please don't remove the lines below // They are used to detect outdated configuration files -// SnapshotHelperVersion [1.21] +// SnapshotHelperVersion [1.24] diff --git a/Tests/Common/DataManagerMock.swift b/Tests/Common/DataManagerMock.swift index 34f5622ed62..f2e5041f53c 100644 --- a/Tests/Common/DataManagerMock.swift +++ b/Tests/Common/DataManagerMock.swift @@ -12,6 +12,7 @@ import RealmSwift import UIKit class DataManagerMock: DataManagerProtocol { + // Search var query: String? var page: Int? @@ -123,6 +124,10 @@ class DataManagerMock: DataManagerProtocol { func allergen(forTag: Tag) -> Allergen? { return nil } + + func label(forTag: String) -> Label? { + return nil + } func additive(forTag: Tag) -> Additive? { return nil diff --git a/Tests/Models/PersistenceManagerMock.swift b/Tests/Models/PersistenceManagerMock.swift index 80244d94cbb..d44e2d9a3c7 100644 --- a/Tests/Models/PersistenceManagerMock.swift +++ b/Tests/Models/PersistenceManagerMock.swift @@ -10,6 +10,8 @@ import RealmSwift class PersistenceManagerMock: PersistenceManagerProtocol { + var labelsIsEmpty: Bool = false + // =======------------------======= // // TODO: implement code below if needed (for now only add the function/propety signatures, so it builds) // =======------------------======= // diff --git a/disabletravis.txt b/disabletravis.txt deleted file mode 100644 index 388c1d0d266..00000000000 --- a/disabletravis.txt +++ /dev/null @@ -1,32 +0,0 @@ -language: swift -osx_image: xcode11 -before_install: -- openssl aes-256-cbc -K $encrypted_593143e92a35_key -iv $encrypted_593143e92a35_iv - -in fastlane/envfiles/AuthKey_KDAUTTM76R.p8.enc -out fastlane/envfiles/AuthKey_KDAUTTM76R.p8 -d -- FILE="/usr/local/bin/mint"; if [[ -d $FILE ]]; then rm -rf "$FILE"; fi -- sh scripts/setup.sh -- killall Xcode || true -xcode_project: OpenFoodFacts.xcodeproj -xcode_destination: platform=iOS Simulator,OS=13.0,name=iPhone 11 -xcode_scheme: OpenFoodFacts -cache: - bundler: true - directories: - - Carthage - - "/usr/local/lib/mint" - - "/usr/local/bin/mint" -notifications: - slack: openfoodfacts:Pw0UOEvADDxNN90ugITF7PKC -env: - global: - secure: TzLeh5qKxmFNlP/LpwsBPdjmXu7UpyKIe6SQdHDQm/bQ9+fSu89Lp8Db9dTPyWXEgKcC3i5X0TeaRcEzvYBk3eZdevd3Axx6dA+xM31FRtGVmZdJ62tUZbQsLNHJo5lAe+K6gQBfiJd983s2goEwrNHNnRaGrmv7xSPPJW4DCeCFW9S/jC0cRCcSZwdrmR986DjnIr7aTiWaSd+XMms60rmBCb7jZbCxYAOPU64uOqRdc0Og2mi8q1XHZzWi7b2OkAdpOwrWzcd4K2XTxfbEIbfhOkAg9bZ2h3+z7VMpWcUYwV7aIOo4ra2u/QkzNK6jZ4Q3h3TLK0e4ilj6vNCWsCqYScDU/BzgZCfhenWcD75Zz5CO0rdAlyQ3gMaxvIsntEyiCpUknYi+i1lMfH/mFwnb323qYdIXJ/BEBLnycqZqZksl43DUoKjmxMElNKKJ8g+TKp+M7FXKBKCd/zPejycLsq4/Z50OKPHPa+q7SLoo1Iryir5IRlD9uZ1EWQq2II2ACUZRuf0gA6GUm7aZEJNWk8QrunI0G75TlKmu9l7gsie5NVMcqZeETfU3vIxuFKJtbV/k2Viw/sQ6h2pr4hUf/VRrfzZCAljTs7ZgKP1sweMRGgU/U2T/Kw2/wB7no8eZ9KdrEcxe1xid0yKyTIWBkeP+7Yvjcu2y2GtYao0= -jobs: - include: - - stage: Deploy - name: Deploy to TestFlight - install: - - brew install getsentry/tools/sentry-cli - - bundle install - script: - - 'if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then travis_wait 50 bundle exec fastlane beta; fi' - if: branch =~ /^release\/.*$/ diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 07433be58ce..79dcefea7f1 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -150,3 +150,9 @@ desc "Upload metadata" lane :metadata do deliver(skip_binary_upload: true) end + +lane :perform_snapshots do + carthage(command: "bootstrap", platform: "iOS", cache_builds: true) + + snapshot +end \ No newline at end of file diff --git a/fastlane/Snapfile b/fastlane/Snapfile index dbaa6e3fceb..66c590f9418 100644 --- a/fastlane/Snapfile +++ b/fastlane/Snapfile @@ -9,13 +9,15 @@ devices([ # "iPhone Xs Max", # "iPad Pro (12.9-inch) (2nd generation)", -"iPad Pro (12.9-inch) (3rd generation)" +"iPad Pro (12.9-inch) (4th generation)" #"iPad Pro (12.9-inch)", # "iPad Pro (9.7-inch)", # "Apple TV 1080p" ]) + + languages([ "en-US", "fr-FR" @@ -171,7 +173,10 @@ scheme("OpenFoodFactsSnapshots") output_directory("./fastlane/screenshots") # remove the '#' to clear all previously generated screenshots before creating new ones -# clear_previous_screenshots(true) +clear_previous_screenshots(true) + +override_status_bar(true) +localize_simulator(true) # Arguments to pass to the app on launch. See https://docs.fastlane.tools/actions/snapshot/#launch-arguments launch_arguments(["debug"]) diff --git a/project.yml b/project.yml index 02e8cb6803f..8f1ac45ae25 100644 --- a/project.yml +++ b/project.yml @@ -1,6 +1,6 @@ name: OpenFoodFacts -fileGroups: [Cartfile, CONTRIBUTING.md, crowdin.yml, fastlane, ISSUE_TEMPLATE.md, LICENSE, project.yml, PULL_REQUEST_TEMPLATE.md, README.md, Snapshots, scripts, .swiftlint.yml, .travis.yml, .gitignore] +fileGroups: [Cartfile, CONTRIBUTING.md, crowdin.yml, fastlane, ISSUE_TEMPLATE.md, LICENSE, project.yml, PULL_REQUEST_TEMPLATE.md, README.md, Snapshots, scripts, .swiftlint.yml, .gitignore] options: minimumXcodeGenVersion: 2.14.0