diff --git a/.travis.yml b/.travis.yml index 26f238f..dc7b1fc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ language: objective-c -xcode_project: chatExample/simpleChat.xcodeproj # path to your xcodeproj folder -xcode_scheme: simpleChat +xcode_project: chatExample/ETHRadar.xcodeproj # path to your xcodeproj folder +xcode_scheme: ETHRadar osx_image: xcode8 -script: xcodebuild -destination "platform=iOS Simulator,name=iPhone 6,OS=10.0" -scheme "simpleChat" -project "chatExample/simpleChat.xcodeproj" build test +script: xcodebuild -destination "platform=iOS Simulator,name=iPhone 7" -scheme "ETHRadar" -project "chatExample/ETHRadar.xcodeproj" build test diff --git a/README.md b/README.md index 5bc96cf..e7218ca 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,12 @@ -# chatExample -[![Build Status](https://travis-ci.org/wolffan/chatExample.svg?branch=master)](https://travis-ci.org/wolffan/chatExample) -Example of a chat conversation UI +# ETHRadar +[![Build Status](https://travis-ci.org/wolffan/chatExample.svg?branch=argent)](https://travis-ci.org/wolffan/chatExample) +Example ETH and token Radar No dependenceis are needed to run the project. Tests will run with CMD+U -To Run UI tests, access the file and manually run tests, UI tests fail on command line execution Overall architecture: Router that handles all dependencies and controllers. Controllers talk to extending Router methods in order to not have hidden dependencies between them -Cells have viewModel to abstract the presentation logic from Controller and Cell +Cell has viewModel to abstract the presentation logic from Controller and Cell Data is fetched and injected through Repositories with different protocols so each class has only the data it needs. diff --git a/chatExample/.DS_Store b/chatExample/.DS_Store new file mode 100644 index 0000000..21ccc25 Binary files /dev/null and b/chatExample/.DS_Store differ diff --git a/chatExample/Assets.xcassets/.DS_Store b/chatExample/Assets.xcassets/.DS_Store new file mode 100644 index 0000000..5008ddf Binary files /dev/null and b/chatExample/Assets.xcassets/.DS_Store differ diff --git a/chatExample/Assets.xcassets/AppIcon.appiconset/Contents.json b/chatExample/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index 9da08d1..0000000 --- a/chatExample/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,65 +0,0 @@ -{ - "images" : [ - { - "idiom" : "iphone", - "size" : "20x20", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "20x20", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "1x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "29x29", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "40x40", - "scale" : "3x" - }, - { - "idiom" : "iphone", - "size" : "57x57", - "scale" : "1x" - }, - { - "size" : "57x57", - "idiom" : "iphone", - "filename" : "dT7eGEonc.png", - "scale" : "2x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "dT7eGEonc-1.png", - "scale" : "2x" - }, - { - "idiom" : "iphone", - "size" : "60x60", - "scale" : "3x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/chatExample/Assets.xcassets/AppIcon.appiconset/dT7eGEonc-1.png b/chatExample/Assets.xcassets/AppIcon.appiconset/dT7eGEonc-1.png deleted file mode 100644 index 06a2c87..0000000 Binary files a/chatExample/Assets.xcassets/AppIcon.appiconset/dT7eGEonc-1.png and /dev/null differ diff --git a/chatExample/Assets.xcassets/AppIcon.appiconset/dT7eGEonc.png b/chatExample/Assets.xcassets/AppIcon.appiconset/dT7eGEonc.png deleted file mode 100644 index 06a2c87..0000000 Binary files a/chatExample/Assets.xcassets/AppIcon.appiconset/dT7eGEonc.png and /dev/null differ diff --git a/chatExample/Assets.xcassets/icon.imageset/Contents.json b/chatExample/Assets.xcassets/icon.imageset/Contents.json deleted file mode 100644 index 02a1f53..0000000 --- a/chatExample/Assets.xcassets/icon.imageset/Contents.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "dT7eGEonc.png", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/chatExample/Assets.xcassets/icon.imageset/dT7eGEonc.png b/chatExample/Assets.xcassets/icon.imageset/dT7eGEonc.png deleted file mode 100644 index 06a2c87..0000000 Binary files a/chatExample/Assets.xcassets/icon.imageset/dT7eGEonc.png and /dev/null differ diff --git a/chatExample/Assets.xcassets/logout.imageset/Contents.json b/chatExample/Assets.xcassets/logout.imageset/Contents.json deleted file mode 100644 index 29fd722..0000000 --- a/chatExample/Assets.xcassets/logout.imageset/Contents.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "Export-50.png", - "scale" : "1x" - }, - { - "idiom" : "universal", - "filename" : "logout@2x 08.25.17.png", - "scale" : "2x" - }, - { - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/chatExample/Assets.xcassets/logout.imageset/logout@2x 08.25.17.png b/chatExample/Assets.xcassets/logout.imageset/logout@2x 08.25.17.png deleted file mode 100644 index 54ac073..0000000 Binary files a/chatExample/Assets.xcassets/logout.imageset/logout@2x 08.25.17.png and /dev/null differ diff --git a/chatExample/simpleChat.xcodeproj/project.pbxproj b/chatExample/ETHRadar.xcodeproj/project.pbxproj similarity index 53% rename from chatExample/simpleChat.xcodeproj/project.pbxproj rename to chatExample/ETHRadar.xcodeproj/project.pbxproj index 42646a5..bf1dacf 100644 --- a/chatExample/simpleChat.xcodeproj/project.pbxproj +++ b/chatExample/ETHRadar.xcodeproj/project.pbxproj @@ -7,82 +7,76 @@ objects = { /* Begin PBXBuildFile section */ + 2D83D9DB202AE81C0075EAAE /* ViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2D83D9DA202AE81B0075EAAE /* ViewController.xib */; }; + 2DAD1018202B70D600B553F2 /* Token.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DAD1017202B70D600B553F2 /* Token.swift */; }; + 2DAD101A202C4C2100B553F2 /* Errors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DAD1019202C4C2100B553F2 /* Errors.swift */; }; + 2DAD101C2030E3C700B553F2 /* DoubleExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DAD101B2030E3C700B553F2 /* DoubleExtension.swift */; }; + 2DAD101E2031FDDC00B553F2 /* TokenStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DAD101D2031FDDC00B553F2 /* TokenStorage.swift */; }; + 2DAD1022203376CE00B553F2 /* MainViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DAD1021203376CE00B553F2 /* MainViewModel.swift */; }; + 2DAD102420341C3F00B553F2 /* Coins.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DAD102320341C3F00B553F2 /* Coins.swift */; }; + 2DB3676D2025D64000427E3F /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 2DB3676C2025D64000427E3F /* Localizable.strings */; }; + 2DBC434420344314000F4558 /* ETHRadarTesting.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DBC434320344314000F4558 /* ETHRadarTesting.swift */; }; + 2DBC434B20344319000F4558 /* DateHelpersTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDCEC30C1DC2B0E9002B7549 /* DateHelpersTests.swift */; }; + 2DBC434C2034431C000F4558 /* ChatViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD88EFA31DCA628A0023FD5F /* ChatViewModelTests.swift */; }; + 2DBC434D2034431F000F4558 /* IntegrationStorageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DAD101F2032419B00B553F2 /* IntegrationStorageTests.swift */; }; CD4D6AC11DBD1DA000643DBF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = CD4D6ABF1DBD1DA000643DBF /* LaunchScreen.storyboard */; }; - CD4D6AD71DBD1DA000643DBF /* simpleChatUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD4D6AD61DBD1DA000643DBF /* simpleChatUITests.swift */; }; CD4D6AEA1DBD1E0500643DBF /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD4D6AE41DBD1E0500643DBF /* AppDelegate.swift */; }; CD4D6AEB1DBD1E0500643DBF /* keyboardExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD4D6AE51DBD1E0500643DBF /* keyboardExtension.swift */; }; CD4D6AEC1DBD1E0500643DBF /* Router.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD4D6AE61DBD1E0500643DBF /* Router.swift */; }; - CD4D6AED1DBD1E0500643DBF /* userRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD4D6AE71DBD1E0500643DBF /* userRepository.swift */; }; CD4D6AEE1DBD1E0500643DBF /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD4D6AE81DBD1E0500643DBF /* ViewController.swift */; }; - CD4D6AEF1DBD1E0500643DBF /* ViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = CD4D6AE91DBD1E0500643DBF /* ViewController.xib */; }; - CD4D6AF11DBD228D00643DBF /* userRepositoryIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD4D6AF01DBD228D00643DBF /* userRepositoryIntegrationTests.swift */; }; - CD88EF961DC729E90023FD5F /* MeChatTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD88EF951DC729E90023FD5F /* MeChatTableViewCell.swift */; }; - CD88EF981DC729F70023FD5F /* MeChatTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = CD88EF971DC729F70023FD5F /* MeChatTableViewCell.xib */; }; - CD88EF9A1DC9CE750023FD5F /* ChatViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD88EF991DC9CE750023FD5F /* ChatViewModel.swift */; }; - CD88EF9C1DCA3BE20023FD5F /* ChatTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD88EF9B1DCA3BE20023FD5F /* ChatTests.swift */; }; - CD88EF9E1DCA412B0023FD5F /* UserCheck.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD88EF9D1DCA412B0023FD5F /* UserCheck.swift */; }; + CD88EF9A1DC9CE750023FD5F /* TokenCellViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD88EF991DC9CE750023FD5F /* TokenCellViewModel.swift */; }; CD88EFA01DCA47C00023FD5F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CD88EF9F1DCA47C00023FD5F /* Assets.xcassets */; }; - CD88EFA21DCA48EC0023FD5F /* UsernameValidatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD88EFA11DCA48EC0023FD5F /* UsernameValidatorTests.swift */; }; - CD88EFA41DCA628A0023FD5F /* ChatViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD88EFA31DCA628A0023FD5F /* ChatViewModelTests.swift */; }; - CD955F291DC15E600032EE3D /* ChatTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD955F281DC15E600032EE3D /* ChatTableViewCell.swift */; }; - CD955F2B1DC15E740032EE3D /* ChatTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = CD955F2A1DC15E740032EE3D /* ChatTableViewCell.xib */; }; - CD955F2D1DC16FFF0032EE3D /* imageLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD955F2C1DC16FFF0032EE3D /* imageLoader.swift */; }; + CD955F291DC15E600032EE3D /* TokenCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD955F281DC15E600032EE3D /* TokenCell.swift */; }; + CD955F2B1DC15E740032EE3D /* TokenCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = CD955F2A1DC15E740032EE3D /* TokenCell.xib */; }; CDAD44B91DBD24D30052BCC9 /* routingExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDAD44B81DBD24D30052BCC9 /* routingExtension.swift */; }; - CDAD44BB1DBD35FA0052BCC9 /* ChatController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDAD44BA1DBD35FA0052BCC9 /* ChatController.swift */; }; - CDAD44BD1DBD37FC0052BCC9 /* ChatController.xib in Resources */ = {isa = PBXBuildFile; fileRef = CDAD44BC1DBD37FC0052BCC9 /* ChatController.xib */; }; + CDAD44BB1DBD35FA0052BCC9 /* TokenController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDAD44BA1DBD35FA0052BCC9 /* TokenController.swift */; }; + CDAD44BD1DBD37FC0052BCC9 /* TokenController.xib in Resources */ = {isa = PBXBuildFile; fileRef = CDAD44BC1DBD37FC0052BCC9 /* TokenController.xib */; }; CDAD44C31DBFFEF70052BCC9 /* DataRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDAD44C21DBFFEF70052BCC9 /* DataRepository.swift */; }; CDAD44C81DC11B780052BCC9 /* Chat.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDAD44C71DC11B780052BCC9 /* Chat.swift */; }; CDCEC30B1DC1D7BE002B7549 /* DateHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDCEC30A1DC1D7BE002B7549 /* DateHelper.swift */; }; - CDCEC30D1DC2B0E9002B7549 /* DateHelpersTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDCEC30C1DC2B0E9002B7549 /* DateHelpersTests.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ - CD4D6AC81DBD1DA000643DBF /* PBXContainerItemProxy */ = { + 2DBC434620344314000F4558 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = CD4D6AAB1DBD1DA000643DBF /* Project object */; proxyType = 1; remoteGlobalIDString = CD4D6AB21DBD1DA000643DBF; - remoteInfo = simpleChat; - }; - CD4D6AD31DBD1DA000643DBF /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = CD4D6AAB1DBD1DA000643DBF /* Project object */; - proxyType = 1; - remoteGlobalIDString = CD4D6AB21DBD1DA000643DBF; - remoteInfo = simpleChat; + remoteInfo = ETHRadar; }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ - CD4D6AB31DBD1DA000643DBF /* simpleChat.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = simpleChat.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 2D5C0F9920342B5C002D5140 /* ETHRadarTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ETHRadarTest.swift; sourceTree = ""; }; + 2D5C0F9B20342B5C002D5140 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 2D83D9DA202AE81B0075EAAE /* ViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ViewController.xib; sourceTree = ""; }; + 2DAD1017202B70D600B553F2 /* Token.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Token.swift; sourceTree = ""; }; + 2DAD1019202C4C2100B553F2 /* Errors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Errors.swift; sourceTree = ""; }; + 2DAD101B2030E3C700B553F2 /* DoubleExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DoubleExtension.swift; sourceTree = ""; }; + 2DAD101D2031FDDC00B553F2 /* TokenStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TokenStorage.swift; sourceTree = ""; }; + 2DAD101F2032419B00B553F2 /* IntegrationStorageTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntegrationStorageTests.swift; sourceTree = ""; }; + 2DAD1021203376CE00B553F2 /* MainViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainViewModel.swift; sourceTree = ""; }; + 2DAD102320341C3F00B553F2 /* Coins.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Coins.swift; sourceTree = ""; }; + 2DB3676C2025D64000427E3F /* Localizable.strings */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; path = Localizable.strings; sourceTree = SOURCE_ROOT; }; + 2DBC434120344314000F4558 /* ETHRadarTesting.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ETHRadarTesting.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 2DBC434320344314000F4558 /* ETHRadarTesting.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ETHRadarTesting.swift; sourceTree = ""; }; + 2DBC434520344314000F4558 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + CD4D6AB31DBD1DA000643DBF /* ETHRadar.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ETHRadar.app; sourceTree = BUILT_PRODUCTS_DIR; }; CD4D6AC01DBD1DA000643DBF /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; CD4D6AC21DBD1DA000643DBF /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - CD4D6AC71DBD1DA000643DBF /* simpleChatTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = simpleChatTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; CD4D6ACD1DBD1DA000643DBF /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - CD4D6AD21DBD1DA000643DBF /* simpleChatUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = simpleChatUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - CD4D6AD61DBD1DA000643DBF /* simpleChatUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = simpleChatUITests.swift; sourceTree = ""; }; - CD4D6AD81DBD1DA100643DBF /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; CD4D6AE41DBD1E0500643DBF /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; CD4D6AE51DBD1E0500643DBF /* keyboardExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = keyboardExtension.swift; sourceTree = ""; }; CD4D6AE61DBD1E0500643DBF /* Router.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Router.swift; sourceTree = ""; }; - CD4D6AE71DBD1E0500643DBF /* userRepository.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = userRepository.swift; sourceTree = ""; }; CD4D6AE81DBD1E0500643DBF /* ViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; - CD4D6AE91DBD1E0500643DBF /* ViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ViewController.xib; sourceTree = ""; }; - CD4D6AF01DBD228D00643DBF /* userRepositoryIntegrationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = userRepositoryIntegrationTests.swift; sourceTree = ""; }; - CD88EF951DC729E90023FD5F /* MeChatTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MeChatTableViewCell.swift; sourceTree = ""; }; - CD88EF971DC729F70023FD5F /* MeChatTableViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MeChatTableViewCell.xib; sourceTree = ""; }; - CD88EF991DC9CE750023FD5F /* ChatViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChatViewModel.swift; sourceTree = ""; }; - CD88EF9B1DCA3BE20023FD5F /* ChatTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChatTests.swift; sourceTree = ""; }; - CD88EF9D1DCA412B0023FD5F /* UserCheck.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserCheck.swift; sourceTree = ""; }; + CD88EF991DC9CE750023FD5F /* TokenCellViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TokenCellViewModel.swift; sourceTree = ""; }; CD88EF9F1DCA47C00023FD5F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = SOURCE_ROOT; }; - CD88EFA11DCA48EC0023FD5F /* UsernameValidatorTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UsernameValidatorTests.swift; sourceTree = ""; }; CD88EFA31DCA628A0023FD5F /* ChatViewModelTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChatViewModelTests.swift; sourceTree = ""; }; - CD955F281DC15E600032EE3D /* ChatTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChatTableViewCell.swift; sourceTree = ""; }; - CD955F2A1DC15E740032EE3D /* ChatTableViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ChatTableViewCell.xib; sourceTree = ""; }; - CD955F2C1DC16FFF0032EE3D /* imageLoader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = imageLoader.swift; sourceTree = ""; }; + CD955F281DC15E600032EE3D /* TokenCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TokenCell.swift; sourceTree = ""; }; + CD955F2A1DC15E740032EE3D /* TokenCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = TokenCell.xib; sourceTree = ""; }; CDAD44B81DBD24D30052BCC9 /* routingExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = routingExtension.swift; sourceTree = ""; }; - CDAD44BA1DBD35FA0052BCC9 /* ChatController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ChatController.swift; sourceTree = ""; }; - CDAD44BC1DBD37FC0052BCC9 /* ChatController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ChatController.xib; sourceTree = ""; }; + CDAD44BA1DBD35FA0052BCC9 /* TokenController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TokenController.swift; sourceTree = ""; }; + CDAD44BC1DBD37FC0052BCC9 /* TokenController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = TokenController.xib; sourceTree = ""; }; CDAD44C21DBFFEF70052BCC9 /* DataRepository.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DataRepository.swift; sourceTree = ""; }; CDAD44C71DC11B780052BCC9 /* Chat.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Chat.swift; sourceTree = ""; }; CDCEC30A1DC1D7BE002B7549 /* DateHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DateHelper.swift; sourceTree = ""; }; @@ -90,21 +84,14 @@ /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ - CD4D6AB01DBD1DA000643DBF /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - CD4D6AC41DBD1DA000643DBF /* Frameworks */ = { + 2DBC433E20344314000F4558 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; - CD4D6ACF1DBD1DA000643DBF /* Frameworks */ = { + CD4D6AB01DBD1DA000643DBF /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( @@ -114,12 +101,31 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 2D5C0F9820342B5C002D5140 /* ETHRadarTest */ = { + isa = PBXGroup; + children = ( + 2D5C0F9920342B5C002D5140 /* ETHRadarTest.swift */, + 2D5C0F9B20342B5C002D5140 /* Info.plist */, + ); + path = ETHRadarTest; + sourceTree = ""; + }; + 2DBC434220344314000F4558 /* ETHRadarTesting */ = { + isa = PBXGroup; + children = ( + 2DBC434320344314000F4558 /* ETHRadarTesting.swift */, + 2DBC434520344314000F4558 /* Info.plist */, + ); + path = ETHRadarTesting; + sourceTree = ""; + }; CD4D6AAA1DBD1DA000643DBF = { isa = PBXGroup; children = ( - CD4D6AB51DBD1DA000643DBF /* simpleChat */, - CD4D6ACA1DBD1DA000643DBF /* simpleChatTests */, - CD4D6AD51DBD1DA000643DBF /* simpleChatUITests */, + CD4D6AB51DBD1DA000643DBF /* ETHRadar */, + CD4D6ACA1DBD1DA000643DBF /* ETHRadarTests */, + 2D5C0F9820342B5C002D5140 /* ETHRadarTest */, + 2DBC434220344314000F4558 /* ETHRadarTesting */, CD4D6AB41DBD1DA000643DBF /* Products */, ); sourceTree = ""; @@ -127,17 +133,17 @@ CD4D6AB41DBD1DA000643DBF /* Products */ = { isa = PBXGroup; children = ( - CD4D6AB31DBD1DA000643DBF /* simpleChat.app */, - CD4D6AC71DBD1DA000643DBF /* simpleChatTests.xctest */, - CD4D6AD21DBD1DA000643DBF /* simpleChatUITests.xctest */, + CD4D6AB31DBD1DA000643DBF /* ETHRadar.app */, + 2DBC434120344314000F4558 /* ETHRadarTesting.xctest */, ); name = Products; sourceTree = ""; }; - CD4D6AB51DBD1DA000643DBF /* simpleChat */ = { + CD4D6AB51DBD1DA000643DBF /* ETHRadar */ = { isa = PBXGroup; children = ( CD88EF9F1DCA47C00023FD5F /* Assets.xcassets */, + 2DB3676C2025D64000427E3F /* Localizable.strings */, CD88EF941DC729CB0023FD5F /* Views */, CD4D6ABF1DBD1DA000643DBF /* LaunchScreen.storyboard */, CD4D6AC21DBD1DA000643DBF /* Info.plist */, @@ -145,43 +151,32 @@ CD4D6AE51DBD1E0500643DBF /* keyboardExtension.swift */, CD4D6AE61DBD1E0500643DBF /* Router.swift */, CDAD44B81DBD24D30052BCC9 /* routingExtension.swift */, + 2DAD1019202C4C2100B553F2 /* Errors.swift */, + 2DAD101B2030E3C700B553F2 /* DoubleExtension.swift */, CDAD44C61DC11B610052BCC9 /* Repository */, CDAD44C51DC11B4B0052BCC9 /* Controllers */, CDAD44C41DC11B3F0052BCC9 /* Models */, ); - path = simpleChat; + path = ETHRadar; sourceTree = ""; }; - CD4D6ACA1DBD1DA000643DBF /* simpleChatTests */ = { + CD4D6ACA1DBD1DA000643DBF /* ETHRadarTests */ = { isa = PBXGroup; children = ( - CD4D6AF01DBD228D00643DBF /* userRepositoryIntegrationTests.swift */, CDCEC30C1DC2B0E9002B7549 /* DateHelpersTests.swift */, - CD88EF9B1DCA3BE20023FD5F /* ChatTests.swift */, - CD88EFA11DCA48EC0023FD5F /* UsernameValidatorTests.swift */, CD88EFA31DCA628A0023FD5F /* ChatViewModelTests.swift */, + 2DAD101F2032419B00B553F2 /* IntegrationStorageTests.swift */, CD4D6ACD1DBD1DA000643DBF /* Info.plist */, ); - path = simpleChatTests; - sourceTree = ""; - }; - CD4D6AD51DBD1DA000643DBF /* simpleChatUITests */ = { - isa = PBXGroup; - children = ( - CD4D6AD61DBD1DA000643DBF /* simpleChatUITests.swift */, - CD4D6AD81DBD1DA100643DBF /* Info.plist */, - ); - path = simpleChatUITests; + path = ETHRadarTests; sourceTree = ""; }; CD88EF941DC729CB0023FD5F /* Views */ = { isa = PBXGroup; children = ( - CD955F281DC15E600032EE3D /* ChatTableViewCell.swift */, - CD955F2A1DC15E740032EE3D /* ChatTableViewCell.xib */, - CD88EF951DC729E90023FD5F /* MeChatTableViewCell.swift */, - CD88EF971DC729F70023FD5F /* MeChatTableViewCell.xib */, - CD88EF991DC9CE750023FD5F /* ChatViewModel.swift */, + CD955F281DC15E600032EE3D /* TokenCell.swift */, + CD955F2A1DC15E740032EE3D /* TokenCell.xib */, + CD88EF991DC9CE750023FD5F /* TokenCellViewModel.swift */, ); name = Views; sourceTree = ""; @@ -190,6 +185,8 @@ isa = PBXGroup; children = ( CDAD44C71DC11B780052BCC9 /* Chat.swift */, + 2DAD1017202B70D600B553F2 /* Token.swift */, + 2DAD1021203376CE00B553F2 /* MainViewModel.swift */, ); name = Models; sourceTree = ""; @@ -198,9 +195,9 @@ isa = PBXGroup; children = ( CD4D6AE81DBD1E0500643DBF /* ViewController.swift */, - CD4D6AE91DBD1E0500643DBF /* ViewController.xib */, - CDAD44BA1DBD35FA0052BCC9 /* ChatController.swift */, - CDAD44BC1DBD37FC0052BCC9 /* ChatController.xib */, + 2D83D9DA202AE81B0075EAAE /* ViewController.xib */, + CDAD44BA1DBD35FA0052BCC9 /* TokenController.swift */, + CDAD44BC1DBD37FC0052BCC9 /* TokenController.xib */, ); name = Controllers; sourceTree = ""; @@ -208,11 +205,10 @@ CDAD44C61DC11B610052BCC9 /* Repository */ = { isa = PBXGroup; children = ( - CD4D6AE71DBD1E0500643DBF /* userRepository.swift */, CDAD44C21DBFFEF70052BCC9 /* DataRepository.swift */, - CD955F2C1DC16FFF0032EE3D /* imageLoader.swift */, CDCEC30A1DC1D7BE002B7549 /* DateHelper.swift */, - CD88EF9D1DCA412B0023FD5F /* UserCheck.swift */, + 2DAD101D2031FDDC00B553F2 /* TokenStorage.swift */, + 2DAD102320341C3F00B553F2 /* Coins.swift */, ); name = Repository; sourceTree = ""; @@ -220,58 +216,40 @@ /* End PBXGroup section */ /* Begin PBXNativeTarget section */ - CD4D6AB21DBD1DA000643DBF /* simpleChat */ = { - isa = PBXNativeTarget; - buildConfigurationList = CD4D6ADB1DBD1DA100643DBF /* Build configuration list for PBXNativeTarget "simpleChat" */; - buildPhases = ( - CD4D6AAF1DBD1DA000643DBF /* Sources */, - CD4D6AB01DBD1DA000643DBF /* Frameworks */, - CD4D6AB11DBD1DA000643DBF /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = simpleChat; - productName = simpleChat; - productReference = CD4D6AB31DBD1DA000643DBF /* simpleChat.app */; - productType = "com.apple.product-type.application"; - }; - CD4D6AC61DBD1DA000643DBF /* simpleChatTests */ = { + 2DBC434020344314000F4558 /* ETHRadarTesting */ = { isa = PBXNativeTarget; - buildConfigurationList = CD4D6ADE1DBD1DA100643DBF /* Build configuration list for PBXNativeTarget "simpleChatTests" */; + buildConfigurationList = 2DBC434820344314000F4558 /* Build configuration list for PBXNativeTarget "ETHRadarTesting" */; buildPhases = ( - CD4D6AC31DBD1DA000643DBF /* Sources */, - CD4D6AC41DBD1DA000643DBF /* Frameworks */, - CD4D6AC51DBD1DA000643DBF /* Resources */, + 2DBC433D20344314000F4558 /* Sources */, + 2DBC433E20344314000F4558 /* Frameworks */, + 2DBC433F20344314000F4558 /* Resources */, ); buildRules = ( ); dependencies = ( - CD4D6AC91DBD1DA000643DBF /* PBXTargetDependency */, + 2DBC434720344314000F4558 /* PBXTargetDependency */, ); - name = simpleChatTests; - productName = simpleChatTests; - productReference = CD4D6AC71DBD1DA000643DBF /* simpleChatTests.xctest */; + name = ETHRadarTesting; + productName = ETHRadarTesting; + productReference = 2DBC434120344314000F4558 /* ETHRadarTesting.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; - CD4D6AD11DBD1DA000643DBF /* simpleChatUITests */ = { + CD4D6AB21DBD1DA000643DBF /* ETHRadar */ = { isa = PBXNativeTarget; - buildConfigurationList = CD4D6AE11DBD1DA100643DBF /* Build configuration list for PBXNativeTarget "simpleChatUITests" */; + buildConfigurationList = CD4D6ADB1DBD1DA100643DBF /* Build configuration list for PBXNativeTarget "ETHRadar" */; buildPhases = ( - CD4D6ACE1DBD1DA000643DBF /* Sources */, - CD4D6ACF1DBD1DA000643DBF /* Frameworks */, - CD4D6AD01DBD1DA000643DBF /* Resources */, + CD4D6AAF1DBD1DA000643DBF /* Sources */, + CD4D6AB01DBD1DA000643DBF /* Frameworks */, + CD4D6AB11DBD1DA000643DBF /* Resources */, ); buildRules = ( ); dependencies = ( - CD4D6AD41DBD1DA000643DBF /* PBXTargetDependency */, ); - name = simpleChatUITests; - productName = simpleChatUITests; - productReference = CD4D6AD21DBD1DA000643DBF /* simpleChatUITests.xctest */; - productType = "com.apple.product-type.bundle.ui-testing"; + name = ETHRadar; + productName = simpleChat; + productReference = CD4D6AB31DBD1DA000643DBF /* ETHRadar.app */; + productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ @@ -279,31 +257,24 @@ CD4D6AAB1DBD1DA000643DBF /* Project object */ = { isa = PBXProject; attributes = { - LastSwiftUpdateCheck = 0800; - LastUpgradeCheck = 0800; + LastSwiftUpdateCheck = 0920; + LastUpgradeCheck = 0920; ORGANIZATIONNAME = "Raimon Lapuente"; TargetAttributes = { - CD4D6AB21DBD1DA000643DBF = { - CreatedOnToolsVersion = 8.0; - DevelopmentTeam = 9SDMDTJ5TT; - LastSwiftMigration = 0800; - ProvisioningStyle = Automatic; - }; - CD4D6AC61DBD1DA000643DBF = { - CreatedOnToolsVersion = 8.0; - DevelopmentTeam = 9SDMDTJ5TT; + 2DBC434020344314000F4558 = { + CreatedOnToolsVersion = 9.2; ProvisioningStyle = Automatic; TestTargetID = CD4D6AB21DBD1DA000643DBF; }; - CD4D6AD11DBD1DA000643DBF = { + CD4D6AB21DBD1DA000643DBF = { CreatedOnToolsVersion = 8.0; DevelopmentTeam = 9SDMDTJ5TT; + LastSwiftMigration = 0920; ProvisioningStyle = Automatic; - TestTargetID = CD4D6AB21DBD1DA000643DBF; }; }; }; - buildConfigurationList = CD4D6AAE1DBD1DA000643DBF /* Build configuration list for PBXProject "simpleChat" */; + buildConfigurationList = CD4D6AAE1DBD1DA000643DBF /* Build configuration list for PBXProject "ETHRadar" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; @@ -316,98 +287,78 @@ projectDirPath = ""; projectRoot = ""; targets = ( - CD4D6AB21DBD1DA000643DBF /* simpleChat */, - CD4D6AC61DBD1DA000643DBF /* simpleChatTests */, - CD4D6AD11DBD1DA000643DBF /* simpleChatUITests */, + CD4D6AB21DBD1DA000643DBF /* ETHRadar */, + 2DBC434020344314000F4558 /* ETHRadarTesting */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ - CD4D6AB11DBD1DA000643DBF /* Resources */ = { + 2DBC433F20344314000F4558 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - CD955F2B1DC15E740032EE3D /* ChatTableViewCell.xib in Resources */, - CD4D6AC11DBD1DA000643DBF /* LaunchScreen.storyboard in Resources */, - CD4D6AEF1DBD1E0500643DBF /* ViewController.xib in Resources */, - CDAD44BD1DBD37FC0052BCC9 /* ChatController.xib in Resources */, - CD88EFA01DCA47C00023FD5F /* Assets.xcassets in Resources */, - CD88EF981DC729F70023FD5F /* MeChatTableViewCell.xib in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; - CD4D6AC51DBD1DA000643DBF /* Resources */ = { + CD4D6AB11DBD1DA000643DBF /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 2D83D9DB202AE81C0075EAAE /* ViewController.xib in Resources */, + CD955F2B1DC15E740032EE3D /* TokenCell.xib in Resources */, + CD4D6AC11DBD1DA000643DBF /* LaunchScreen.storyboard in Resources */, + 2DB3676D2025D64000427E3F /* Localizable.strings in Resources */, + CDAD44BD1DBD37FC0052BCC9 /* TokenController.xib in Resources */, + CD88EFA01DCA47C00023FD5F /* Assets.xcassets in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; - CD4D6AD01DBD1DA000643DBF /* Resources */ = { - isa = PBXResourcesBuildPhase; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 2DBC433D20344314000F4558 /* Sources */ = { + isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 2DBC434D2034431F000F4558 /* IntegrationStorageTests.swift in Sources */, + 2DBC434420344314000F4558 /* ETHRadarTesting.swift in Sources */, + 2DBC434C2034431C000F4558 /* ChatViewModelTests.swift in Sources */, + 2DBC434B20344319000F4558 /* DateHelpersTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ CD4D6AAF1DBD1DA000643DBF /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( CDAD44B91DBD24D30052BCC9 /* routingExtension.swift in Sources */, CD4D6AEE1DBD1E0500643DBF /* ViewController.swift in Sources */, - CD88EF9E1DCA412B0023FD5F /* UserCheck.swift in Sources */, CD4D6AEB1DBD1E0500643DBF /* keyboardExtension.swift in Sources */, + 2DAD101E2031FDDC00B553F2 /* TokenStorage.swift in Sources */, + 2DAD102420341C3F00B553F2 /* Coins.swift in Sources */, + 2DAD101A202C4C2100B553F2 /* Errors.swift in Sources */, CDAD44C81DC11B780052BCC9 /* Chat.swift in Sources */, - CD88EF961DC729E90023FD5F /* MeChatTableViewCell.swift in Sources */, - CD955F2D1DC16FFF0032EE3D /* imageLoader.swift in Sources */, + 2DAD1018202B70D600B553F2 /* Token.swift in Sources */, CD4D6AEC1DBD1E0500643DBF /* Router.swift in Sources */, - CD4D6AED1DBD1E0500643DBF /* userRepository.swift in Sources */, - CD88EF9A1DC9CE750023FD5F /* ChatViewModel.swift in Sources */, - CDAD44BB1DBD35FA0052BCC9 /* ChatController.swift in Sources */, + 2DAD101C2030E3C700B553F2 /* DoubleExtension.swift in Sources */, + CD88EF9A1DC9CE750023FD5F /* TokenCellViewModel.swift in Sources */, + CDAD44BB1DBD35FA0052BCC9 /* TokenController.swift in Sources */, CDAD44C31DBFFEF70052BCC9 /* DataRepository.swift in Sources */, CDCEC30B1DC1D7BE002B7549 /* DateHelper.swift in Sources */, - CD955F291DC15E600032EE3D /* ChatTableViewCell.swift in Sources */, + CD955F291DC15E600032EE3D /* TokenCell.swift in Sources */, CD4D6AEA1DBD1E0500643DBF /* AppDelegate.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - CD4D6AC31DBD1DA000643DBF /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - CD88EFA21DCA48EC0023FD5F /* UsernameValidatorTests.swift in Sources */, - CD4D6AF11DBD228D00643DBF /* userRepositoryIntegrationTests.swift in Sources */, - CD88EF9C1DCA3BE20023FD5F /* ChatTests.swift in Sources */, - CD88EFA41DCA628A0023FD5F /* ChatViewModelTests.swift in Sources */, - CDCEC30D1DC2B0E9002B7549 /* DateHelpersTests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - CD4D6ACE1DBD1DA000643DBF /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - CD4D6AD71DBD1DA000643DBF /* simpleChatUITests.swift in Sources */, + 2DAD1022203376CE00B553F2 /* MainViewModel.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ - CD4D6AC91DBD1DA000643DBF /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = CD4D6AB21DBD1DA000643DBF /* simpleChat */; - targetProxy = CD4D6AC81DBD1DA000643DBF /* PBXContainerItemProxy */; - }; - CD4D6AD41DBD1DA000643DBF /* PBXTargetDependency */ = { + 2DBC434720344314000F4558 /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = CD4D6AB21DBD1DA000643DBF /* simpleChat */; - targetProxy = CD4D6AD31DBD1DA000643DBF /* PBXContainerItemProxy */; + target = CD4D6AB21DBD1DA000643DBF /* ETHRadar */; + targetProxy = 2DBC434620344314000F4558 /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ @@ -423,6 +374,48 @@ /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ + 2DBC434920344314000F4558 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = ETHRadarTesting/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 11.2; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = mymoney.balance.ETHRadarTesting; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ETHRadar.app/ETHRadar"; + }; + name = Debug; + }; + 2DBC434A20344314000F4558 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_STYLE = Automatic; + GCC_C_LANGUAGE_STANDARD = gnu11; + INFOPLIST_FILE = ETHRadarTesting/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 11.2; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = mymoney.balance.ETHRadarTesting; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ETHRadar.app/ETHRadar"; + }; + name = Release; + }; CD4D6AD91DBD1DA100643DBF /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -432,7 +425,9 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; @@ -440,7 +435,12 @@ CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; @@ -469,6 +469,7 @@ SDKROOT = iphoneos; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; }; name = Debug; }; @@ -481,7 +482,9 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; @@ -489,7 +492,12 @@ CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; @@ -510,6 +518,7 @@ MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_VERSION = 3.0; VALIDATE_PRODUCT = YES; }; name = Release; @@ -519,11 +528,12 @@ buildSettings = { CLANG_ENABLE_MODULES = YES; DEVELOPMENT_TEAM = 9SDMDTJ5TT; - INFOPLIST_FILE = simpleChat/Info.plist; + INFOPLIST_FILE = "$(SRCROOT)/ETHRadar/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.raimonlapuente.simple.chat.simpleChat; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_SWIFT3_OBJC_INFERENCE = On; SWIFT_VERSION = 3.0; }; name = Debug; @@ -533,107 +543,41 @@ buildSettings = { CLANG_ENABLE_MODULES = YES; DEVELOPMENT_TEAM = 9SDMDTJ5TT; - INFOPLIST_FILE = simpleChat/Info.plist; + INFOPLIST_FILE = "$(SRCROOT)/ETHRadar/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.raimonlapuente.simple.chat.simpleChat; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_SWIFT3_OBJC_INFERENCE = On; SWIFT_VERSION = 3.0; }; name = Release; }; - CD4D6ADF1DBD1DA100643DBF /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - BUNDLE_LOADER = "$(TEST_HOST)"; - DEVELOPMENT_TEAM = 9SDMDTJ5TT; - INFOPLIST_FILE = simpleChatTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.raimonlapuente.simple.chat.simpleChatTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 3.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/simpleChat.app/simpleChat"; - }; - name = Debug; - }; - CD4D6AE01DBD1DA100643DBF /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - BUNDLE_LOADER = "$(TEST_HOST)"; - DEVELOPMENT_TEAM = 9SDMDTJ5TT; - INFOPLIST_FILE = simpleChatTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.raimonlapuente.simple.chat.simpleChatTests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 3.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/simpleChat.app/simpleChat"; - }; - name = Release; - }; - CD4D6AE21DBD1DA100643DBF /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - DEVELOPMENT_TEAM = 9SDMDTJ5TT; - INFOPLIST_FILE = simpleChatUITests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.raimonlapuente.simple.chat.simpleChatUITests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 3.0; - TEST_TARGET_NAME = simpleChat; - }; - name = Debug; - }; - CD4D6AE31DBD1DA100643DBF /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; - DEVELOPMENT_TEAM = 9SDMDTJ5TT; - INFOPLIST_FILE = simpleChatUITests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.raimonlapuente.simple.chat.simpleChatUITests; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 3.0; - TEST_TARGET_NAME = simpleChat; - }; - name = Release; - }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - CD4D6AAE1DBD1DA000643DBF /* Build configuration list for PBXProject "simpleChat" */ = { + 2DBC434820344314000F4558 /* Build configuration list for PBXNativeTarget "ETHRadarTesting" */ = { isa = XCConfigurationList; buildConfigurations = ( - CD4D6AD91DBD1DA100643DBF /* Debug */, - CD4D6ADA1DBD1DA100643DBF /* Release */, + 2DBC434920344314000F4558 /* Debug */, + 2DBC434A20344314000F4558 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - CD4D6ADB1DBD1DA100643DBF /* Build configuration list for PBXNativeTarget "simpleChat" */ = { + CD4D6AAE1DBD1DA000643DBF /* Build configuration list for PBXProject "ETHRadar" */ = { isa = XCConfigurationList; buildConfigurations = ( - CD4D6ADC1DBD1DA100643DBF /* Debug */, - CD4D6ADD1DBD1DA100643DBF /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - CD4D6ADE1DBD1DA100643DBF /* Build configuration list for PBXNativeTarget "simpleChatTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - CD4D6ADF1DBD1DA100643DBF /* Debug */, - CD4D6AE01DBD1DA100643DBF /* Release */, + CD4D6AD91DBD1DA100643DBF /* Debug */, + CD4D6ADA1DBD1DA100643DBF /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - CD4D6AE11DBD1DA100643DBF /* Build configuration list for PBXNativeTarget "simpleChatUITests" */ = { + CD4D6ADB1DBD1DA100643DBF /* Build configuration list for PBXNativeTarget "ETHRadar" */ = { isa = XCConfigurationList; buildConfigurations = ( - CD4D6AE21DBD1DA100643DBF /* Debug */, - CD4D6AE31DBD1DA100643DBF /* Release */, + CD4D6ADC1DBD1DA100643DBF /* Debug */, + CD4D6ADD1DBD1DA100643DBF /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; diff --git a/chatExample/ETHRadar.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/chatExample/ETHRadar.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..99b1535 --- /dev/null +++ b/chatExample/ETHRadar.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/chatExample/simpleChat.xcodeproj/xcshareddata/xcschemes/simpleChat.xcscheme b/chatExample/ETHRadar.xcodeproj/xcshareddata/xcschemes/ETHRadar.xcscheme similarity index 63% rename from chatExample/simpleChat.xcodeproj/xcshareddata/xcschemes/simpleChat.xcscheme rename to chatExample/ETHRadar.xcodeproj/xcshareddata/xcschemes/ETHRadar.xcscheme index c32c103..64bd006 100644 --- a/chatExample/simpleChat.xcodeproj/xcshareddata/xcschemes/simpleChat.xcscheme +++ b/chatExample/ETHRadar.xcodeproj/xcshareddata/xcschemes/ETHRadar.xcscheme @@ -1,6 +1,6 @@ + BuildableName = "ETHRadar.app" + BlueprintName = "ETHRadar" + ReferencedContainer = "container:ETHRadar.xcodeproj"> @@ -26,16 +26,17 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + language = "" shouldUseLaunchSchemeArgsEnv = "YES"> + BlueprintIdentifier = "2D5C0F9620342B5C002D5140" + BuildableName = "ETHRadarTests.xctest" + BlueprintName = "ETHRadarTests" + ReferencedContainer = "container:ETHRadar.xcodeproj"> + BuildableName = "ETHRadarUITests.xctest" + BlueprintName = "ETHRadarUITests" + ReferencedContainer = "container:ETHRadar.xcodeproj"> + + + + + + + + @@ -53,9 +74,9 @@ + BuildableName = "ETHRadar.app" + BlueprintName = "ETHRadar" + ReferencedContainer = "container:ETHRadar.xcodeproj"> @@ -65,6 +86,7 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + language = "" launchStyle = "0" useCustomWorkingDirectory = "NO" ignoresPersistentStateOnLaunch = "NO" @@ -76,9 +98,9 @@ + BuildableName = "ETHRadar.app" + BlueprintName = "ETHRadar" + ReferencedContainer = "container:ETHRadar.xcodeproj"> @@ -102,9 +124,9 @@ + BuildableName = "ETHRadar.app" + BlueprintName = "ETHRadar" + ReferencedContainer = "container:ETHRadar.xcodeproj"> diff --git a/chatExample/simpleChat/AppDelegate.swift b/chatExample/ETHRadar/AppDelegate.swift similarity index 100% rename from chatExample/simpleChat/AppDelegate.swift rename to chatExample/ETHRadar/AppDelegate.swift diff --git a/chatExample/simpleChat/Base.lproj/LaunchScreen.storyboard b/chatExample/ETHRadar/Base.lproj/LaunchScreen.storyboard similarity index 100% rename from chatExample/simpleChat/Base.lproj/LaunchScreen.storyboard rename to chatExample/ETHRadar/Base.lproj/LaunchScreen.storyboard diff --git a/chatExample/simpleChat/Chat.swift b/chatExample/ETHRadar/Chat.swift similarity index 100% rename from chatExample/simpleChat/Chat.swift rename to chatExample/ETHRadar/Chat.swift diff --git a/chatExample/ETHRadar/Coins.swift b/chatExample/ETHRadar/Coins.swift new file mode 100644 index 0000000..d39b1d6 --- /dev/null +++ b/chatExample/ETHRadar/Coins.swift @@ -0,0 +1,53 @@ +// +// Coins.swift +// ETHRadar +// +// Created by Raimon Lapuente Ferran on 14/02/2018. +// Copyright © 2018 Raimon Lapuente. All rights reserved. +// + +import Foundation + +// coins info + +enum Coins: String { + case GNT + case REP + case OMG + case ETH + + func fullName() -> String { + switch self { + case .GNT: return "Golem" + case .REP: return "Augur" + case .OMG: return "OmniseGo" + case .ETH: return "Ethereum" + } + } + + func address() -> String { + switch self { + case .GNT: return "0xa74476443119A942dE498590Fe1f2454d7D4aC0d" + case .REP: return "0xe94327d07fc17907b4db788e5adf2ed424addff6" + case .OMG: return "0xd26114cd6EE289AccF82350c8d8487fedB8A0C07" + case .ETH: return "0x082d3e0f04664b65127876e9A05e2183451c792a" + } + } + + func rateString() -> String { + return self.rawValue+"_"+"eth" + } + + func rateURL() -> String { + return "https://shapeshift.io/rate/\(self.rateString())" + } + + func tokenURL() -> String { + switch self { + case .ETH: + return "https://api.etherscan.io/api?module=account&action=balance&address=\(self.address())&tag=latest&apikey=\(DataRepository.EtherscanAPIKey)" + default: + return "https://api.etherscan.io/api?module=account&action=tokenbalance&contractaddress=\(self.address())&address=\(DataRepository.address)&tag=latest&apikey=\(DataRepository.EtherscanAPIKey)" + } + } +} diff --git a/chatExample/ETHRadar/DataRepository.swift b/chatExample/ETHRadar/DataRepository.swift new file mode 100644 index 0000000..fd42fc4 --- /dev/null +++ b/chatExample/ETHRadar/DataRepository.swift @@ -0,0 +1,141 @@ +// +// DataRepository.swift +// simpleChat +// +// Created by Raimon Lapuente on 25/10/2016. +// Copyright © 2016 Raimon Lapuente. All rights reserved. +// + +import Foundation + +protocol ETHRepository { + func getAllTokens() -> [Token] + func getETHBalance() -> Double + func getToken(position: NSInteger) -> Token + func allTokens() -> NSInteger + + func fetchAll() + var loading: Bool { get } + + func updateCall(block: @escaping updateBlock) +} + + +typealias updateBlock = () -> () + +// Show us your ability to interact with external apis. You’ll have to deal with multiple calls +//to fetch the required information. We would like to see how you’ll design that and what +//will be your strategy to handle bad networking (and offline device), caching and +//refreshing. + +class DataRepository: ETHRepository { + + static let address = "0x082d3e0f04664b65127876e9A05e2183451c792a" + static let EtherscanAPIKey = "E5QFXD7ZYRH7THQM5PIXB8JD4GY38SEJZ4" + + let storage: TokenStorage + var loading: Bool + private var updateBlock: updateBlock? + + init(storage: TokenStorage) { + self.storage = storage + self.loading = false + } + + // TODO - reque a request + fileprivate func fetch(url: String, parser: @escaping (_ result:[String:Any]) -> Void){ + let url = URL(string:url) + let request = NSMutableURLRequest(url:url!) + request.httpMethod = "GET" + + let task = URLSession.shared.dataTask(with: request as URLRequest) { (data, response, error) -> Void in + do { + if let httpResponse = response as? HTTPURLResponse { + if httpResponse.statusCode != 200 { + print("Something went wrong...") + } else { + guard let safeData = data else { + print("error") + return + } + if let json = try JSONSerialization.jsonObject(with: safeData, options: JSONSerialization.ReadingOptions()) as? [String:Any] { + parser(json) + } + else { + print("error, no json info") + } + } + } + } catch { + print("Something went wrong.. .2") + } + } + + task.resume() + } + + func fetchAll() { + for coin in allCoins() { + guard let enumCoin = Coins(rawValue: coin) else { + return + } + updateCoin(coin: enumCoin) + } + } + + //update coin on memory + func updateCoin(coin: Coins) { + let url = coin.tokenURL() + fetch(url: url) { (result) in + guard let numberOfTokens = result["result"] as? String else { + return + } + self.storage.update(token: coin.rawValue, value: Double(numberOfTokens)!.cryptoBalueToDecimals()) + self.getRate(coin: coin) + } + } + + func getRate(coin: Coins) { + let url = coin.rateURL() + fetch(url: url) { (result) in + guard let rate = result["rate"] as? String, let doubleRate = Double(rate) else { + return + } + self.storage.updateRate(token: coin.rawValue, rate: doubleRate) + self.updateBlock?() + } + } + + func allCoins() -> [String] { + return [Coins.GNT.rawValue, Coins.REP.rawValue, Coins.OMG.rawValue, Coins.ETH.rawValue] + } + func allTokens() -> [String] { + return [Coins.GNT.rawValue, Coins.REP.rawValue, Coins.OMG.rawValue] + } + + func updateCall(block: @escaping updateBlock) { + updateBlock = block + } + + //repository + + func getAllTokens() -> [Token] { + return self.storage.tokens.filter({$0.key != Coins.ETH.rawValue}).map({$0.value}) + } + + func allTokens() -> NSInteger { + return self.getAllTokens().count + } + + func getETHBalance() -> Double { + if let eth = self.storage.tokens[Coins.ETH.rawValue] { + return eth.amount + } else { + return 0 + } + } + + func getToken(position: NSInteger) -> Token { + return getAllTokens()[position] + } +} diff --git a/chatExample/simpleChat/DateHelper.swift b/chatExample/ETHRadar/DateHelper.swift similarity index 100% rename from chatExample/simpleChat/DateHelper.swift rename to chatExample/ETHRadar/DateHelper.swift diff --git a/chatExample/ETHRadar/DoubleExtension.swift b/chatExample/ETHRadar/DoubleExtension.swift new file mode 100644 index 0000000..2511579 --- /dev/null +++ b/chatExample/ETHRadar/DoubleExtension.swift @@ -0,0 +1,19 @@ +// +// DoubleExtension.swift +// ETHRadar +// +// Created by Raimon Lapuente Ferran on 11/02/2018. +// Copyright © 2018 Raimon Lapuente. All rights reserved. +// + +import Foundation + +extension Double { + func scientificToEightDecimals(decimals: Int) -> Double { + let decimal = self / pow(10.0, Double(decimals)) + return decimal + } + func cryptoBalueToDecimals() -> Double { + return scientificToEightDecimals(decimals: 18) + } +} diff --git a/chatExample/ETHRadar/Errors.swift b/chatExample/ETHRadar/Errors.swift new file mode 100644 index 0000000..161c367 --- /dev/null +++ b/chatExample/ETHRadar/Errors.swift @@ -0,0 +1,13 @@ +// +// Errors.swift +// ETHRadar +// +// Created by Raimon Lapuente Ferran on 08/02/2018. +// Copyright © 2018 Raimon Lapuente. All rights reserved. +// + +import Foundation + +enum ETHErrors: Error { + case JSONError +} diff --git a/chatExample/simpleChat/Info.plist b/chatExample/ETHRadar/Info.plist similarity index 100% rename from chatExample/simpleChat/Info.plist rename to chatExample/ETHRadar/Info.plist diff --git a/chatExample/ETHRadar/MainViewModel.swift b/chatExample/ETHRadar/MainViewModel.swift new file mode 100644 index 0000000..fadc6f7 --- /dev/null +++ b/chatExample/ETHRadar/MainViewModel.swift @@ -0,0 +1,86 @@ +// +// MainViewModel.swift +// ETHRadar +// +// Created by Raimon Lapuente Ferran on 13/02/2018. +// Copyright © 2018 Raimon Lapuente. All rights reserved. +// + +import Foundation + +enum State { + case loading + case empty + case done +} + +protocol MainProtocol { + var status: State { get } + func update() +} + +typealias ethBlock = (_ ethAmount: String) -> Void + +class MainViewModel: MainProtocol { + var status: State = .empty + let dataRepo: ETHRepository + private var ethBlock: ethBlock? + private var tokenBlock: ethBlock? + + init(repository: ETHRepository) { + dataRepo = repository + dataRepo.updateCall { + DispatchQueue.main.async { + self.refreshUI() + } + } + } + + func refreshUI() { + if dataRepo.allTokens() != 0 { + status = .loading + } + tokenBlock?(tokenInitialValue()) + ethBlock?(ethInitialValue()) + } + + func update() { + self.refreshUI() + dataRepo.fetchAll() + } + + func populateETH(block: @escaping (_ ethAmount: String) -> Void) { + ethBlock = block + } + + func populateTokens(block: @escaping (_ ethAmount: String) -> Void) { + tokenBlock = block + } + + func ethInitialValue() -> String { + if status == .empty { + return "0 ETH" + } else { + return ethValue() + } + } + + func ethValue() -> String { + return "\(dataRepo.getETHBalance()) ETH" + } + + func tokenInitialValue() -> String { + if status == .empty { + return "0 ETH" + } else { + return tokenValue() + } + } + + func tokenValue() -> String { + let total = dataRepo.getAllTokens().map({$0.amount*$0.rate}).reduce(0, +) + return "\(total) ETH" + } + + +} diff --git a/chatExample/ETHRadar/Router.swift b/chatExample/ETHRadar/Router.swift new file mode 100644 index 0000000..3bff3e9 --- /dev/null +++ b/chatExample/ETHRadar/Router.swift @@ -0,0 +1,60 @@ +// +// Router.swift +// chatExample +// +// Created by Raimon Lapuente on 22/10/2016. +// Copyright © 2016 Raimon Lapuente. All rights reserved. +// + +import Foundation +import UIKit + +enum InitError : Error { + case windowCantBeNil +} + +class Router { + let navigation : UINavigationController + let window : UIWindow + let dataRepo : ETHRepository + + init?(window: UIWindow?) { + guard let validWindow = window else { + return nil + } + let storage = TokenStorage.init(tokens:TokenStorage.loadData()) + self.dataRepo = DataRepository.init(storage: storage) + self.dataRepo.fetchAll() + + self.window = validWindow + self.navigation = UINavigationController.init(rootViewController: Router.createMain(dataRepo: self.dataRepo)) + } + + func setUp() { + self.window.rootViewController = navigation + self.window.makeKeyAndVisible() + } + + class func createMain(dataRepo : ETHRepository) -> ViewController { + let viewModel = MainViewModel.init(repository: dataRepo) + let login = ViewController.init(viewModel: viewModel) + return login + } + + class func createTokenController(repository: ETHRepository) -> TokenController { + let chatController = TokenController(repository: repository) + return chatController + } + + // -- Navigation Methods -- + + func openTokens(animated: Bool) { + let chatController = Router.createTokenController(repository: self.dataRepo) + self.navigation.pushViewController(chatController, animated: animated) + } + + func logout() { + self.navigation.isNavigationBarHidden = true + self.navigation.popViewController(animated: true) + } +} diff --git a/chatExample/ETHRadar/Token.swift b/chatExample/ETHRadar/Token.swift new file mode 100644 index 0000000..72b7e7d --- /dev/null +++ b/chatExample/ETHRadar/Token.swift @@ -0,0 +1,45 @@ +// +// Token.swift +// ETHRadar +// +// Created by Raimon Lapuente Ferran on 07/02/2018. +// Copyright © 2018 Raimon Lapuente. All rights reserved. +// + +import Foundation + +class Token: NSObject, NSCoding { + let name: String + let amount: Double + let rate: Double + + private static let encodernameKey = "nameStorage" + private static let encoderamountKey = "amountStorage" + private static let encoderethValueKey = "rateStorage" + + required init?(coder aDecoder: NSCoder) { + guard let name = aDecoder.decodeObject(forKey: Token.encodernameKey) as? String else { + print("something happened") + return nil + } + let amount = aDecoder.decodeDouble(forKey: Token.encoderamountKey) + let ethValue = aDecoder.decodeDouble(forKey: Token.encoderethValueKey) + self.name = name + self.amount = Double(amount) + self.rate = ethValue + } + + func encode(with aCoder: NSCoder) { + aCoder.encode(name, forKey: Token.encodernameKey) + aCoder.encode(amount, forKey: Token.encoderamountKey) + aCoder.encode(rate, forKey: Token.encoderethValueKey) + } + + init(amount: Double, name: String, rate: Double) { + self.name = name + self.amount = amount + self.rate = rate + } + + +} diff --git a/chatExample/ETHRadar/TokenCell.swift b/chatExample/ETHRadar/TokenCell.swift new file mode 100644 index 0000000..2f5dd04 --- /dev/null +++ b/chatExample/ETHRadar/TokenCell.swift @@ -0,0 +1,38 @@ +// +// ChatTableViewCell.swift +// simpleChat +// +// Created by Raimon Lapuente on 26/10/2016. +// Copyright © 2016 Raimon Lapuente. All rights reserved. +// + +import Foundation +import UIKit + +class Cell : UITableViewCell { + func configWith(viewModel:TokenCellViewModel) {} +} + +class TokenCell: Cell { + + @IBOutlet weak var tokenName: UILabel! + @IBOutlet weak var tokenAmount: UILabel! + @IBOutlet weak var tokenValue: UILabel! + @IBOutlet weak var backgroundRound: UIView! + + override func prepareForReuse() { + tokenName.text = "" + tokenAmount.text = "" + tokenValue.text = "" + } + + override func awakeFromNib() { + backgroundRound.layer.cornerRadius = 10.0 + } + + override func configWith(viewModel:TokenCellViewModel) { + tokenValue.text = viewModel.tokenEthValue + tokenName.text = viewModel.tokenName + tokenAmount.text = viewModel.tokenAmount + } +} diff --git a/chatExample/ETHRadar/TokenCell.xib b/chatExample/ETHRadar/TokenCell.xib new file mode 100644 index 0000000..001d05f --- /dev/null +++ b/chatExample/ETHRadar/TokenCell.xib @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/chatExample/ETHRadar/TokenCellViewModel.swift b/chatExample/ETHRadar/TokenCellViewModel.swift new file mode 100644 index 0000000..d7c5fd1 --- /dev/null +++ b/chatExample/ETHRadar/TokenCellViewModel.swift @@ -0,0 +1,29 @@ +// +// ChatViewModel.swift +// simpleChat +// +// Created by Raimon Lapuente on 02/11/2016. +// Copyright © 2016 Raimon Lapuente. All rights reserved. +// + +import Foundation + +class TokenCellViewModel { + + let tokenAmount: String + let tokenName: String + let tokenEthValue: String + + private let token: Token + + init(token: Token) { + self.token = token + if let coin: Coins = Coins(rawValue:self.token.name) { + self.tokenName = "\(coin.fullName())(\(self.token.name))" + } else { + self.tokenName = "(\(self.token.name))" + } + self.tokenAmount = "\(self.token.amount)" + self.tokenEthValue = "\(self.token.amount * self.token.rate) ETH" + } +} diff --git a/chatExample/ETHRadar/TokenController.swift b/chatExample/ETHRadar/TokenController.swift new file mode 100644 index 0000000..5e65348 --- /dev/null +++ b/chatExample/ETHRadar/TokenController.swift @@ -0,0 +1,66 @@ + +// +// chatController.swift +// simpleChat +// +// Created by Raimon Lapuente on 23/10/2016. +// Copyright © 2016 Raimon Lapuente. All rights reserved. +// + +import Foundation +import UIKit + +class TokenController: UIViewController, UITableViewDelegate, UITableViewDataSource, UITextFieldDelegate { + + @IBOutlet weak var table: UITableView! + + let repository: ETHRepository + + init(repository: ETHRepository) { + self.repository = repository + super.init(nibName: nil, bundle: nil) + } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func viewDidLoad() { + super.viewDidLoad() + + title = NSLocalizedString("Token.Title", comment: "") + + configureTable() + registerForKeyboard() + + navigationController?.isNavigationBarHidden = false + + } + + func configureTable() { + table.rowHeight = UITableViewAutomaticDimension + table.estimatedRowHeight = 45 + let nib : UINib = UINib(nibName: "TokenCell", bundle: nil) + table.register(nib, forCellReuseIdentifier: "TokenCell") + } + + // -- Collection Delegates -- + + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return 1 + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let token = self.repository.getToken(position: indexPath.section) + let viewModel = TokenCellViewModel.init(token:token) + var cell : TokenCell + cell = tableView.dequeueReusableCell(withIdentifier: "TokenCell", for: indexPath) as! TokenCell + cell.configWith(viewModel: viewModel) + return cell + } + + + func numberOfSections(in tableView: UITableView) -> Int { + return self.repository.allTokens() + } +} diff --git a/chatExample/ETHRadar/TokenController.xib b/chatExample/ETHRadar/TokenController.xib new file mode 100644 index 0000000..b6c5aff --- /dev/null +++ b/chatExample/ETHRadar/TokenController.xib @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/chatExample/ETHRadar/TokenStorage.swift b/chatExample/ETHRadar/TokenStorage.swift new file mode 100644 index 0000000..bfc0cef --- /dev/null +++ b/chatExample/ETHRadar/TokenStorage.swift @@ -0,0 +1,87 @@ +// +// DataStorage.swift +// ETHRadar +// +// Created by Raimon Lapuente Ferran on 12/02/2018. +// Copyright © 2018 Raimon Lapuente. All rights reserved. +// + +import Foundation + +class TokenStorage: NSObject, NSCoding { + + private static let encoderKey = "tokenStorage" + + required init?(coder aDecoder: NSCoder) { + if let decodedTokens = aDecoder.decodeObject(forKey: TokenStorage.encoderKey) as? [String:Token] { + self.internalTokens = decodedTokens + } + } + + func encode(with aCoder: NSCoder) { + aCoder.encode(self.internalTokens, forKey: TokenStorage.encoderKey) + } + + fileprivate var internalTokens = [String:Token]() + + init(tokens:[String:Token]?) { + if let safeTokens = tokens { + self.internalTokens = safeTokens + } else { + self.internalTokens = [String:Token]() + } + } + + var tokens: [String:Token] { + get { + return internalTokens + } + set { + internalTokens = tokens + } + } + + func update(token: String, value: Double) { + if let oldToken = internalTokens[token] { + let newToken = Token.init(amount: value, name: oldToken.name, rate: oldToken.rate) + self.internalTokens[token] = newToken + } else { + let newToken = Token.init(amount: value, name: token, rate: 0) + self.internalTokens[token] = newToken + } + saveData() + } + + func updateRate(token: String, rate: Double) { + if let oldToken = internalTokens[token] { + let newToken = Token.init(amount: oldToken.amount, name: oldToken.name, rate: rate) + self.internalTokens[token] = newToken + } else { + print("there should be a token") + } + saveData() + } + +} + +extension TokenStorage { + func saveData() { + let result = NSKeyedArchiver.archiveRootObject(self.internalTokens, toFile: StorageHelper.getFilePath()) + } + + class func loadData() -> [String:Token]? { + if let loadedData = NSKeyedUnarchiver.unarchiveObject(withFile: StorageHelper.getFilePath()) as? [String:Token] { + return loadedData + } + return nil + } +} + +class StorageHelper { + static func getFilePath() -> String { + let file = FileManager() + let url = file.urls(for: .documentDirectory, in: .userDomainMask).first! + let path = url.appendingPathComponent("tokens").path + return path + } +} diff --git a/chatExample/ETHRadar/ViewController.swift b/chatExample/ETHRadar/ViewController.swift new file mode 100644 index 0000000..326cf3f --- /dev/null +++ b/chatExample/ETHRadar/ViewController.swift @@ -0,0 +1,66 @@ +// +// ViewController.swift +// chatExample +// +// Created by Raimon Lapuente on 22/10/2016. +// Copyright © 2016 Raimon Lapuente. All rights reserved. +// + +import UIKit + + + +class ViewController: UIViewController, keyboardAnimations, UITextFieldDelegate { + + @IBOutlet weak var ETHLabel: UILabel! + @IBOutlet weak var TokenLabel: UILabel! + @IBOutlet weak var viewTokensButton: UIButton! + + let viewModel: MainViewModel + + init(viewModel: MainViewModel) { + self.viewModel = viewModel + super.init(nibName: nil, bundle: nil) + + self.viewModel.populateETH { (eth) in + self.ETHLabel.text = eth + } + self.viewModel.populateTokens { (tokenEth) in + self.TokenLabel.text = tokenEth + } + } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func viewDidLoad() { + super.viewDidLoad() + } + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + self.navigationController?.isNavigationBarHidden = true + self.registerForKeyboard() + + self.viewModel.update() + } + override func viewWillDisappear(_ animated: Bool) { + super.viewWillDisappear(animated) + self.deregisterKeyboard() + } + + @IBAction func viewMoreTapped(_ sender: Any) { + self.showTokens() + } + + func textFieldShouldReturn(_ textField: UITextField) -> Bool { + return true + } + + func animateKeyboardChange(height: Float) { + UIView.animate(withDuration: 0.2, animations: { + self.view.layoutIfNeeded() + }) + } +} + diff --git a/chatExample/ETHRadar/ViewController.xib b/chatExample/ETHRadar/ViewController.xib new file mode 100644 index 0000000..311e9a7 --- /dev/null +++ b/chatExample/ETHRadar/ViewController.xib @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/chatExample/ETHRadar/en.lproj/ViewController.strings b/chatExample/ETHRadar/en.lproj/ViewController.strings new file mode 100644 index 0000000..a4a5321 --- /dev/null +++ b/chatExample/ETHRadar/en.lproj/ViewController.strings @@ -0,0 +1,3 @@ + +/* Class = "UILabel"; text = "Label"; ObjectID = "7DT-aN-zme"; */ +"7DT-aN-zme.text" = "Label"; diff --git a/chatExample/simpleChat/keyboardExtension.swift b/chatExample/ETHRadar/keyboardExtension.swift similarity index 93% rename from chatExample/simpleChat/keyboardExtension.swift rename to chatExample/ETHRadar/keyboardExtension.swift index 2e10c8d..d3aa5f2 100644 --- a/chatExample/simpleChat/keyboardExtension.swift +++ b/chatExample/ETHRadar/keyboardExtension.swift @@ -31,7 +31,7 @@ extension UIViewController : keyboardRegistration { notificationCenter.removeObserver(self, name: NSNotification.Name.UIKeyboardWillHide, object: nil) } - func keyboardWillShow(notification: NSNotification) { + @objc func keyboardWillShow(notification: NSNotification) { if let controller = self as? keyboardAnimations { if let info = notification.userInfo { let keyboardFrame : CGRect = (info[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue @@ -41,7 +41,7 @@ extension UIViewController : keyboardRegistration { } } - func keyboardWillHide(notification: NSNotification) { + @objc func keyboardWillHide(notification: NSNotification) { if let controller = self as? keyboardAnimations { if let info = notification.userInfo { let keyboardFrame : CGRect = (info[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue diff --git a/chatExample/simpleChat/routingExtension.swift b/chatExample/ETHRadar/routingExtension.swift similarity index 74% rename from chatExample/simpleChat/routingExtension.swift rename to chatExample/ETHRadar/routingExtension.swift index d337e25..85946e4 100644 --- a/chatExample/simpleChat/routingExtension.swift +++ b/chatExample/ETHRadar/routingExtension.swift @@ -10,15 +10,15 @@ import Foundation import UIKit protocol transferUser { - func finisWithUsername(username: String) + func showTokens() } extension ViewController: transferUser { - func finisWithUsername(username: String) { + func showTokens() { let app = UIApplication.shared.delegate as! AppDelegate if let router = app.router { - router.loginFinishedWithUser(username: username, animated: true) + router.openTokens(animated: true) } } } @@ -27,7 +27,7 @@ protocol logoutUser { func userlogout() } -extension ChatController: logoutUser { +extension TokenController: logoutUser { func userlogout() { let app = UIApplication.shared.delegate as! AppDelegate if let router = app.router { diff --git a/chatExample/ETHRadarTest/ETHRadarTest.swift b/chatExample/ETHRadarTest/ETHRadarTest.swift new file mode 100644 index 0000000..baff4e3 --- /dev/null +++ b/chatExample/ETHRadarTest/ETHRadarTest.swift @@ -0,0 +1,35 @@ +// +// ETHRadarTest.swift +// ETHRadarTest +// +// Created by Raimon Lapuente Ferran on 14/02/2018. +// Copyright © 2018 Raimon Lapuente. All rights reserved. +// + +import XCTest + +class ETHRadarTest: 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. + } + } + +} diff --git a/chatExample/simpleChatUITests/Info.plist b/chatExample/ETHRadarTest/Info.plist similarity index 94% rename from chatExample/simpleChatUITests/Info.plist rename to chatExample/ETHRadarTest/Info.plist index 6c6c23c..6c40a6c 100644 --- a/chatExample/simpleChatUITests/Info.plist +++ b/chatExample/ETHRadarTest/Info.plist @@ -3,7 +3,7 @@ CFBundleDevelopmentRegion - en + $(DEVELOPMENT_LANGUAGE) CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier diff --git a/chatExample/ETHRadarTesting/ETHRadarTesting.swift b/chatExample/ETHRadarTesting/ETHRadarTesting.swift new file mode 100644 index 0000000..f933e63 --- /dev/null +++ b/chatExample/ETHRadarTesting/ETHRadarTesting.swift @@ -0,0 +1,35 @@ +// +// ETHRadarTesting.swift +// ETHRadarTesting +// +// Created by Raimon Lapuente Ferran on 14/02/2018. +// Copyright © 2018 Raimon Lapuente. All rights reserved. +// + +import XCTest + +class ETHRadarTesting: 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. + } + } + +} diff --git a/chatExample/ETHRadarTesting/Info.plist b/chatExample/ETHRadarTesting/Info.plist new file mode 100644 index 0000000..6c40a6c --- /dev/null +++ b/chatExample/ETHRadarTesting/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/chatExample/simpleChatTests/ChatTests.swift b/chatExample/ETHRadarTests/ChatTests.swift similarity index 97% rename from chatExample/simpleChatTests/ChatTests.swift rename to chatExample/ETHRadarTests/ChatTests.swift index 1f79165..c4ad93e 100644 --- a/chatExample/simpleChatTests/ChatTests.swift +++ b/chatExample/ETHRadarTests/ChatTests.swift @@ -7,7 +7,7 @@ // import XCTest -@testable import simpleChat +@testable import ETHRadar class ChatTests: XCTestCase { diff --git a/chatExample/ETHRadarTests/ChatViewModelTests.swift b/chatExample/ETHRadarTests/ChatViewModelTests.swift new file mode 100644 index 0000000..93c257a --- /dev/null +++ b/chatExample/ETHRadarTests/ChatViewModelTests.swift @@ -0,0 +1,46 @@ +// +// ChatViewModelTests.swift +// simpleChat +// +// Created by Raimon Lapuente on 02/11/2016. +// Copyright © 2016 Raimon Lapuente. All rights reserved. +// + +import XCTest +@testable import ETHRadar + +class TokenViewModelTests: 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 testChatViewModelShowsCorrectCoinName() { + //given + let token = Token(amount: 2456.0, name: "GNT", rate: 0.345) + let tokenViewModel = TokenCellViewModel.init(token: token) + + //then + XCTAssertEqual(tokenViewModel.tokenAmount, "2456.0") + XCTAssertEqual(tokenViewModel.tokenName, "Golem(GNT)") + XCTAssertEqual(tokenViewModel.tokenEthValue, "847.32 ETH") + } + + func testChatViewModelShowsUnknownCoinName() { + //given + let token = Token(amount: 2456.0, name: "REF", rate: 0.345) + let tokenViewModel = TokenCellViewModel.init(token: token) + + //then + XCTAssertEqual(tokenViewModel.tokenAmount, "2456.0") + XCTAssertEqual(tokenViewModel.tokenName, "(REF)") + XCTAssertEqual(tokenViewModel.tokenEthValue, "847.32 ETH") + } + +} diff --git a/chatExample/simpleChatTests/DateHelpersTests.swift b/chatExample/ETHRadarTests/DateHelpersTests.swift similarity index 97% rename from chatExample/simpleChatTests/DateHelpersTests.swift rename to chatExample/ETHRadarTests/DateHelpersTests.swift index 4d0b2ae..b8a8cd6 100644 --- a/chatExample/simpleChatTests/DateHelpersTests.swift +++ b/chatExample/ETHRadarTests/DateHelpersTests.swift @@ -7,7 +7,7 @@ // import XCTest -@testable import simpleChat +@testable import ETHRadar class DateHelpersTests: XCTestCase { diff --git a/chatExample/simpleChatTests/Info.plist b/chatExample/ETHRadarTests/Info.plist similarity index 100% rename from chatExample/simpleChatTests/Info.plist rename to chatExample/ETHRadarTests/Info.plist diff --git a/chatExample/ETHRadarTests/IntegrationStorageTests.swift b/chatExample/ETHRadarTests/IntegrationStorageTests.swift new file mode 100644 index 0000000..c91557f --- /dev/null +++ b/chatExample/ETHRadarTests/IntegrationStorageTests.swift @@ -0,0 +1,61 @@ +// +// IntegrationStorageTests.swift +// ETHRadarTests +// +// Created by Raimon Lapuente Ferran on 12/02/2018. +// Copyright © 2018 Raimon Lapuente. All rights reserved. +// + +import Foundation +import XCTest + +@testable import ETHRadar + +class IntegrationStorageTests: XCTestCase { + + override func tearDown() { + TestHelper.cleanTokens() + super.tearDown() + } + + func testStorgeIsEmpty() { + //given + let storage = TokenStorage.loadData() + + //then + XCTAssertNil(storage, "Storaget should be nil") + } + + func testStorageWhenNotEmpty() { + //given + let token = Token.init(amount: 2.52, name: "aToken", rate: 0.25) + let oneToken = TokenStorage.init(tokens: [token.name:token]) + oneToken.saveData() + + //when + let readData = TokenStorage.loadData() + + //then + XCTAssertEqual(readData?.count, 1) + } + + func testRetrivalKeepsDataStructure() { + //given + let token = Token.init(amount: 2.52, name: "aToken", rate: 0.25) + let oneToken = TokenStorage.init(tokens: [token.name:token]) + oneToken.saveData() + + //when + let readData = TokenStorage.loadData() + + //then + XCTAssertNotNil(readData?["aToken"]) + } +} + +class TestHelper { + class func cleanTokens () { + let fileManager = FileManager.default + try? fileManager.removeItem(atPath: StorageHelper.getFilePath()) + } +} diff --git a/chatExample/Localizable.strings b/chatExample/Localizable.strings new file mode 100644 index 0000000..f9ec6d4 --- /dev/null +++ b/chatExample/Localizable.strings @@ -0,0 +1,10 @@ +/* + Localizable.strings + ETHRadar + + Created by Raimon Lapuente Ferran on 03/02/2018. + Copyright © 2018 Raimon Lapuente. All rights reserved. +*/ + +"Token.Title" = "ERC-20 Tokens"; + diff --git a/chatExample/simpleChat.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/chatExample/simpleChat.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 463f3e2..0000000 --- a/chatExample/simpleChat.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/chatExample/simpleChat/ChatController.swift b/chatExample/simpleChat/ChatController.swift deleted file mode 100644 index 2164e62..0000000 --- a/chatExample/simpleChat/ChatController.swift +++ /dev/null @@ -1,135 +0,0 @@ - -// -// chatController.swift -// simpleChat -// -// Created by Raimon Lapuente on 23/10/2016. -// Copyright © 2016 Raimon Lapuente. All rights reserved. -// - -import Foundation -import UIKit - -class ChatController: UIViewController, UITableViewDelegate, UITableViewDataSource, keyboardAnimations, UITextFieldDelegate { - - @IBOutlet weak var table: UITableView! - @IBOutlet weak var chatBox: UITextField! - @IBOutlet weak var chatContainer: UIView! - @IBOutlet weak var sendButton: UIButton! - - @IBOutlet weak var bottomSpaceToChatBox: NSLayoutConstraint! - - let username: String - let repository: chatRepository - - init(username: String, repository: chatRepository) { - self.username = username - self.repository = repository - super.init(nibName: nil, bundle: nil) - } - - required init?(coder aDecoder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - override func viewDidLoad() { - super.viewDidLoad() - - self.title = ("Chat - " + username) - - self.hideBackButton() - self.addLogoutButton() - self.configureTable() - self.registerForKeyboard() - self.configureTextBox() - - self.navigationController?.isNavigationBarHidden = false - - } - - func configureTextBox() { - self.chatBox.layer.cornerRadius = 5.0 - } - - func configureTable() { - self.table.rowHeight = UITableViewAutomaticDimension - self.table.estimatedRowHeight = 120 - var nib : UINib = UINib(nibName: "ChatTableViewCell", bundle: nil) - self.table.register(nib, forCellReuseIdentifier: "ChatTableViewCell") - nib = UINib(nibName: "MeChatTableViewCell", bundle: nil) - self.table.register(nib, forCellReuseIdentifier: "MeChatTableViewCell") - - } - - func hideBackButton() { - self.navigationItem.hidesBackButton = true - } - - func addLogoutButton() { - let logoutImage = UIImage(named: "logout") - let logoutButton = UIBarButtonItem(image: logoutImage, style: .plain, target: self, action: #selector(logoutPressed)) - self.navigationItem.rightBarButtonItem = logoutButton - } - - func logoutPressed() { - self.deregisterKeyboard() - self.userlogout() - } - - @IBAction func sendPressed(_ sender: AnyObject) { - self.chatBox.resignFirstResponder() - if let text = self.chatBox.text, text != "" { - self.addChat(text:text) - self.table.reloadData() - - //do on becomefirstresponder - let lastElement = self.repository.totalChats() - 1 - let indexPath = IndexPath(item: 0, section: lastElement) - self.table.scrollToRow(at: indexPath, at: UITableViewScrollPosition.bottom, animated: true) - } - self.chatBox.text = "" - } - - func animateKeyboardChange(height: Float) { - self.bottomSpaceToChatBox.constant += CGFloat(height) - UIView.animate(withDuration: 0.2, animations: { - self.view.layoutIfNeeded() - }) - } - - func textFieldShouldReturn(_ textField: UITextField) -> Bool { - if let text = textField.text, text == "" { - return false - } - return true - } - - func addChat(text: String) { - self.repository.addChat(user: self.username, text: text) - } - - // -- Collection Delegates -- - - func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return 1 - } - - func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let chat = self.repository.getChatAt(position: indexPath.section) - let viewModel = ChatViewModel.init(chat: chat,username:self.username) - var cell : conversationCell - if viewModel.me { - cell = tableView.dequeueReusableCell(withIdentifier: "MeChatTableViewCell", for: indexPath) as! MeChatTableViewCell - cell.configWith(viewModel:viewModel) - } else { - cell = tableView.dequeueReusableCell(withIdentifier: "ChatTableViewCell", for: indexPath) as! ChatTableViewCell - cell.configWith(viewModel: viewModel) - } - return cell - } - - - func numberOfSections(in tableView: UITableView) -> Int { - return self.repository.totalChats() - } -} diff --git a/chatExample/simpleChat/ChatController.xib b/chatExample/simpleChat/ChatController.xib deleted file mode 100644 index be41127..0000000 --- a/chatExample/simpleChat/ChatController.xib +++ /dev/null @@ -1,86 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/chatExample/simpleChat/ChatTableViewCell.swift b/chatExample/simpleChat/ChatTableViewCell.swift deleted file mode 100644 index dc89a24..0000000 --- a/chatExample/simpleChat/ChatTableViewCell.swift +++ /dev/null @@ -1,41 +0,0 @@ -// -// ChatTableViewCell.swift -// simpleChat -// -// Created by Raimon Lapuente on 26/10/2016. -// Copyright © 2016 Raimon Lapuente. All rights reserved. -// - -import Foundation -import UIKit - -class conversationCell : UITableViewCell { - func configWith(viewModel:ChatViewModel) {} -} - -class ChatTableViewCell: conversationCell { - - @IBOutlet weak var conversationText: UILabel! - @IBOutlet weak var userImage: UIImageView! - @IBOutlet weak var time: UILabel! - @IBOutlet weak var backgroundRound: UIView! - - override func prepareForReuse() { - time.text = "" - conversationText.text = "" - userImage.image = nil - userImage.isHidden = true - } - - override func awakeFromNib() { - self.backgroundRound.layer.cornerRadius = 10.0 - } - - override func configWith(viewModel:ChatViewModel) { - self.conversationText.text = viewModel.conversation - self.time.text = viewModel.time - if let image = viewModel.logo { - self.userImage.downloadFrom(link: image) - } - } -} diff --git a/chatExample/simpleChat/ChatTableViewCell.xib b/chatExample/simpleChat/ChatTableViewCell.xib deleted file mode 100644 index 46ab2ae..0000000 --- a/chatExample/simpleChat/ChatTableViewCell.xib +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/chatExample/simpleChat/ChatViewModel.swift b/chatExample/simpleChat/ChatViewModel.swift deleted file mode 100644 index 2515d4d..0000000 --- a/chatExample/simpleChat/ChatViewModel.swift +++ /dev/null @@ -1,31 +0,0 @@ -// -// ChatViewModel.swift -// simpleChat -// -// Created by Raimon Lapuente on 02/11/2016. -// Copyright © 2016 Raimon Lapuente. All rights reserved. -// - -import Foundation - -class ChatViewModel { - - let username : String - let time : String - let conversation : String - let logo : URL? - let me : Bool - - init(chat: Chat, username: String) { - self.me = (chat.username == username) - self.username = chat.username - if !me { - self.time = "\(chat.username) - \(chat.time)" - } else { - self.time = "\(chat.time)" - - } - self.conversation = chat.content - self.logo = chat.userImageURL - } -} diff --git a/chatExample/simpleChat/DataRepository.swift b/chatExample/simpleChat/DataRepository.swift deleted file mode 100644 index 5995d58..0000000 --- a/chatExample/simpleChat/DataRepository.swift +++ /dev/null @@ -1,84 +0,0 @@ -// -// DataRepository.swift -// simpleChat -// -// Created by Raimon Lapuente on 25/10/2016. -// Copyright © 2016 Raimon Lapuente. All rights reserved. -// - -import Foundation - -protocol chatRepository { - func getAllChats() -> Array - func totalChats() -> NSInteger - func getChatAt(position: NSInteger) -> Chat - func addChat(user: String, text: String) -} - -protocol userValidator { - func totalChattedUsers() -> [String] -} - -class DataRepository: chatRepository, userValidator { - - var chats: Array = [Chat]() - - func fetch(){ - let url = URL(string:"https://s3-eu-west-1.amazonaws.com/rocket-interview/chat.json") - let request = NSMutableURLRequest(url:url!) - request.httpMethod = "GET" - - let task = URLSession.shared.dataTask(with: request as URLRequest) { (data, response, error) -> Void in - do { - if let httpResponse = response as? HTTPURLResponse { - if httpResponse.statusCode != 200 { - print("Something went wrong...") - } else { - - let json = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions()) as? [String:[Any]] - if let Dictionary = json?["chats"] { - for chatDictionary in Dictionary { - if let chatObject = chatDictionary as? [String:Any] { - if let chat = Chat.initWithJson(json: chatObject) { - self.chats.append(chat) - } - } - } - } - } - } - } catch { - print("Something went wrong...") - } - } - - task.resume() - } - - func getAllChats() -> Array { - return self.chats - } - - func totalChats() -> NSInteger { - return self.chats.count - } - - func getChatAt(position: NSInteger) -> Chat { - return self.chats[position] - } - - func totalChattedUsers() -> [String] { - var contacts : [String] = [String]() - for contact in self.chats { - contacts.append(contact.username) - } - return contacts - } - - func addChat(user: String, text: String) { - let date = Date() - let time = DateHelper.getHourTime(date: date) - let chat = Chat(username: user, content: text, userImage: nil, time: time) - self.chats.append(chat) - } -} diff --git a/chatExample/simpleChat/MeChatTableViewCell.swift b/chatExample/simpleChat/MeChatTableViewCell.swift deleted file mode 100644 index 3997eb8..0000000 --- a/chatExample/simpleChat/MeChatTableViewCell.swift +++ /dev/null @@ -1,32 +0,0 @@ -// -// MeChatTableViewCell.swift -// simpleChat -// -// Created by Raimon Lapuente on 31/10/2016. -// Copyright © 2016 Raimon Lapuente. All rights reserved. -// - -import Foundation -import UIKit - -class MeChatTableViewCell: conversationCell { - - @IBOutlet weak var conversationText: UILabel! - @IBOutlet weak var time: UILabel! - @IBOutlet weak var backgroundRound: UIView! - - override func prepareForReuse() { - time.text = "" - conversationText.text = "" - } - - override func awakeFromNib() { - self.backgroundRound.layer.cornerRadius = 10.0 - } - - override func configWith(viewModel:ChatViewModel) { - self.conversationText.text = viewModel.conversation - self.time.text = viewModel.time - } -} - diff --git a/chatExample/simpleChat/MeChatTableViewCell.xib b/chatExample/simpleChat/MeChatTableViewCell.xib deleted file mode 100644 index 76317f3..0000000 --- a/chatExample/simpleChat/MeChatTableViewCell.xib +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/chatExample/simpleChat/Router.swift b/chatExample/simpleChat/Router.swift deleted file mode 100644 index 2423cd8..0000000 --- a/chatExample/simpleChat/Router.swift +++ /dev/null @@ -1,77 +0,0 @@ -// -// Router.swift -// chatExample -// -// Created by Raimon Lapuente on 22/10/2016. -// Copyright © 2016 Raimon Lapuente. All rights reserved. -// - -import Foundation -import UIKit - -enum InitError : Error { - case windowCantBeNil -} - -class Router { - let navigation : UINavigationController - let window : UIWindow - let userRepo : userStorage - let dataRepo : DataRepository - let userCheck : UserCheck - - init?(window: UIWindow?) { - guard let validWindow = window else { - return nil - } - self.userRepo = userRepository() - self.dataRepo = DataRepository() - self.dataRepo.fetch() - self.userCheck = UserCheck.init(userList: self.dataRepo) - - self.window = validWindow - let (hasSession, username) = Router.hasStoredSession(userRepo: self.userRepo) - self.navigation = UINavigationController.init(rootViewController: Router.createLogin(userRepo: self.userRepo, userCheck: self.userCheck)) - if hasSession { - self.loginFinishedWithUser(username: username!, animated: false) - } - } - - func setUp() { - self.window.rootViewController = navigation - self.window.makeKeyAndVisible() - } - - class func createLogin(userRepo : userStorage, userCheck: UserCheck) -> ViewController { - let login = ViewController(userVaildator:userCheck) - return login - } - - class func createChatController(username: String, repository: chatRepository) -> ChatController { - let chatController = ChatController(username: username, repository: repository) - return chatController - } - - // -- Session methods -- - - class func hasStoredSession(userRepo: userStorage) -> (Bool,String?) { - if let user = userRepo.getSavedUser() { - return (true, user) - } - return (false, nil) - } - - // -- Navigation Methods -- - - func loginFinishedWithUser(username: String, animated: Bool) { - self.userRepo.saveUser(username: username) - let chatController = Router.createChatController(username: username, repository: self.dataRepo) - self.navigation.pushViewController(chatController, animated: animated) - } - - func logout() { - self.userRepo.removeUser() - self.navigation.isNavigationBarHidden = true - self.navigation.popViewController(animated: true) - } -} diff --git a/chatExample/simpleChat/UserCheck.swift b/chatExample/simpleChat/UserCheck.swift deleted file mode 100644 index 7a31ea6..0000000 --- a/chatExample/simpleChat/UserCheck.swift +++ /dev/null @@ -1,28 +0,0 @@ -// -// UserCheck.swift -// simpleChat -// -// Created by Raimon Lapuente on 02/11/2016. -// Copyright © 2016 Raimon Lapuente. All rights reserved. -// - -import Foundation - -class UserCheck { - - let userList: userValidator - - init(userList: userValidator) { - self.userList = userList - } - - private func checkUserExists(username: String) -> Bool { - let usernameList = self.userList.totalChattedUsers - return usernameList().contains(username) - } - - //Note: validate user should really return an enum with the exact error to be able to display to user, we are making it simpler - func validUser(username: String) -> Bool { - return username != "" && !self.checkUserExists(username: username) - } -} diff --git a/chatExample/simpleChat/ViewController.swift b/chatExample/simpleChat/ViewController.swift deleted file mode 100644 index f740f7f..0000000 --- a/chatExample/simpleChat/ViewController.swift +++ /dev/null @@ -1,67 +0,0 @@ -// -// ViewController.swift -// chatExample -// -// Created by Raimon Lapuente on 22/10/2016. -// Copyright © 2016 Raimon Lapuente. All rights reserved. -// - -import UIKit - - - -class ViewController: UIViewController, keyboardAnimations, UITextFieldDelegate { - - @IBOutlet weak var bottomDistance: NSLayoutConstraint! - @IBOutlet weak var usernameField: UITextField! - @IBOutlet weak var loginButton: UIButton! - @IBOutlet weak var messageImage: UIImageView! - - let userCheck: UserCheck - - init(userVaildator: UserCheck) { - self.userCheck = userVaildator - super.init(nibName: nil, bundle: nil) - } - - required init?(coder aDecoder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - override func viewDidLoad() { - super.viewDidLoad() - - self.loginButton.layer.cornerRadius = 5.0 - self.usernameField.layer.cornerRadius = 5.0 - - self.registerForKeyboard() - - self.navigationController?.isNavigationBarHidden = true - } - - @IBAction func loginButtonPressed(_ sender: AnyObject) { - self.usernameField.resignFirstResponder() - if let username = usernameField.text, self.userCheck.validUser(username: username) { - self.finisWithUsername(username: username) - } else { - //alert user - usernameField.text = "" - usernameField.placeholder = "Please use different username" - } - } - - func textFieldShouldReturn(_ textField: UITextField) -> Bool { - self.usernameField.resignFirstResponder() - return true - } - - func animateKeyboardChange(height: Float) { - if self.bottomDistance.constant < 0 && height > 0 { return } - - self.bottomDistance.constant -= CGFloat(height) - UIView.animate(withDuration: 0.2, animations: { - self.view.layoutIfNeeded() - }) - } -} - diff --git a/chatExample/simpleChat/ViewController.xib b/chatExample/simpleChat/ViewController.xib deleted file mode 100644 index d747b0d..0000000 --- a/chatExample/simpleChat/ViewController.xib +++ /dev/null @@ -1,82 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/chatExample/simpleChat/imageLoader.swift b/chatExample/simpleChat/imageLoader.swift deleted file mode 100644 index 903af62..0000000 --- a/chatExample/simpleChat/imageLoader.swift +++ /dev/null @@ -1,41 +0,0 @@ -// -// imageLoader.swift -// simpleChat -// -// Created by Raimon Lapuente on 27/10/2016. -// Copyright © 2016 Raimon Lapuente. All rights reserved. -// - -import Foundation -import UIKit - -extension UIImageView -{ - func downloadFrom(link:URL) - { - URLSession.shared.dataTask(with: link as URL, completionHandler: { (data, _, error) -> Void in - guard let data = data , error == nil else { - self.isHidden = true - self.layoutSubviews() - return - } - DispatchQueue.main.async() { () -> Void in - if let image = UIImage(data: data) { - self.isHidden = false - self.configureImageView() - self.image = image - } else { - self.isHidden = true - } - self.layoutSubviews() - } - }).resume() - } - - func configureImageView() { - self.layer.cornerRadius = 20.0 - self.layer.borderWidth = 2.0 - self.layer.borderColor = UIColor.white.cgColor - self.clipsToBounds = true - } -} diff --git a/chatExample/simpleChat/userRepository.swift b/chatExample/simpleChat/userRepository.swift deleted file mode 100644 index c570f28..0000000 --- a/chatExample/simpleChat/userRepository.swift +++ /dev/null @@ -1,35 +0,0 @@ -// -// userRepository.swift -// chatExample -// -// Created by Raimon Lapuente on 23/10/2016. -// Copyright © 2016 Raimon Lapuente. All rights reserved. -// - -import Foundation - -protocol userStorage { - func saveUser(username: String) - func removeUser() - func getSavedUser() -> String? -} - -class userRepository : userStorage { - - let storage = UserDefaults.init() - private static let userKey = "chat.Example.User" - - func saveUser(username: String) { - storage.set(username, forKey: userRepository.userKey) - storage.synchronize() - } - - func removeUser() { - storage.set(nil, forKey: userRepository.userKey) - storage.synchronize() - } - - func getSavedUser() -> String? { - return storage.string(forKey: userRepository.userKey) - } -} diff --git a/chatExample/simpleChatTests/ChatViewModelTests.swift b/chatExample/simpleChatTests/ChatViewModelTests.swift deleted file mode 100644 index cdf9baa..0000000 --- a/chatExample/simpleChatTests/ChatViewModelTests.swift +++ /dev/null @@ -1,44 +0,0 @@ -// -// ChatViewModelTests.swift -// simpleChat -// -// Created by Raimon Lapuente on 02/11/2016. -// Copyright © 2016 Raimon Lapuente. All rights reserved. -// - -import XCTest -@testable import simpleChat - -class ChatViewModelTests: 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 testChatViewModelShowsTimeAsUserAndTimeWhenNotmainUser() { - //given - let chat = Chat(username: "user1", content: "random content", userImage: "RandomString", time: "12:43") - let chatViewModel = ChatViewModel.init(chat: chat, username: "Olivia") - - //then - XCTAssertEqual(chatViewModel.time, "user1 - 12:43") - XCTAssertFalse(chatViewModel.me) - } - - func testChatViewModelShowsTimeOnlyWhenUserIsMe() { - //given - let chat = Chat(username: "user1", content: "random content", userImage: "RandomString", time: "12:43") - let chatViewModel = ChatViewModel.init(chat: chat, username: "user1") - - //then - XCTAssertEqual(chatViewModel.time, "12:43") - XCTAssertTrue(chatViewModel.me) - } - -} diff --git a/chatExample/simpleChatTests/UsernameValidatorTests.swift b/chatExample/simpleChatTests/UsernameValidatorTests.swift deleted file mode 100644 index 0cf7642..0000000 --- a/chatExample/simpleChatTests/UsernameValidatorTests.swift +++ /dev/null @@ -1,57 +0,0 @@ -// -// UsernameValidatorTests.swift -// simpleChat -// -// Created by Raimon Lapuente on 02/11/2016. -// Copyright © 2016 Raimon Lapuente. All rights reserved. -// - -import XCTest -@testable import simpleChat - -class UserValidatorStub: userValidator { - func totalChattedUsers() -> [String] { - return ["Morgan","Chris","Jhon","Julie","Marso","Joanna","Phil","Garfield"] - } -} - -class UsernameValidatorTests: XCTestCase { - - var userListStub : userValidator? - var userValidator : UserCheck? - - override func setUp() { - super.setUp() - userListStub = UserValidatorStub() - userValidator = UserCheck.init(userList: self.userListStub!) - } - - override func tearDown() { - // Put teardown code here. This method is called after the invocation of each test method in the class. - super.tearDown() - } - - func testUserIsValid() { - // given - let username = "Raimon" - - //then - XCTAssertTrue((self.userValidator?.validUser(username: username))!) - } - - func testExistingUserIsNotValid() { - // given - let username = "Morgan" - - //then - XCTAssertFalse((self.userValidator?.validUser(username: username))!) - } - - func testEmptyStringUserIsNotValid() { - // given - let username = "" - - //then - XCTAssertFalse((self.userValidator?.validUser(username: username))!) - } -} diff --git a/chatExample/simpleChatTests/userRepositoryIntegrationTests.swift b/chatExample/simpleChatTests/userRepositoryIntegrationTests.swift deleted file mode 100644 index 0b4c5aa..0000000 --- a/chatExample/simpleChatTests/userRepositoryIntegrationTests.swift +++ /dev/null @@ -1,59 +0,0 @@ -// -// userRepositoryTests.swift -// chatExample -// -// Created by Raimon Lapuente on 23/10/2016. -// Copyright © 2016 Raimon Lapuente. All rights reserved. -// - -import XCTest -@testable import simpleChat - -class userRepositoryIntegrationTests: XCTestCase { - - private static let userKey = "chat.Example.User" - - let userRepo = userRepository() - - override func setUp() { - super.setUp() - userRepo.removeUser() - } - - override func tearDown() { - userRepo.removeUser() - super.tearDown() - } - - func testUserSaveReturnsSavedUser() { - //given - let user = "Michael" - - //when - userRepo.saveUser(username: user) - - //then - XCTAssertEqual(userRepo.getSavedUser(), "Michael") - } - - func testGetUserWhenNoUserReturnsNil() { - //given - let user = userRepo.getSavedUser() - - //then - XCTAssertNil(user) - } - - func testUserDeletion() { - //given - let user = "Tony" - userRepo.saveUser(username: user) - - //when - userRepo.removeUser() - - //then - XCTAssertNil(userRepo.getSavedUser()) - } - -} diff --git a/chatExample/simpleChatUITests/simpleChatUITests.swift b/chatExample/simpleChatUITests/simpleChatUITests.swift deleted file mode 100644 index 7fa5ced..0000000 --- a/chatExample/simpleChatUITests/simpleChatUITests.swift +++ /dev/null @@ -1,103 +0,0 @@ -// -// simpleChatUITests.swift -// simpleChatUITests -// -// Created by Raimon Lapuente on 23/10/2016. -// Copyright © 2016 Raimon Lapuente. All rights reserved. -// - -import XCTest -import Foundation - -class simpleChatUITests: XCTestCase { - - override func setUp() { - super.setUp() - - let storage = UserDefaults.init() - let userKey = "chat.Example.User" - storage.set(nil, forKey: userKey) - storage.synchronize() - - // Put setup code here. This method is called before the invocation of each test method in the class. - - // In UI tests it is usually best to stop immediately when a failure occurs. - continueAfterFailure = true - // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. - XCUIApplication().launch() - } - - override func tearDown() { - super.tearDown() - } - - func testUserCantBeNilOnLogin() { - - let app = XCUIApplication() - app.buttons["LOGIN"].tap() - XCTAssertNotNil(app.textFields["Please use different username"]) - - } - - func testUsernameCantBeOneOfTheExistingOnBackend() { - - let app = XCUIApplication() - let firstNameLastNameTextField = app.textFields["First Name & Last Name"] - firstNameLastNameTextField.tap() - firstNameLastNameTextField.typeText("Olivia") - app.buttons["LOGIN"].tap() - XCTAssertNotNil(app.textFields["Please use different username"]) - } - - func testUsernameValidMovesToNextScreen() { - - let app = XCUIApplication() - let firstNameLastNameTextField = app.textFields["First Name & Last Name"] - firstNameLastNameTextField.tap() - firstNameLastNameTextField.typeText("Rai") - app.buttons["LOGIN"].tap() - XCTAssertNotNil(XCUIApplication().navigationBars["Chat - Rai"]) - self.logout() - - } - - func testTypingAndSendingMessageDisplaysOnConversation() { - - let app = XCUIApplication() - let firstNameLastNameTextField = app.textFields["First Name & Last Name"] - firstNameLastNameTextField.tap() - firstNameLastNameTextField.typeText("Rai") - app.buttons["LOGIN"].tap() - - let typeSomethingTextField = app.textFields["Type something"] - typeSomethingTextField.tap() - typeSomethingTextField.typeText("hello all") - app.buttons["SEND"].tap() - XCTAssertNotNil(app.tables.staticTexts["hello all"]) - self.logout() - - } - - func testLogoutReturnsToFirstScreen() { - - self.login() - - let app = XCUIApplication() - app.navigationBars["Chat - Rai"].buttons["logout"].tap() - XCTAssertNotNil(app.staticTexts["Type your name"]) - - } - - func login() { - let app = XCUIApplication() - let firstNameLastNameTextField = app.textFields["First Name & Last Name"] - firstNameLastNameTextField.tap() - firstNameLastNameTextField.typeText("Rai") - app.buttons["LOGIN"].tap() - } - - func logout() { - let app = XCUIApplication() - app.navigationBars["Chat - Rai"].buttons["logout"].tap() - } -}