diff --git a/.gitignore b/.gitignore index 9f332f5..82c3e53 100644 --- a/.gitignore +++ b/.gitignore @@ -62,7 +62,7 @@ Carthage/Build # For more information about the recommended setup visit: # https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md -fastlane +fastlane/README.md fastlane/report.xml fastlane/Preview.html fastlane/screenshots diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..e115d04 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,9 @@ +language: objective-c +osx_image: xcode8.3 +branches: + only: + - develop +before_install: + - echo -e "machine github.com\n login $GITHUB_ACCESS_TOKEN" >> ~/.netrc +script: + - ./fastlane/travis.sh diff --git a/Cartfile b/Cartfile index bd33c11..7abfe60 100644 --- a/Cartfile +++ b/Cartfile @@ -1,6 +1,6 @@ github "SVProgressHUD/SVProgressHUD" github "radex/SwiftyUserDefaults" -github "libgit2/objective-git" "master" +github "libgit2/objective-git" github "zahlz/SwiftPasscodeLock" "master" github "bitserf/FavIcon" github "kishikawakatsumi/KeychainAccess" "master" diff --git a/README.md b/README.md index b2a7a00..ae866e3 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ [![GitHub release](https://img.shields.io/github/release/mssun/pass-ios.svg)](https://github.com/mssun/pass-ios/releases) ![Swift 3.1](https://img.shields.io/badge/Swift-3.1-orange.svg) [![Gitter](https://img.shields.io/gitter/room/nwjs/nw.js.svg)](https://gitter.im/passforios/passforios) +[![Build Status](https://travis-ci.org/mssun/passforios.svg?branch=develop)](https://travis-ci.org/mssun/passforios) Pass is an iOS client compatible with [ZX2C4's Pass command line application](http://www.passwordstore.org/). It is a password manager using diff --git a/fastlane/Appfile b/fastlane/Appfile new file mode 100644 index 0000000..8a3ad8c --- /dev/null +++ b/fastlane/Appfile @@ -0,0 +1,4 @@ +app_identifier ENV["APP_IDENTIFIER"] +apple_id ENV["APPLE_ID"] +team_id ENV["TEAM_ID"] +itc_team_id ENV["ITC_TEAM_ID"] diff --git a/fastlane/Fastfile b/fastlane/Fastfile new file mode 100644 index 0000000..ca14983 --- /dev/null +++ b/fastlane/Fastfile @@ -0,0 +1,101 @@ +# Customise this file, documentation can be found here: +# https://github.com/fastlane/fastlane/tree/master/fastlane/docs +# All available actions: https://docs.fastlane.tools/actions +# can also be listed using the `fastlane actions` command + +# Change the syntax highlighting to Ruby +# All lines starting with a # are ignored when running `fastlane` + +# If you want to automatically update fastlane if a new version is available: +# update_fastlane + +# This is the minimum version number required. +# Update this, if you use features of a newer version +fastlane_version "2.17.0" + +default_platform :ios + +platform :ios do + before_all do + cocoapods + carthage(platform: "iOS") + end + + desc "Travis" + lane :travis do + test + beta + end + + desc "Runs all the tests" + lane :test do + scan( + scheme: "pass", + device: "iPhone 7" + ) + end + + desc "Submit a new Beta Build to Apple TestFlight" + desc "This will also make sure the profile is up to date" + lane :beta do + create_keychain( + name: ENV["MATCH_KEYCHAIN_NAME"], + password: ENV["MATCH_KEYCHAIN_PASSWORD"], + default_keychain: true, + unlock: true, + timeout: 3600, + add_to_search_list: true + ) + match( + type: "appstore", + keychain_name: ENV["MATCH_KEYCHAIN_NAME"], + keychain_password: ENV["MATCH_KEYCHAIN_PASSWORD"], + readonly: true + ) + # ensure_git_status_clean + increment_build_number( + build_number: latest_testflight_build_number + 1, + xcodeproj: "pass.xcodeproj" + ) + # commit_version_bump(xcodeproj: "pass.xcodeproj") + # push_to_git_remote + gym(scheme: "pass") + pilot(skip_waiting_for_build_processing: true) + mailgun( + postmaster: ENV["MY_POSTMASTER"], + apikey: ENV["MY_API_KEY"], + to: ENV["DESTINATION_EMAIL"], + from: ENV["EMAIL_FROM_NAME"], + reply_to: ENV["EMAIL_REPLY_TO"], + subject: "A new build of Pass for iOS has been uploaded", + success: true, + app_link: "https://github.com/mssun/passforios", + ci_build_link: "https://travis-ci.org/mssun/passforios", + message: "A new build has been uploaded by Travis CI.", + ) + end + + desc "Deploy a new version to the App Store" + lane :release do + # match(type: "appstore") + # snapshot + gym(scheme: "pass") # Build your app - more options available + deliver(force: true) + # frameit + end + + # You can define as many lanes as you want + + after_all do |lane| + end + + error do |lane, exception| + end +end + + +# More information about multiple platforms in fastlane: https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Platforms.md +# All available actions: https://docs.fastlane.tools/actions + +# fastlane reports which actions are used +# No personal data is recorded. Learn more at https://github.com/fastlane/enhancer diff --git a/fastlane/Matchfile b/fastlane/Matchfile new file mode 100644 index 0000000..7a59cec --- /dev/null +++ b/fastlane/Matchfile @@ -0,0 +1,9 @@ +git_url "https://github.com/mssun/certificates-passforios.git" + +type "development" # The default type, can be: appstore, adhoc, enterprise or development + +# app_identifier ["tools.fastlane.app", "tools.fastlane.app2"] +# username "user@fastlane.tools" # Your Apple Developer Portal username + +# For all available options run `fastlane match --help` +# Remove the # in the beginning of the line to enable the other options diff --git a/fastlane/travis.sh b/fastlane/travis.sh new file mode 100755 index 0000000..1f3e185 --- /dev/null +++ b/fastlane/travis.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +gem update fastlane +if [ "$TRAVIS_PULL_REQUEST" == "true" ]; then + fastlane test; +else + fastlane travis; +fi +exit $? diff --git a/pass.xcodeproj/project.pbxproj b/pass.xcodeproj/project.pbxproj index 80aac60..12b0373 100644 --- a/pass.xcodeproj/project.pbxproj +++ b/pass.xcodeproj/project.pbxproj @@ -24,6 +24,7 @@ DC037CBF1E4ED4E100609409 /* TextViewTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC037CBD1E4ED4E100609409 /* TextViewTableViewCell.swift */; }; DC037CC01E4ED4E100609409 /* TextViewTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = DC037CBE1E4ED4E100609409 /* TextViewTableViewCell.xib */; }; DC1208581E35EBE60042942E /* ObjectiveGit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC1208571E35EBE60042942E /* ObjectiveGit.framework */; }; + DC13B1511E8640810097803F /* passTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC13B1501E8640810097803F /* passTests.swift */; }; DC193FFA1E49B4430077E0A3 /* AdvancedSettingsTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC193FF91E49B4430077E0A3 /* AdvancedSettingsTableViewController.swift */; }; DC193FFC1E49E0340077E0A3 /* PasscodeLock.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DC193FFB1E49E0340077E0A3 /* PasscodeLock.framework */; }; DC193FFE1E49E0760077E0A3 /* PasscodeLockRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC193FFD1E49E0760077E0A3 /* PasscodeLockRepository.swift */; }; @@ -52,10 +53,10 @@ DCC277D21E30D6EA00402246 /* pass.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = DCC408C81E30BA1300F29B0E /* pass.xcdatamodeld */; }; DCC408A41E2FCC9E00F29B0E /* PasswordStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCC408A31E2FCC9E00F29B0E /* PasswordStore.swift */; }; DCC408C71E307DBB00F29B0E /* SVProgressHUD.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DCC408C61E307DBB00F29B0E /* SVProgressHUD.framework */; }; + DCC441521E8F6C06008A90C4 /* RawPasswordViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCC441511E8F6C06008A90C4 /* RawPasswordViewController.swift */; }; + DCC441541E916382008A90C4 /* GitSSHKeyArmorSettingTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCC441531E916382008A90C4 /* GitSSHKeyArmorSettingTableViewController.swift */; }; DCDDEAB01E4639F300F68193 /* LabelTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = DCDDEAAF1E4639F300F68193 /* LabelTableViewCell.xib */; }; DCDDEAB31E4896BF00F68193 /* PasswordDetailTitleTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCDDEAB11E4896BF00F68193 /* PasswordDetailTitleTableViewCell.swift */; }; - DCE6C2671E71261C003038C6 /* PasswordWithFolderTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCE6C2651E71261C003038C6 /* PasswordWithFolderTableViewCell.swift */; }; - DCE6C2681E71261C003038C6 /* PasswordWithFolderTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = DCE6C2661E71261C003038C6 /* PasswordWithFolderTableViewCell.xib */; }; DCFB779A1E4F3BCF008DE471 /* TitleTextFieldTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCFB77981E4F3BCF008DE471 /* TitleTextFieldTableViewCell.swift */; }; DCFB779B1E4F3BCF008DE471 /* TitleTextFieldTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = DCFB77991E4F3BCF008DE471 /* TitleTextFieldTableViewCell.xib */; }; DCFB779E1E4F40C7008DE471 /* FillPasswordTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCFB779C1E4F40C7008DE471 /* FillPasswordTableViewCell.swift */; }; @@ -67,6 +68,16 @@ DCFB77AB1E503729008DE471 /* ContentTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCFB77AA1E503729008DE471 /* ContentTableViewCell.swift */; }; /* End PBXBuildFile section */ +/* Begin PBXContainerItemProxy section */ + DC13B1531E8640810097803F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = DC917BCB1E2E8231000FDF54 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DC917BD21E2E8231000FDF54; + remoteInfo = pass; + }; +/* End PBXContainerItemProxy section */ + /* Begin PBXFileReference section */ 274CCFCF32444A2FF46BE7F4 /* Pods-pass.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-pass.debug.xcconfig"; path = "Pods/Target Support Files/Pods-pass/Pods-pass.debug.xcconfig"; sourceTree = ""; }; A262A58C1E68749C006B0890 /* Base32.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Base32.framework; path = Carthage/Build/iOS/Base32.framework; sourceTree = ""; }; @@ -87,6 +98,9 @@ DC037CBD1E4ED4E100609409 /* TextViewTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TextViewTableViewCell.swift; sourceTree = ""; }; DC037CBE1E4ED4E100609409 /* TextViewTableViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = TextViewTableViewCell.xib; sourceTree = ""; }; DC1208571E35EBE60042942E /* ObjectiveGit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ObjectiveGit.framework; path = Carthage/Build/iOS/ObjectiveGit.framework; sourceTree = ""; }; + DC13B14E1E8640810097803F /* passTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = passTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + DC13B1501E8640810097803F /* passTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = passTests.swift; sourceTree = ""; }; + DC13B1521E8640810097803F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; DC193FF91E49B4430077E0A3 /* AdvancedSettingsTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AdvancedSettingsTableViewController.swift; sourceTree = ""; }; DC193FFB1E49E0340077E0A3 /* PasscodeLock.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PasscodeLock.framework; path = Carthage/Build/iOS/PasscodeLock.framework; sourceTree = ""; }; DC193FFD1E49E0760077E0A3 /* PasscodeLockRepository.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PasscodeLockRepository.swift; sourceTree = ""; }; @@ -118,10 +132,10 @@ DCC408A31E2FCC9E00F29B0E /* PasswordStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PasswordStore.swift; sourceTree = ""; }; DCC408C61E307DBB00F29B0E /* SVProgressHUD.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SVProgressHUD.framework; path = Carthage/Build/iOS/SVProgressHUD.framework; sourceTree = ""; }; DCC408C91E30BA1300F29B0E /* pass.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = pass.xcdatamodel; sourceTree = ""; }; + DCC441511E8F6C06008A90C4 /* RawPasswordViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RawPasswordViewController.swift; sourceTree = ""; }; + DCC441531E916382008A90C4 /* GitSSHKeyArmorSettingTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GitSSHKeyArmorSettingTableViewController.swift; sourceTree = ""; }; DCDDEAAF1E4639F300F68193 /* LabelTableViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = LabelTableViewCell.xib; sourceTree = ""; }; DCDDEAB11E4896BF00F68193 /* PasswordDetailTitleTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PasswordDetailTitleTableViewCell.swift; sourceTree = ""; }; - DCE6C2651E71261C003038C6 /* PasswordWithFolderTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PasswordWithFolderTableViewCell.swift; sourceTree = ""; }; - DCE6C2661E71261C003038C6 /* PasswordWithFolderTableViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = PasswordWithFolderTableViewCell.xib; sourceTree = ""; }; DCFB77981E4F3BCF008DE471 /* TitleTextFieldTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TitleTextFieldTableViewCell.swift; sourceTree = ""; }; DCFB77991E4F3BCF008DE471 /* TitleTextFieldTableViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = TitleTextFieldTableViewCell.xib; sourceTree = ""; }; DCFB779C1E4F40C7008DE471 /* FillPasswordTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FillPasswordTableViewCell.swift; sourceTree = ""; }; @@ -134,6 +148,13 @@ /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ + DC13B14B1E8640810097803F /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; DC917BD01E2E8231000FDF54 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -162,6 +183,15 @@ name = Pods; sourceTree = ""; }; + DC13B14F1E8640810097803F /* passTests */ = { + isa = PBXGroup; + children = ( + DC13B1501E8640810097803F /* passTests.swift */, + DC13B1521E8640810097803F /* Info.plist */, + ); + path = passTests; + sourceTree = ""; + }; DC19400C1E4B39400077E0A3 /* Controllers */ = { isa = PBXGroup; children = ( @@ -177,12 +207,14 @@ DCA049991E335CC800522E8F /* GitServerSettingTableViewController.swift */, DC037CA51E4B883900609409 /* OpenSourceComponentsTableViewController.swift */, DC4914981E434600007FF592 /* PasswordDetailTableViewController.swift */, + DCC441511E8F6C06008A90C4 /* RawPasswordViewController.swift */, DCFB77A81E502FF6008DE471 /* PasswordEditorTableViewController.swift */, DC5734AD1E439AD400D09270 /* PasswordsViewController.swift */, DCA0499B1E3362F400522E8F /* PGPKeySettingTableViewController.swift */, DCAAF7441E2FA66800AB94BC /* SettingsTableViewController.swift */, DC037CA91E4B8EAE00609409 /* SpecialThanksTableViewController.swift */, DC8963BF1E38EEB900828B09 /* SSHKeySettingTableViewController.swift */, + DCC441531E916382008A90C4 /* GitSSHKeyArmorSettingTableViewController.swift */, ); path = Controllers; sourceTree = ""; @@ -229,8 +261,6 @@ DC037CBD1E4ED4E100609409 /* TextViewTableViewCell.swift */, DC037CBE1E4ED4E100609409 /* TextViewTableViewCell.xib */, DCFB77AA1E503729008DE471 /* ContentTableViewCell.swift */, - DCE6C2651E71261C003038C6 /* PasswordWithFolderTableViewCell.swift */, - DCE6C2661E71261C003038C6 /* PasswordWithFolderTableViewCell.xib */, ); path = Views; sourceTree = ""; @@ -239,6 +269,7 @@ isa = PBXGroup; children = ( DC917BD51E2E8231000FDF54 /* pass */, + DC13B14F1E8640810097803F /* passTests */, DC917BD41E2E8231000FDF54 /* Products */, DC917BED1E2F38C4000FDF54 /* Frameworks */, A51B01737D08DB47BB58F85A /* Pods */, @@ -249,6 +280,7 @@ isa = PBXGroup; children = ( DC917BD31E2E8231000FDF54 /* pass.app */, + DC13B14E1E8640810097803F /* passTests.xctest */, ); name = Products; sourceTree = ""; @@ -289,6 +321,24 @@ /* End PBXGroup section */ /* Begin PBXNativeTarget section */ + DC13B14D1E8640810097803F /* passTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = DC13B1571E8640810097803F /* Build configuration list for PBXNativeTarget "passTests" */; + buildPhases = ( + DC13B14A1E8640810097803F /* Sources */, + DC13B14B1E8640810097803F /* Frameworks */, + DC13B14C1E8640810097803F /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + DC13B1541E8640810097803F /* PBXTargetDependency */, + ); + name = passTests; + productName = passTests; + productReference = DC13B14E1E8640810097803F /* passTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; DC917BD21E2E8231000FDF54 /* pass */ = { isa = PBXNativeTarget; buildConfigurationList = DC917BE51E2E8231000FDF54 /* Build configuration list for PBXNativeTarget "pass" */; @@ -316,14 +366,20 @@ DC917BCB1E2E8231000FDF54 /* Project object */ = { isa = PBXProject; attributes = { - LastSwiftUpdateCheck = 0820; + LastSwiftUpdateCheck = 0830; LastUpgradeCheck = 0820; ORGANIZATIONNAME = "Bob Sun"; TargetAttributes = { + DC13B14D1E8640810097803F = { + CreatedOnToolsVersion = 8.3; + DevelopmentTeam = 4WDM8E95VU; + ProvisioningStyle = Automatic; + TestTargetID = DC917BD21E2E8231000FDF54; + }; DC917BD21E2E8231000FDF54 = { CreatedOnToolsVersion = 8.2.1; DevelopmentTeam = 4WDM8E95VU; - ProvisioningStyle = Automatic; + ProvisioningStyle = Manual; }; }; }; @@ -341,11 +397,19 @@ projectRoot = ""; targets = ( DC917BD21E2E8231000FDF54 /* pass */, + DC13B14D1E8640810097803F /* passTests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ + DC13B14C1E8640810097803F /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; DC917BD11E2E8231000FDF54 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -357,7 +421,6 @@ DCDDEAB01E4639F300F68193 /* LabelTableViewCell.xib in Resources */, DC917BDC1E2E8231000FDF54 /* Main.storyboard in Resources */, A2802BFA1E70813A00879216 /* SliderTableViewCell.xib in Resources */, - DCE6C2681E71261C003038C6 /* PasswordWithFolderTableViewCell.xib in Resources */, DCFB779B1E4F3BCF008DE471 /* TitleTextFieldTableViewCell.xib in Resources */, DCFB779F1E4F40C7008DE471 /* FillPasswordTableViewCell.xib in Resources */, DC037CC01E4ED4E100609409 /* TextViewTableViewCell.xib in Resources */, @@ -437,12 +500,21 @@ /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ + DC13B14A1E8640810097803F /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DC13B1511E8640810097803F /* passTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; DC917BCF1E2E8231000FDF54 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( DCC408A41E2FCC9E00F29B0E /* PasswordStore.swift in Sources */, DC037CBF1E4ED4E100609409 /* TextViewTableViewCell.swift in Sources */, + DCC441541E916382008A90C4 /* GitSSHKeyArmorSettingTableViewController.swift in Sources */, DC8963C01E38EEB900828B09 /* SSHKeySettingTableViewController.swift in Sources */, DC193FFA1E49B4430077E0A3 /* AdvancedSettingsTableViewController.swift in Sources */, DCFB77AB1E503729008DE471 /* ContentTableViewCell.swift in Sources */, @@ -452,7 +524,6 @@ DC5F385B1E56AADB00C69ACA /* PGPKeyArmorSettingTableViewController.swift in Sources */, A27424D91E7C35960093F436 /* NotificationNames.swift in Sources */, DCAAF7451E2FA66800AB94BC /* SettingsTableViewController.swift in Sources */, - DCE6C2671E71261C003038C6 /* PasswordWithFolderTableViewCell.swift in Sources */, DCFB77A71E502DF9008DE471 /* EditPasswordTableViewController.swift in Sources */, DCA0499A1E335CC800522E8F /* GitServerSettingTableViewController.swift in Sources */, DCDDEAB31E4896BF00F68193 /* PasswordDetailTitleTableViewCell.swift in Sources */, @@ -469,6 +540,7 @@ DC037CB21E4CAB1700609409 /* AboutRepositoryTableViewController.swift in Sources */, DC037CB01E4CA51F00609409 /* GeneralSettingsTableViewController.swift in Sources */, DC037CB81E4DD1A500609409 /* AddPasswordTableViewController.swift in Sources */, + DCC441521E8F6C06008A90C4 /* RawPasswordViewController.swift in Sources */, DC1940001E49E1A60077E0A3 /* PasscodeLockConfiguration.swift in Sources */, DC917BD71E2E8231000FDF54 /* AppDelegate.swift in Sources */, DCFB779A1E4F3BCF008DE471 /* TitleTextFieldTableViewCell.swift in Sources */, @@ -484,6 +556,14 @@ }; /* End PBXSourcesBuildPhase section */ +/* Begin PBXTargetDependency section */ + DC13B1541E8640810097803F /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DC917BD21E2E8231000FDF54 /* pass */; + targetProxy = DC13B1531E8640810097803F /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + /* Begin PBXVariantGroup section */ DC917BDA1E2E8231000FDF54 /* Main.storyboard */ = { isa = PBXVariantGroup; @@ -504,6 +584,38 @@ /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ + DC13B1551E8640810097803F /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + DEVELOPMENT_TEAM = 4WDM8E95VU; + INFOPLIST_FILE = passTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 10.3; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = me.mssun.passTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/pass.app/pass"; + }; + name = Debug; + }; + DC13B1561E8640810097803F /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + DEVELOPMENT_TEAM = 4WDM8E95VU; + INFOPLIST_FILE = passTests/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 10.3; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = me.mssun.passTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/pass.app/pass"; + }; + name = Release; + }; DC917BE31E2E8231000FDF54 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -601,7 +713,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - CURRENT_PROJECT_VERSION = 24; + CURRENT_PROJECT_VERSION = 2; DEFINES_MODULE = NO; DEVELOPMENT_TEAM = 4WDM8E95VU; FRAMEWORK_SEARCH_PATHS = ( @@ -620,6 +732,8 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = me.mssun.passforios; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE = "893c10b3-79b1-46f7-914a-e625bf10d665"; + PROVISIONING_PROFILE_SPECIFIER = "match Development me.mssun.passforios"; SWIFT_OBJC_BRIDGING_HEADER = "$(SRCROOT)/pass/Helpers/Objective-CBridgingHeader.h"; SWIFT_VERSION = 3.0; TARGETED_DEVICE_FAMILY = "1,2"; @@ -632,8 +746,8 @@ baseConfigurationReference = AEAD6B31EAF5D061447A68CC /* Pods-pass.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - CURRENT_PROJECT_VERSION = 24; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; + CURRENT_PROJECT_VERSION = 2; DEFINES_MODULE = NO; DEVELOPMENT_TEAM = 4WDM8E95VU; FRAMEWORK_SEARCH_PATHS = ( @@ -652,6 +766,8 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = me.mssun.passforios; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE = "aefeea85-1194-4db2-9ce4-fb9995e2fdff"; + PROVISIONING_PROFILE_SPECIFIER = "match AppStore me.mssun.passforios"; SWIFT_OBJC_BRIDGING_HEADER = "$(SRCROOT)/pass/Helpers/Objective-CBridgingHeader.h"; SWIFT_VERSION = 3.0; TARGETED_DEVICE_FAMILY = "1,2"; @@ -662,6 +778,15 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ + DC13B1571E8640810097803F /* Build configuration list for PBXNativeTarget "passTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DC13B1551E8640810097803F /* Debug */, + DC13B1561E8640810097803F /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; DC917BCE1E2E8231000FDF54 /* Build configuration list for PBXProject "pass" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/pass.xcodeproj/xcshareddata/xcschemes/pass.xcscheme b/pass.xcodeproj/xcshareddata/xcschemes/pass.xcscheme new file mode 100644 index 0000000..95834d6 --- /dev/null +++ b/pass.xcodeproj/xcshareddata/xcschemes/pass.xcscheme @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pass/Assets.xcassets/Camera.imageset/Contents.json b/pass/Assets.xcassets/Camera.imageset/Contents.json new file mode 100644 index 0000000..3f581ce --- /dev/null +++ b/pass/Assets.xcassets/Camera.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "Screenshot-50.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "Screenshot-100.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/pass/Assets.xcassets/Camera.imageset/Screenshot-100.png b/pass/Assets.xcassets/Camera.imageset/Screenshot-100.png new file mode 100644 index 0000000..8375cf6 Binary files /dev/null and b/pass/Assets.xcassets/Camera.imageset/Screenshot-100.png differ diff --git a/pass/Assets.xcassets/Camera.imageset/Screenshot-50.png b/pass/Assets.xcassets/Camera.imageset/Screenshot-50.png new file mode 100644 index 0000000..59fd700 Binary files /dev/null and b/pass/Assets.xcassets/Camera.imageset/Screenshot-50.png differ diff --git a/pass/Assets.xcassets/Copy.imageset/Contents.json b/pass/Assets.xcassets/Copy.imageset/Contents.json new file mode 100644 index 0000000..96c0b79 --- /dev/null +++ b/pass/Assets.xcassets/Copy.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "Copy-50.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "Copy-100.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/pass/Assets.xcassets/Copy.imageset/Copy-100.png b/pass/Assets.xcassets/Copy.imageset/Copy-100.png new file mode 100644 index 0000000..7bbaf9a Binary files /dev/null and b/pass/Assets.xcassets/Copy.imageset/Copy-100.png differ diff --git a/pass/Assets.xcassets/Copy.imageset/Copy-50.png b/pass/Assets.xcassets/Copy.imageset/Copy-50.png new file mode 100644 index 0000000..fe26bc2 Binary files /dev/null and b/pass/Assets.xcassets/Copy.imageset/Copy-50.png differ diff --git a/pass/Assets.xcassets/HorizontalSettings.imageset/Contents.json b/pass/Assets.xcassets/HorizontalSettings.imageset/Contents.json new file mode 100644 index 0000000..f75fd31 --- /dev/null +++ b/pass/Assets.xcassets/HorizontalSettings.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "Horizontal Settings Mixer-50.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "Horizontal Settings Mixer-75.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/pass/Assets.xcassets/HorizontalSettings.imageset/Horizontal Settings Mixer-50.png b/pass/Assets.xcassets/HorizontalSettings.imageset/Horizontal Settings Mixer-50.png new file mode 100644 index 0000000..0d8ce8b Binary files /dev/null and b/pass/Assets.xcassets/HorizontalSettings.imageset/Horizontal Settings Mixer-50.png differ diff --git a/pass/Assets.xcassets/HorizontalSettings.imageset/Horizontal Settings Mixer-75.png b/pass/Assets.xcassets/HorizontalSettings.imageset/Horizontal Settings Mixer-75.png new file mode 100644 index 0000000..84f4783 Binary files /dev/null and b/pass/Assets.xcassets/HorizontalSettings.imageset/Horizontal Settings Mixer-75.png differ diff --git a/pass/Assets.xcassets/Invisible.imageset/Contents.json b/pass/Assets.xcassets/Invisible.imageset/Contents.json new file mode 100644 index 0000000..43f3396 --- /dev/null +++ b/pass/Assets.xcassets/Invisible.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "not-visible-interface-symbol-of-an-eye-with-a-slash-on-it.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/pass/Assets.xcassets/Invisible.imageset/not-visible-interface-symbol-of-an-eye-with-a-slash-on-it.pdf b/pass/Assets.xcassets/Invisible.imageset/not-visible-interface-symbol-of-an-eye-with-a-slash-on-it.pdf new file mode 100644 index 0000000..226d0ee Binary files /dev/null and b/pass/Assets.xcassets/Invisible.imageset/not-visible-interface-symbol-of-an-eye-with-a-slash-on-it.pdf differ diff --git a/pass/Assets.xcassets/Refresh.imageset/Contents.json b/pass/Assets.xcassets/Refresh.imageset/Contents.json new file mode 100644 index 0000000..5932896 --- /dev/null +++ b/pass/Assets.xcassets/Refresh.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "Refresh-64.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "Refresh-75.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/pass/Assets.xcassets/Refresh.imageset/Refresh-64.png b/pass/Assets.xcassets/Refresh.imageset/Refresh-64.png new file mode 100644 index 0000000..4ce94ef Binary files /dev/null and b/pass/Assets.xcassets/Refresh.imageset/Refresh-64.png differ diff --git a/pass/Assets.xcassets/Refresh.imageset/Refresh-75.png b/pass/Assets.xcassets/Refresh.imageset/Refresh-75.png new file mode 100644 index 0000000..7a710ba Binary files /dev/null and b/pass/Assets.xcassets/Refresh.imageset/Refresh-75.png differ diff --git a/pass/Assets.xcassets/Visible.imageset/Contents.json b/pass/Assets.xcassets/Visible.imageset/Contents.json new file mode 100644 index 0000000..d4d3042 --- /dev/null +++ b/pass/Assets.xcassets/Visible.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "eye-visible-outlined-interface-symbol.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/pass/Assets.xcassets/Visible.imageset/eye-visible-outlined-interface-symbol.pdf b/pass/Assets.xcassets/Visible.imageset/eye-visible-outlined-interface-symbol.pdf new file mode 100644 index 0000000..17ee334 Binary files /dev/null and b/pass/Assets.xcassets/Visible.imageset/eye-visible-outlined-interface-symbol.pdf differ diff --git a/pass/Base.lproj/Main.storyboard b/pass/Base.lproj/Main.storyboard index 3883447..f91974e 100644 --- a/pass/Base.lproj/Main.storyboard +++ b/pass/Base.lproj/Main.storyboard @@ -1,11 +1,11 @@ - + - + @@ -158,7 +158,7 @@ - + @@ -167,8 +167,8 @@ - diff --git a/pass/Views/LabelTableViewCell.swift b/pass/Views/LabelTableViewCell.swift index 726b535..c113004 100644 --- a/pass/Views/LabelTableViewCell.swift +++ b/pass/Views/LabelTableViewCell.swift @@ -27,6 +27,9 @@ class LabelTableViewCell: UITableViewCell { weak var delegatePasswordTableView : PasswordDetailTableViewController? + var passwordDisplayButton: UIButton? + var buttons: UIView? + var cellData: LabelTableViewCellData? { didSet { titleLabel.text = cellData?.title ?? "" @@ -43,9 +46,11 @@ class LabelTableViewCell: UITableViewCell { } else { contentLabel.text = Globals.passwordDots } + contentLabel.font = UIFont(name: Globals.passwordFonts, size: contentLabel.font.pointSize) } else { contentLabel.text = cellData?.content } + updateButtons() } } @@ -58,6 +63,13 @@ class LabelTableViewCell: UITableViewCell { override func awakeFromNib() { super.awakeFromNib() } + + override func layoutSubviews() { + super.layoutSubviews() + if buttons != nil { + self.accessoryView = buttons + } + } override func setSelected(_ selected: Bool, animated: Bool) { super.setSelected(selected, animated: animated) @@ -99,13 +111,26 @@ class LabelTableViewCell: UITableViewCell { contentLabel.text = "" } isReveal = true + passwordDisplayButton?.setImage(#imageLiteral(resourceName: "Invisible"), for: .normal) } func concealPassword(_ sender: Any?) { contentLabel.text = Globals.passwordDots isReveal = false + passwordDisplayButton?.setImage(#imageLiteral(resourceName: "Visible"), for: .normal) } + func reversePasswordDisplay(_ sender: Any?) { + if isReveal { + // conceal + concealPassword(sender) + } else { + // reveal + revealPassword(sender) + } + } + + func openLink(_ sender: Any?) { // if isURLCell, passwordTableView should not be nil delegatePasswordTableView!.openLink() @@ -115,4 +140,50 @@ class LabelTableViewCell: UITableViewCell { // if isHOTPCell, passwordTableView should not be nil delegatePasswordTableView!.getNextHOTP() } + + func updateButtons() { + passwordDisplayButton = nil + buttons = nil + + // total width and height of a button + let height = min(self.bounds.height, 36.0) + let width = max(height * 0.8, Globals.tableCellButtonSize) + + // margins (between button boundary and icon) + let marginY = max((height - Globals.tableCellButtonSize) / 2, 0.0) + let marginX = max((width - Globals.tableCellButtonSize) / 2, 0.0) + + if isPasswordCell { + // password button + passwordDisplayButton = UIButton(type: .system) + passwordDisplayButton!.frame = CGRect(x: 0, y: 0, width: width, height: height) + passwordDisplayButton!.setImage(#imageLiteral(resourceName: "Visible"), for: .normal) + passwordDisplayButton!.imageView?.contentMode = .scaleAspectFit + passwordDisplayButton!.contentEdgeInsets = UIEdgeInsetsMake(marginY, marginX, marginY, marginX) + passwordDisplayButton!.addTarget(self, action: #selector(reversePasswordDisplay), for: UIControlEvents.touchUpInside) + buttons = passwordDisplayButton + } else if isHOTPCell { + // hotp button + let nextButton = UIButton(type: .system) + nextButton.frame = CGRect(x: 0, y: 0, width: width, height: height) + nextButton.setImage(#imageLiteral(resourceName: "Refresh"), for: .normal) + nextButton.imageView?.contentMode = .scaleAspectFit + nextButton.contentEdgeInsets = UIEdgeInsetsMake(marginY, marginX, marginY, marginX) + nextButton.addTarget(self, action: #selector(getNextHOTP), for: UIControlEvents.touchUpInside) + + // password button + passwordDisplayButton = UIButton(type: .system) + passwordDisplayButton!.frame = CGRect(x: width, y: 0, width: width, height: height) + + passwordDisplayButton!.setImage(#imageLiteral(resourceName: "Visible"), for: .normal) + passwordDisplayButton!.imageView?.contentMode = .scaleAspectFit + passwordDisplayButton!.contentEdgeInsets = UIEdgeInsetsMake(marginY, marginX, marginY, marginX) + passwordDisplayButton!.addTarget(self, action: #selector(reversePasswordDisplay), for: UIControlEvents.touchUpInside) + + buttons = UIView() + buttons!.frame = CGRect(x: 0, y: 0, width: width * 2, height: height) + buttons!.addSubview(nextButton) + buttons!.addSubview(passwordDisplayButton!) + } + } } diff --git a/pass/Views/LabelTableViewCell.xib b/pass/Views/LabelTableViewCell.xib index 8c8990f..da80c59 100644 --- a/pass/Views/LabelTableViewCell.xib +++ b/pass/Views/LabelTableViewCell.xib @@ -1,11 +1,11 @@ - + - + @@ -16,17 +16,20 @@ - + - + diff --git a/pass/Views/PasswordDetailTitleTableViewCell.xib b/pass/Views/PasswordDetailTitleTableViewCell.xib index 759a78f..fcd32f9 100644 --- a/pass/Views/PasswordDetailTitleTableViewCell.xib +++ b/pass/Views/PasswordDetailTitleTableViewCell.xib @@ -1,11 +1,11 @@ - + - + @@ -17,7 +17,7 @@ - + diff --git a/pass/Views/PasswordWithFolderTableViewCell.swift b/pass/Views/PasswordWithFolderTableViewCell.swift deleted file mode 100644 index b1b9c1e..0000000 --- a/pass/Views/PasswordWithFolderTableViewCell.swift +++ /dev/null @@ -1,27 +0,0 @@ -// -// PasswordTableViewCell.swift -// pass -// -// Created by Mingshen Sun on 8/3/2017. -// Copyright © 2017 Bob Sun. All rights reserved. -// - -import UIKit - -class PasswordWithFolderTableViewCell: UITableViewCell { - - @IBOutlet weak var passwordLabel: UILabel! - @IBOutlet weak var folderLabel: UILabel! - - override func awakeFromNib() { - super.awakeFromNib() - // Initialization code - } - - override func setSelected(_ selected: Bool, animated: Bool) { - super.setSelected(selected, animated: animated) - - // Configure the view for the selected state - } - -} diff --git a/pass/Views/PasswordWithFolderTableViewCell.xib b/pass/Views/PasswordWithFolderTableViewCell.xib deleted file mode 100644 index 74957c5..0000000 --- a/pass/Views/PasswordWithFolderTableViewCell.xib +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/pass/Views/SliderTableViewCell.swift b/pass/Views/SliderTableViewCell.swift index a641c44..cbcdebb 100644 --- a/pass/Views/SliderTableViewCell.swift +++ b/pass/Views/SliderTableViewCell.swift @@ -58,6 +58,13 @@ class SliderTableViewCell: ContentTableViewCell { slider.maximumValue = Float(maximumValue) slider.value = Float(defaultValue) valueLabel.text = String(defaultValue) + + // "not editable" + if minimumValue == maximumValue { + titleLabel.textColor = UIColor.gray + valueLabel.textColor = UIColor.gray + slider.isUserInteractionEnabled = false + } } } diff --git a/pass/Views/SliderTableViewCell.xib b/pass/Views/SliderTableViewCell.xib index 09698e8..593b9d3 100644 --- a/pass/Views/SliderTableViewCell.xib +++ b/pass/Views/SliderTableViewCell.xib @@ -1,11 +1,11 @@ - + - + @@ -20,7 +20,7 @@ - + @@ -34,8 +34,8 @@ - - + diff --git a/pass/Views/TextFieldTableViewCell.xib b/pass/Views/TextFieldTableViewCell.xib index 000fbd6..d854c95 100644 --- a/pass/Views/TextFieldTableViewCell.xib +++ b/pass/Views/TextFieldTableViewCell.xib @@ -1,11 +1,11 @@ - + - + @@ -16,11 +16,11 @@ - + - + @@ -30,7 +30,7 @@ - + diff --git a/pass/Views/TextViewTableViewCell.xib b/pass/Views/TextViewTableViewCell.xib index 83178bb..33f8756 100644 --- a/pass/Views/TextViewTableViewCell.xib +++ b/pass/Views/TextViewTableViewCell.xib @@ -1,5 +1,5 @@ - + @@ -20,7 +20,7 @@ - + @@ -31,9 +31,9 @@ - - - + + + diff --git a/pass/Views/TitleTextFieldTableViewCell.xib b/pass/Views/TitleTextFieldTableViewCell.xib index 37cdf0d..ae3d121 100644 --- a/pass/Views/TitleTextFieldTableViewCell.xib +++ b/pass/Views/TitleTextFieldTableViewCell.xib @@ -1,11 +1,11 @@ - + - + @@ -16,17 +16,20 @@ - + - - + + + + + @@ -36,17 +39,17 @@ + - - + diff --git a/passTests/Info.plist b/passTests/Info.plist new file mode 100644 index 0000000..2b23286 --- /dev/null +++ b/passTests/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 2 + + diff --git a/passTests/passTests.swift b/passTests/passTests.swift new file mode 100644 index 0000000..fbc5343 --- /dev/null +++ b/passTests/passTests.swift @@ -0,0 +1,35 @@ +// +// passTests.swift +// passTests +// +// Created by Mingshen Sun on 24/3/2017. +// Copyright © 2017 Bob Sun. All rights reserved. +// + +import XCTest + +class passTests: XCTestCase { + + override func setUp() { + super.setUp() + // Put setup code here. This method is called before the invocation of each test method in the class. + } + + override func tearDown() { + // Put teardown code here. This method is called after the invocation of each test method in the class. + super.tearDown() + } + + func testExample() { + // This is an example of a functional test case. + // Use XCTAssert and related functions to verify your tests produce the correct results. + } + + func testPerformanceExample() { + // This is an example of a performance test case. + self.measure { + // Put the code you want to measure the time of here. + } + } + +}