From 7dda45068caa4e90547844c3795d20189ed3c8bd Mon Sep 17 00:00:00 2001 From: Ananth Jk Date: Wed, 19 Jan 2022 21:45:21 +0000 Subject: [PATCH 1/9] Initial Commit --- MovieSearch.xcodeproj/project.pbxproj | 584 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcschemes/xcschememanagement.plist | 14 + .../AccentColor.colorset/Contents.json | 11 + .../AppIcon.appiconset/Contents.json | 98 +++ MovieSearch/Assets.xcassets/Contents.json | 6 + MovieSearch/ContentView.swift | 21 + MovieSearch/MovieSearchApp.swift | 17 + .../Preview Assets.xcassets/Contents.json | 6 + MovieSearchTests/MovieSearchTests.swift | 36 ++ MovieSearchUITests/MovieSearchUITests.swift | 42 ++ .../MovieSearchUITestsLaunchTests.swift | 32 + 13 files changed, 882 insertions(+) create mode 100644 MovieSearch.xcodeproj/project.pbxproj create mode 100644 MovieSearch.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 MovieSearch.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 MovieSearch.xcodeproj/xcuserdata/ananthjk.xcuserdatad/xcschemes/xcschememanagement.plist create mode 100644 MovieSearch/Assets.xcassets/AccentColor.colorset/Contents.json create mode 100644 MovieSearch/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 MovieSearch/Assets.xcassets/Contents.json create mode 100644 MovieSearch/ContentView.swift create mode 100644 MovieSearch/MovieSearchApp.swift create mode 100644 MovieSearch/Preview Content/Preview Assets.xcassets/Contents.json create mode 100644 MovieSearchTests/MovieSearchTests.swift create mode 100644 MovieSearchUITests/MovieSearchUITests.swift create mode 100644 MovieSearchUITests/MovieSearchUITestsLaunchTests.swift diff --git a/MovieSearch.xcodeproj/project.pbxproj b/MovieSearch.xcodeproj/project.pbxproj new file mode 100644 index 0000000..5ac9359 --- /dev/null +++ b/MovieSearch.xcodeproj/project.pbxproj @@ -0,0 +1,584 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 55; + objects = { + +/* Begin PBXBuildFile section */ + 0AF34D1D2798BDEE009F97E4 /* MovieSearchApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AF34D1C2798BDEE009F97E4 /* MovieSearchApp.swift */; }; + 0AF34D1F2798BDEE009F97E4 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AF34D1E2798BDEE009F97E4 /* ContentView.swift */; }; + 0AF34D212798BDEF009F97E4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0AF34D202798BDEF009F97E4 /* Assets.xcassets */; }; + 0AF34D242798BDEF009F97E4 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0AF34D232798BDEF009F97E4 /* Preview Assets.xcassets */; }; + 0AF34D2E2798BDEF009F97E4 /* MovieSearchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AF34D2D2798BDEF009F97E4 /* MovieSearchTests.swift */; }; + 0AF34D382798BDEF009F97E4 /* MovieSearchUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AF34D372798BDEF009F97E4 /* MovieSearchUITests.swift */; }; + 0AF34D3A2798BDEF009F97E4 /* MovieSearchUITestsLaunchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AF34D392798BDEF009F97E4 /* MovieSearchUITestsLaunchTests.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 0AF34D2A2798BDEF009F97E4 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 0AF34D112798BDEE009F97E4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 0AF34D182798BDEE009F97E4; + remoteInfo = MovieSearch; + }; + 0AF34D342798BDEF009F97E4 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 0AF34D112798BDEE009F97E4 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 0AF34D182798BDEE009F97E4; + remoteInfo = MovieSearch; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 0AF34D192798BDEE009F97E4 /* MovieSearch.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MovieSearch.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 0AF34D1C2798BDEE009F97E4 /* MovieSearchApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MovieSearchApp.swift; sourceTree = ""; }; + 0AF34D1E2798BDEE009F97E4 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; + 0AF34D202798BDEF009F97E4 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 0AF34D232798BDEF009F97E4 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; + 0AF34D292798BDEF009F97E4 /* MovieSearchTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MovieSearchTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 0AF34D2D2798BDEF009F97E4 /* MovieSearchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MovieSearchTests.swift; sourceTree = ""; }; + 0AF34D332798BDEF009F97E4 /* MovieSearchUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MovieSearchUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 0AF34D372798BDEF009F97E4 /* MovieSearchUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MovieSearchUITests.swift; sourceTree = ""; }; + 0AF34D392798BDEF009F97E4 /* MovieSearchUITestsLaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MovieSearchUITestsLaunchTests.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 0AF34D162798BDEE009F97E4 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0AF34D262798BDEF009F97E4 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0AF34D302798BDEF009F97E4 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 0AF34D102798BDEE009F97E4 = { + isa = PBXGroup; + children = ( + 0AF34D1B2798BDEE009F97E4 /* MovieSearch */, + 0AF34D2C2798BDEF009F97E4 /* MovieSearchTests */, + 0AF34D362798BDEF009F97E4 /* MovieSearchUITests */, + 0AF34D1A2798BDEE009F97E4 /* Products */, + ); + sourceTree = ""; + }; + 0AF34D1A2798BDEE009F97E4 /* Products */ = { + isa = PBXGroup; + children = ( + 0AF34D192798BDEE009F97E4 /* MovieSearch.app */, + 0AF34D292798BDEF009F97E4 /* MovieSearchTests.xctest */, + 0AF34D332798BDEF009F97E4 /* MovieSearchUITests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 0AF34D1B2798BDEE009F97E4 /* MovieSearch */ = { + isa = PBXGroup; + children = ( + 0AF34D1C2798BDEE009F97E4 /* MovieSearchApp.swift */, + 0AF34D1E2798BDEE009F97E4 /* ContentView.swift */, + 0AF34D202798BDEF009F97E4 /* Assets.xcassets */, + 0AF34D222798BDEF009F97E4 /* Preview Content */, + ); + path = MovieSearch; + sourceTree = ""; + }; + 0AF34D222798BDEF009F97E4 /* Preview Content */ = { + isa = PBXGroup; + children = ( + 0AF34D232798BDEF009F97E4 /* Preview Assets.xcassets */, + ); + path = "Preview Content"; + sourceTree = ""; + }; + 0AF34D2C2798BDEF009F97E4 /* MovieSearchTests */ = { + isa = PBXGroup; + children = ( + 0AF34D2D2798BDEF009F97E4 /* MovieSearchTests.swift */, + ); + path = MovieSearchTests; + sourceTree = ""; + }; + 0AF34D362798BDEF009F97E4 /* MovieSearchUITests */ = { + isa = PBXGroup; + children = ( + 0AF34D372798BDEF009F97E4 /* MovieSearchUITests.swift */, + 0AF34D392798BDEF009F97E4 /* MovieSearchUITestsLaunchTests.swift */, + ); + path = MovieSearchUITests; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 0AF34D182798BDEE009F97E4 /* MovieSearch */ = { + isa = PBXNativeTarget; + buildConfigurationList = 0AF34D3D2798BDEF009F97E4 /* Build configuration list for PBXNativeTarget "MovieSearch" */; + buildPhases = ( + 0AF34D152798BDEE009F97E4 /* Sources */, + 0AF34D162798BDEE009F97E4 /* Frameworks */, + 0AF34D172798BDEE009F97E4 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = MovieSearch; + productName = MovieSearch; + productReference = 0AF34D192798BDEE009F97E4 /* MovieSearch.app */; + productType = "com.apple.product-type.application"; + }; + 0AF34D282798BDEF009F97E4 /* MovieSearchTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 0AF34D402798BDEF009F97E4 /* Build configuration list for PBXNativeTarget "MovieSearchTests" */; + buildPhases = ( + 0AF34D252798BDEF009F97E4 /* Sources */, + 0AF34D262798BDEF009F97E4 /* Frameworks */, + 0AF34D272798BDEF009F97E4 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 0AF34D2B2798BDEF009F97E4 /* PBXTargetDependency */, + ); + name = MovieSearchTests; + productName = MovieSearchTests; + productReference = 0AF34D292798BDEF009F97E4 /* MovieSearchTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 0AF34D322798BDEF009F97E4 /* MovieSearchUITests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 0AF34D432798BDEF009F97E4 /* Build configuration list for PBXNativeTarget "MovieSearchUITests" */; + buildPhases = ( + 0AF34D2F2798BDEF009F97E4 /* Sources */, + 0AF34D302798BDEF009F97E4 /* Frameworks */, + 0AF34D312798BDEF009F97E4 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 0AF34D352798BDEF009F97E4 /* PBXTargetDependency */, + ); + name = MovieSearchUITests; + productName = MovieSearchUITests; + productReference = 0AF34D332798BDEF009F97E4 /* MovieSearchUITests.xctest */; + productType = "com.apple.product-type.bundle.ui-testing"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 0AF34D112798BDEE009F97E4 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastSwiftUpdateCheck = 1320; + LastUpgradeCheck = 1320; + TargetAttributes = { + 0AF34D182798BDEE009F97E4 = { + CreatedOnToolsVersion = 13.2.1; + }; + 0AF34D282798BDEF009F97E4 = { + CreatedOnToolsVersion = 13.2.1; + TestTargetID = 0AF34D182798BDEE009F97E4; + }; + 0AF34D322798BDEF009F97E4 = { + CreatedOnToolsVersion = 13.2.1; + TestTargetID = 0AF34D182798BDEE009F97E4; + }; + }; + }; + buildConfigurationList = 0AF34D142798BDEE009F97E4 /* Build configuration list for PBXProject "MovieSearch" */; + compatibilityVersion = "Xcode 13.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 0AF34D102798BDEE009F97E4; + productRefGroup = 0AF34D1A2798BDEE009F97E4 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 0AF34D182798BDEE009F97E4 /* MovieSearch */, + 0AF34D282798BDEF009F97E4 /* MovieSearchTests */, + 0AF34D322798BDEF009F97E4 /* MovieSearchUITests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 0AF34D172798BDEE009F97E4 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 0AF34D242798BDEF009F97E4 /* Preview Assets.xcassets in Resources */, + 0AF34D212798BDEF009F97E4 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0AF34D272798BDEF009F97E4 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0AF34D312798BDEF009F97E4 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 0AF34D152798BDEE009F97E4 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 0AF34D1F2798BDEE009F97E4 /* ContentView.swift in Sources */, + 0AF34D1D2798BDEE009F97E4 /* MovieSearchApp.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0AF34D252798BDEF009F97E4 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 0AF34D2E2798BDEF009F97E4 /* MovieSearchTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0AF34D2F2798BDEF009F97E4 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 0AF34D382798BDEF009F97E4 /* MovieSearchUITests.swift in Sources */, + 0AF34D3A2798BDEF009F97E4 /* MovieSearchUITestsLaunchTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 0AF34D2B2798BDEF009F97E4 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 0AF34D182798BDEE009F97E4 /* MovieSearch */; + targetProxy = 0AF34D2A2798BDEF009F97E4 /* PBXContainerItemProxy */; + }; + 0AF34D352798BDEF009F97E4 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 0AF34D182798BDEE009F97E4 /* MovieSearch */; + targetProxy = 0AF34D342798BDEF009F97E4 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 0AF34D3B2798BDEF009F97E4 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + 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_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 15.2; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 0AF34D3C2798BDEF009F97E4 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + 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_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 15.2; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 0AF34D3E2798BDEF009F97E4 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = "\"MovieSearch/Preview Content\""; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchScreen_Generation = YES; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.ananth.moviesearch.MovieSearch; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 0AF34D3F2798BDEF009F97E4 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = "\"MovieSearch/Preview Content\""; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchScreen_Generation = YES; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.ananth.moviesearch.MovieSearch; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + 0AF34D412798BDEF009F97E4 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 15.2; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.ananth.moviesearch.MovieSearchTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/MovieSearch.app/MovieSearch"; + }; + name = Debug; + }; + 0AF34D422798BDEF009F97E4 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 15.2; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.ananth.moviesearch.MovieSearchTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/MovieSearch.app/MovieSearch"; + }; + name = Release; + }; + 0AF34D442798BDEF009F97E4 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.ananth.moviesearch.MovieSearchUITests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_TARGET_NAME = MovieSearch; + }; + name = Debug; + }; + 0AF34D452798BDEF009F97E4 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.ananth.moviesearch.MovieSearchUITests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_TARGET_NAME = MovieSearch; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 0AF34D142798BDEE009F97E4 /* Build configuration list for PBXProject "MovieSearch" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0AF34D3B2798BDEF009F97E4 /* Debug */, + 0AF34D3C2798BDEF009F97E4 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 0AF34D3D2798BDEF009F97E4 /* Build configuration list for PBXNativeTarget "MovieSearch" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0AF34D3E2798BDEF009F97E4 /* Debug */, + 0AF34D3F2798BDEF009F97E4 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 0AF34D402798BDEF009F97E4 /* Build configuration list for PBXNativeTarget "MovieSearchTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0AF34D412798BDEF009F97E4 /* Debug */, + 0AF34D422798BDEF009F97E4 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 0AF34D432798BDEF009F97E4 /* Build configuration list for PBXNativeTarget "MovieSearchUITests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0AF34D442798BDEF009F97E4 /* Debug */, + 0AF34D452798BDEF009F97E4 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 0AF34D112798BDEE009F97E4 /* Project object */; +} diff --git a/MovieSearch.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/MovieSearch.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/MovieSearch.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/MovieSearch.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/MovieSearch.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/MovieSearch.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/MovieSearch.xcodeproj/xcuserdata/ananthjk.xcuserdatad/xcschemes/xcschememanagement.plist b/MovieSearch.xcodeproj/xcuserdata/ananthjk.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..a64e6a1 --- /dev/null +++ b/MovieSearch.xcodeproj/xcuserdata/ananthjk.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,14 @@ + + + + + SchemeUserState + + MovieSearch.xcscheme_^#shared#^_ + + orderHint + 0 + + + + diff --git a/MovieSearch/Assets.xcassets/AccentColor.colorset/Contents.json b/MovieSearch/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 0000000..eb87897 --- /dev/null +++ b/MovieSearch/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MovieSearch/Assets.xcassets/AppIcon.appiconset/Contents.json b/MovieSearch/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..9221b9b --- /dev/null +++ b/MovieSearch/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,98 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "20x20" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "20x20" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "29x29" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "29x29" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "40x40" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "40x40" + }, + { + "idiom" : "iphone", + "scale" : "2x", + "size" : "60x60" + }, + { + "idiom" : "iphone", + "scale" : "3x", + "size" : "60x60" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "20x20" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "20x20" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "29x29" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "29x29" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "40x40" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "40x40" + }, + { + "idiom" : "ipad", + "scale" : "1x", + "size" : "76x76" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "76x76" + }, + { + "idiom" : "ipad", + "scale" : "2x", + "size" : "83.5x83.5" + }, + { + "idiom" : "ios-marketing", + "scale" : "1x", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MovieSearch/Assets.xcassets/Contents.json b/MovieSearch/Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/MovieSearch/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MovieSearch/ContentView.swift b/MovieSearch/ContentView.swift new file mode 100644 index 0000000..0595ed9 --- /dev/null +++ b/MovieSearch/ContentView.swift @@ -0,0 +1,21 @@ +// +// ContentView.swift +// MovieSearch +// +// Created by Ananth Jk on 19/01/2022. +// + +import SwiftUI + +struct ContentView: View { + var body: some View { + Text("Hello, world!") + .padding() + } +} + +struct ContentView_Previews: PreviewProvider { + static var previews: some View { + ContentView() + } +} diff --git a/MovieSearch/MovieSearchApp.swift b/MovieSearch/MovieSearchApp.swift new file mode 100644 index 0000000..230f57a --- /dev/null +++ b/MovieSearch/MovieSearchApp.swift @@ -0,0 +1,17 @@ +// +// MovieSearchApp.swift +// MovieSearch +// +// Created by Ananth Jk on 19/01/2022. +// + +import SwiftUI + +@main +struct MovieSearchApp: App { + var body: some Scene { + WindowGroup { + ContentView() + } + } +} diff --git a/MovieSearch/Preview Content/Preview Assets.xcassets/Contents.json b/MovieSearch/Preview Content/Preview Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/MovieSearch/Preview Content/Preview Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MovieSearchTests/MovieSearchTests.swift b/MovieSearchTests/MovieSearchTests.swift new file mode 100644 index 0000000..527471f --- /dev/null +++ b/MovieSearchTests/MovieSearchTests.swift @@ -0,0 +1,36 @@ +// +// MovieSearchTests.swift +// MovieSearchTests +// +// Created by Ananth Jk on 19/01/2022. +// + +import XCTest +@testable import MovieSearch + +class MovieSearchTests: XCTestCase { + + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + func testExample() throws { + // This is an example of a functional test case. + // Use XCTAssert and related functions to verify your tests produce the correct results. + // Any test you write for XCTest can be annotated as throws and async. + // Mark your test throws to produce an unexpected failure when your test encounters an uncaught error. + // Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards. + } + + func testPerformanceExample() throws { + // 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/MovieSearchUITests/MovieSearchUITests.swift b/MovieSearchUITests/MovieSearchUITests.swift new file mode 100644 index 0000000..676d4d7 --- /dev/null +++ b/MovieSearchUITests/MovieSearchUITests.swift @@ -0,0 +1,42 @@ +// +// MovieSearchUITests.swift +// MovieSearchUITests +// +// Created by Ananth Jk on 19/01/2022. +// + +import XCTest + +class MovieSearchUITests: XCTestCase { + + override func setUpWithError() throws { + // 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 = false + + // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + func testExample() throws { + // UI tests must launch the application that they test. + let app = XCUIApplication() + app.launch() + + // Use recording to get started writing UI tests. + // Use XCTAssert and related functions to verify your tests produce the correct results. + } + + func testLaunchPerformance() throws { + if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 7.0, *) { + // This measures how long it takes to launch your application. + measure(metrics: [XCTApplicationLaunchMetric()]) { + XCUIApplication().launch() + } + } + } +} diff --git a/MovieSearchUITests/MovieSearchUITestsLaunchTests.swift b/MovieSearchUITests/MovieSearchUITestsLaunchTests.swift new file mode 100644 index 0000000..5e13242 --- /dev/null +++ b/MovieSearchUITests/MovieSearchUITestsLaunchTests.swift @@ -0,0 +1,32 @@ +// +// MovieSearchUITestsLaunchTests.swift +// MovieSearchUITests +// +// Created by Ananth Jk on 19/01/2022. +// + +import XCTest + +class MovieSearchUITestsLaunchTests: XCTestCase { + + override class var runsForEachTargetApplicationUIConfiguration: Bool { + true + } + + override func setUpWithError() throws { + continueAfterFailure = false + } + + func testLaunch() throws { + let app = XCUIApplication() + app.launch() + + // Insert steps here to perform after app launch but before taking a screenshot, + // such as logging into a test account or navigating somewhere in the app + + let attachment = XCTAttachment(screenshot: app.screenshot()) + attachment.name = "Launch Screen" + attachment.lifetime = .keepAlways + add(attachment) + } +} From 975fce1853b491a9d072a6526f0467c213144664 Mon Sep 17 00:00:00 2001 From: Ananth Jk Date: Wed, 19 Jan 2022 22:07:54 +0000 Subject: [PATCH 2/9] RemoteTest: Created API Manager --- MovieSearch.xcodeproj/project.pbxproj | 20 +++++++ MovieSearch/APIManager/APIManager.swift | 72 +++++++++++++++++++++++++ MovieSearch/APIManager/Request.swift | 24 +++++++++ MovieSearchTests/APITest.swift | 19 +++++++ 4 files changed, 135 insertions(+) create mode 100644 MovieSearch/APIManager/APIManager.swift create mode 100644 MovieSearch/APIManager/Request.swift create mode 100644 MovieSearchTests/APITest.swift diff --git a/MovieSearch.xcodeproj/project.pbxproj b/MovieSearch.xcodeproj/project.pbxproj index 5ac9359..0704157 100644 --- a/MovieSearch.xcodeproj/project.pbxproj +++ b/MovieSearch.xcodeproj/project.pbxproj @@ -14,6 +14,9 @@ 0AF34D2E2798BDEF009F97E4 /* MovieSearchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AF34D2D2798BDEF009F97E4 /* MovieSearchTests.swift */; }; 0AF34D382798BDEF009F97E4 /* MovieSearchUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AF34D372798BDEF009F97E4 /* MovieSearchUITests.swift */; }; 0AF34D3A2798BDEF009F97E4 /* MovieSearchUITestsLaunchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AF34D392798BDEF009F97E4 /* MovieSearchUITestsLaunchTests.swift */; }; + 0AF34D472798C04A009F97E4 /* APIManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AF34D462798C04A009F97E4 /* APIManager.swift */; }; + 0AF34D492798C0DA009F97E4 /* Request.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AF34D482798C0DA009F97E4 /* Request.swift */; }; + 0AF34D4B2798C213009F97E4 /* APITest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AF34D4A2798C213009F97E4 /* APITest.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -44,6 +47,9 @@ 0AF34D332798BDEF009F97E4 /* MovieSearchUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MovieSearchUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 0AF34D372798BDEF009F97E4 /* MovieSearchUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MovieSearchUITests.swift; sourceTree = ""; }; 0AF34D392798BDEF009F97E4 /* MovieSearchUITestsLaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MovieSearchUITestsLaunchTests.swift; sourceTree = ""; }; + 0AF34D462798C04A009F97E4 /* APIManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = APIManager.swift; sourceTree = ""; }; + 0AF34D482798C0DA009F97E4 /* Request.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Request.swift; sourceTree = ""; }; + 0AF34D4A2798C213009F97E4 /* APITest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = APITest.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -96,6 +102,7 @@ children = ( 0AF34D1C2798BDEE009F97E4 /* MovieSearchApp.swift */, 0AF34D1E2798BDEE009F97E4 /* ContentView.swift */, + 0AF34D4C2798C303009F97E4 /* APIManager */, 0AF34D202798BDEF009F97E4 /* Assets.xcassets */, 0AF34D222798BDEF009F97E4 /* Preview Content */, ); @@ -114,6 +121,7 @@ isa = PBXGroup; children = ( 0AF34D2D2798BDEF009F97E4 /* MovieSearchTests.swift */, + 0AF34D4A2798C213009F97E4 /* APITest.swift */, ); path = MovieSearchTests; sourceTree = ""; @@ -127,6 +135,15 @@ path = MovieSearchUITests; sourceTree = ""; }; + 0AF34D4C2798C303009F97E4 /* APIManager */ = { + isa = PBXGroup; + children = ( + 0AF34D462798C04A009F97E4 /* APIManager.swift */, + 0AF34D482798C0DA009F97E4 /* Request.swift */, + ); + path = APIManager; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -257,6 +274,8 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 0AF34D472798C04A009F97E4 /* APIManager.swift in Sources */, + 0AF34D492798C0DA009F97E4 /* Request.swift in Sources */, 0AF34D1F2798BDEE009F97E4 /* ContentView.swift in Sources */, 0AF34D1D2798BDEE009F97E4 /* MovieSearchApp.swift in Sources */, ); @@ -266,6 +285,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 0AF34D4B2798C213009F97E4 /* APITest.swift in Sources */, 0AF34D2E2798BDEF009F97E4 /* MovieSearchTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/MovieSearch/APIManager/APIManager.swift b/MovieSearch/APIManager/APIManager.swift new file mode 100644 index 0000000..2d4fea7 --- /dev/null +++ b/MovieSearch/APIManager/APIManager.swift @@ -0,0 +1,72 @@ +// +// APIManager.swift +// MovieSearch +// +// Created by Ananth Jk on 19/01/2022. +// + +import Foundation + +enum APIError: Error { + case networkError + case parsingError +} + +final class APIManager { + + static let shared = APIManager() + + let apiKey = "a303f5f9" + let host = "http://www.omdbapi.com/" + + private let urlSession: URLSession + + init(urlSession: URLSession = .shared) { + self.urlSession = urlSession + } + + func execute(_ request: Request, completion: @escaping (Result) -> Void) { + urlSession.dataTask(with: urlRequest(for: request)) { responseData, response, _ in + if let data = responseData { + let response: Value + do { + response = try JSONDecoder().decode(Value.self, from: data) + } catch { + completion(.failure(.parsingError)) + return + } + + completion(.success(response)) + } else { + completion(.failure(.networkError)) + } + }.resume() + } + + private func urlRequest(for request: Request) -> URLRequest { + let url = URL(host, apiKey, request) + var result = URLRequest(url: url) + result.httpMethod = request.method.rawValue + return result + } + +} + +extension URL { + func url(with queryItems: [URLQueryItem]) -> URL { + var components = URLComponents(url: self, resolvingAgainstBaseURL: true)! + components.queryItems = (components.queryItems ?? []) + queryItems + return components.url! + } + + init(_ host: String, _ apiKey: String, _ request: Request) { + let queryItems = [ ("apikey", apiKey) ] + .map { name, value in URLQueryItem(name: name, value: "\(value)") } + + let url = URL(string: host)! + .appendingPathComponent(request.path) + .url(with: queryItems) + + self.init(string: url.absoluteString)! + } +} diff --git a/MovieSearch/APIManager/Request.swift b/MovieSearch/APIManager/Request.swift new file mode 100644 index 0000000..e0537a0 --- /dev/null +++ b/MovieSearch/APIManager/Request.swift @@ -0,0 +1,24 @@ +// +// Request.swift +// MovieSearch +// +// Created by Ananth Jk on 19/01/2022. +// + +import Foundation + +enum Method: String { + case get = "GET" +} + +struct Request { + + var method: Method + var path: String + + init(method: Method = .get, path: String) { + self.method = method + self.path = path + } + +} diff --git a/MovieSearchTests/APITest.swift b/MovieSearchTests/APITest.swift new file mode 100644 index 0000000..7c257bf --- /dev/null +++ b/MovieSearchTests/APITest.swift @@ -0,0 +1,19 @@ +// +// APITest.swift +// MovieSearchTests +// +// Created by Ananth Jk on 19/01/2022. +// + +import XCTest +@testable import MovieSearch + +class APITest: XCTestCase { + + func test_url_queryParams() { + let queryItem = URLQueryItem(name: "testName", value: "testValue") + let url = URL(string: "http://www.omdbapi.com")!.url(with: [queryItem]) + XCTAssertEqual(url.absoluteString, "http://www.omdbapi.com?testName=testValue") + } + +} From 6ce1bb6da3c53b8a56b22364a963c63c35440646 Mon Sep 17 00:00:00 2001 From: Ananth Jk Date: Wed, 19 Jan 2022 22:26:29 +0000 Subject: [PATCH 3/9] RemoteTest: Added model --- MovieSearch.xcodeproj/project.pbxproj | 12 +++++++++++ MovieSearch/Model/Movie.swift | 29 +++++++++++++++++++++++++++ MovieSearchTests/APITest.swift | 6 ++++++ 3 files changed, 47 insertions(+) create mode 100644 MovieSearch/Model/Movie.swift diff --git a/MovieSearch.xcodeproj/project.pbxproj b/MovieSearch.xcodeproj/project.pbxproj index 0704157..1153df2 100644 --- a/MovieSearch.xcodeproj/project.pbxproj +++ b/MovieSearch.xcodeproj/project.pbxproj @@ -17,6 +17,7 @@ 0AF34D472798C04A009F97E4 /* APIManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AF34D462798C04A009F97E4 /* APIManager.swift */; }; 0AF34D492798C0DA009F97E4 /* Request.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AF34D482798C0DA009F97E4 /* Request.swift */; }; 0AF34D4B2798C213009F97E4 /* APITest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AF34D4A2798C213009F97E4 /* APITest.swift */; }; + 0AF34D502798C4AE009F97E4 /* Movie.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AF34D4F2798C4AE009F97E4 /* Movie.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -50,6 +51,7 @@ 0AF34D462798C04A009F97E4 /* APIManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = APIManager.swift; sourceTree = ""; }; 0AF34D482798C0DA009F97E4 /* Request.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Request.swift; sourceTree = ""; }; 0AF34D4A2798C213009F97E4 /* APITest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = APITest.swift; sourceTree = ""; }; + 0AF34D4F2798C4AE009F97E4 /* Movie.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Movie.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -102,6 +104,7 @@ children = ( 0AF34D1C2798BDEE009F97E4 /* MovieSearchApp.swift */, 0AF34D1E2798BDEE009F97E4 /* ContentView.swift */, + 0AF34D4E2798C371009F97E4 /* Model */, 0AF34D4C2798C303009F97E4 /* APIManager */, 0AF34D202798BDEF009F97E4 /* Assets.xcassets */, 0AF34D222798BDEF009F97E4 /* Preview Content */, @@ -144,6 +147,14 @@ path = APIManager; sourceTree = ""; }; + 0AF34D4E2798C371009F97E4 /* Model */ = { + isa = PBXGroup; + children = ( + 0AF34D4F2798C4AE009F97E4 /* Movie.swift */, + ); + path = Model; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -278,6 +289,7 @@ 0AF34D492798C0DA009F97E4 /* Request.swift in Sources */, 0AF34D1F2798BDEE009F97E4 /* ContentView.swift in Sources */, 0AF34D1D2798BDEE009F97E4 /* MovieSearchApp.swift in Sources */, + 0AF34D502798C4AE009F97E4 /* Movie.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/MovieSearch/Model/Movie.swift b/MovieSearch/Model/Movie.swift new file mode 100644 index 0000000..fda6e3f --- /dev/null +++ b/MovieSearch/Model/Movie.swift @@ -0,0 +1,29 @@ +// +// Movie.swift +// MovieSearch +// +// Created by Ananth Jk on 19/01/2022. +// + +import Foundation + +struct Movie: Decodable, Identifiable { + var id: String { + imdbRating + } + let title: String + let year: String + let imdbID: String + let plot: String + let imdbRating: String + let genre: String + + enum CodingKeys: String, CodingKey { + case imdbID + case imdbRating + case title = "Title" + case year = "Year" + case plot = "Plot" + case genre = "Genre" + } +} diff --git a/MovieSearchTests/APITest.swift b/MovieSearchTests/APITest.swift index 7c257bf..5b13893 100644 --- a/MovieSearchTests/APITest.swift +++ b/MovieSearchTests/APITest.swift @@ -15,5 +15,11 @@ class APITest: XCTestCase { let url = URL(string: "http://www.omdbapi.com")!.url(with: [queryItem]) XCTAssertEqual(url.absoluteString, "http://www.omdbapi.com?testName=testValue") } + + func test_full_url_builder() { + let request: Request = Request(method: .get, path: "/testing") + let url = URL("http://www.omdbapi.com", "testKey", request) + XCTAssertEqual(url.absoluteString, "http://www.omdbapi.com/testing?apikey=testKey") + } } From 406184b9554ddb9852360efc20eb23a81ffc880d Mon Sep 17 00:00:00 2001 From: Ananth Jk Date: Thu, 20 Jan 2022 00:32:21 +0000 Subject: [PATCH 4/9] RemoteTask: Added search api call --- MovieSearch.xcodeproj/project.pbxproj | 16 ++++-- MovieSearch/APIManager/APIManager.swift | 11 ++-- MovieSearch/APIManager/Request.swift | 6 ++- MovieSearch/ContentView.swift | 21 -------- MovieSearch/Model/Movie.swift | 24 +++++++-- MovieSearch/MovieSearchApp.swift | 2 +- MovieSearch/MovieView.swift | 21 ++++++++ MovieSearch/SearchView.swift | 72 +++++++++++++++++++++++++ MovieSearch/SearchViewModel.swift | 53 ++++++++++++++++++ 9 files changed, 189 insertions(+), 37 deletions(-) delete mode 100644 MovieSearch/ContentView.swift create mode 100644 MovieSearch/MovieView.swift create mode 100644 MovieSearch/SearchView.swift create mode 100644 MovieSearch/SearchViewModel.swift diff --git a/MovieSearch.xcodeproj/project.pbxproj b/MovieSearch.xcodeproj/project.pbxproj index 1153df2..050fa29 100644 --- a/MovieSearch.xcodeproj/project.pbxproj +++ b/MovieSearch.xcodeproj/project.pbxproj @@ -8,7 +8,7 @@ /* Begin PBXBuildFile section */ 0AF34D1D2798BDEE009F97E4 /* MovieSearchApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AF34D1C2798BDEE009F97E4 /* MovieSearchApp.swift */; }; - 0AF34D1F2798BDEE009F97E4 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AF34D1E2798BDEE009F97E4 /* ContentView.swift */; }; + 0AF34D1F2798BDEE009F97E4 /* SearchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AF34D1E2798BDEE009F97E4 /* SearchView.swift */; }; 0AF34D212798BDEF009F97E4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0AF34D202798BDEF009F97E4 /* Assets.xcassets */; }; 0AF34D242798BDEF009F97E4 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0AF34D232798BDEF009F97E4 /* Preview Assets.xcassets */; }; 0AF34D2E2798BDEF009F97E4 /* MovieSearchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AF34D2D2798BDEF009F97E4 /* MovieSearchTests.swift */; }; @@ -18,6 +18,8 @@ 0AF34D492798C0DA009F97E4 /* Request.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AF34D482798C0DA009F97E4 /* Request.swift */; }; 0AF34D4B2798C213009F97E4 /* APITest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AF34D4A2798C213009F97E4 /* APITest.swift */; }; 0AF34D502798C4AE009F97E4 /* Movie.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AF34D4F2798C4AE009F97E4 /* Movie.swift */; }; + 0AF34D522798C84E009F97E4 /* MovieView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AF34D512798C84E009F97E4 /* MovieView.swift */; }; + 0AF34D542798D634009F97E4 /* SearchViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AF34D532798D634009F97E4 /* SearchViewModel.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -40,7 +42,7 @@ /* Begin PBXFileReference section */ 0AF34D192798BDEE009F97E4 /* MovieSearch.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MovieSearch.app; sourceTree = BUILT_PRODUCTS_DIR; }; 0AF34D1C2798BDEE009F97E4 /* MovieSearchApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MovieSearchApp.swift; sourceTree = ""; }; - 0AF34D1E2798BDEE009F97E4 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; + 0AF34D1E2798BDEE009F97E4 /* SearchView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchView.swift; sourceTree = ""; }; 0AF34D202798BDEF009F97E4 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 0AF34D232798BDEF009F97E4 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; 0AF34D292798BDEF009F97E4 /* MovieSearchTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MovieSearchTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -52,6 +54,8 @@ 0AF34D482798C0DA009F97E4 /* Request.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Request.swift; sourceTree = ""; }; 0AF34D4A2798C213009F97E4 /* APITest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = APITest.swift; sourceTree = ""; }; 0AF34D4F2798C4AE009F97E4 /* Movie.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Movie.swift; sourceTree = ""; }; + 0AF34D512798C84E009F97E4 /* MovieView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MovieView.swift; sourceTree = ""; }; + 0AF34D532798D634009F97E4 /* SearchViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchViewModel.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -103,7 +107,9 @@ isa = PBXGroup; children = ( 0AF34D1C2798BDEE009F97E4 /* MovieSearchApp.swift */, - 0AF34D1E2798BDEE009F97E4 /* ContentView.swift */, + 0AF34D1E2798BDEE009F97E4 /* SearchView.swift */, + 0AF34D532798D634009F97E4 /* SearchViewModel.swift */, + 0AF34D512798C84E009F97E4 /* MovieView.swift */, 0AF34D4E2798C371009F97E4 /* Model */, 0AF34D4C2798C303009F97E4 /* APIManager */, 0AF34D202798BDEF009F97E4 /* Assets.xcassets */, @@ -286,8 +292,10 @@ buildActionMask = 2147483647; files = ( 0AF34D472798C04A009F97E4 /* APIManager.swift in Sources */, + 0AF34D542798D634009F97E4 /* SearchViewModel.swift in Sources */, + 0AF34D522798C84E009F97E4 /* MovieView.swift in Sources */, 0AF34D492798C0DA009F97E4 /* Request.swift in Sources */, - 0AF34D1F2798BDEE009F97E4 /* ContentView.swift in Sources */, + 0AF34D1F2798BDEE009F97E4 /* SearchView.swift in Sources */, 0AF34D1D2798BDEE009F97E4 /* MovieSearchApp.swift in Sources */, 0AF34D502798C4AE009F97E4 /* Movie.swift in Sources */, ); diff --git a/MovieSearch/APIManager/APIManager.swift b/MovieSearch/APIManager/APIManager.swift index 2d4fea7..47216a2 100644 --- a/MovieSearch/APIManager/APIManager.swift +++ b/MovieSearch/APIManager/APIManager.swift @@ -17,7 +17,7 @@ final class APIManager { static let shared = APIManager() let apiKey = "a303f5f9" - let host = "http://www.omdbapi.com/" + let host = "https://www.omdbapi.com/" private let urlSession: URLSession @@ -31,7 +31,8 @@ final class APIManager { let response: Value do { response = try JSONDecoder().decode(Value.self, from: data) - } catch { + } catch(let err) { + print(err) completion(.failure(.parsingError)) return } @@ -60,11 +61,11 @@ extension URL { } init(_ host: String, _ apiKey: String, _ request: Request) { - let queryItems = [ ("apikey", apiKey) ] - .map { name, value in URLQueryItem(name: name, value: "\(value)") } + let queryItems = [ ("apikey", apiKey), ("s", request.search) ] + .map { name, value in URLQueryItem(name: name, value: "\(value ?? "")") } let url = URL(string: host)! - .appendingPathComponent(request.path) + .appendingPathComponent(request.path ?? "") .url(with: queryItems) self.init(string: url.absoluteString)! diff --git a/MovieSearch/APIManager/Request.swift b/MovieSearch/APIManager/Request.swift index e0537a0..361c5c9 100644 --- a/MovieSearch/APIManager/Request.swift +++ b/MovieSearch/APIManager/Request.swift @@ -14,11 +14,13 @@ enum Method: String { struct Request { var method: Method - var path: String + var search: String? + var path: String? - init(method: Method = .get, path: String) { + init(method: Method = .get, path: String?, search: String?) { self.method = method self.path = path + self.search = search } } diff --git a/MovieSearch/ContentView.swift b/MovieSearch/ContentView.swift deleted file mode 100644 index 0595ed9..0000000 --- a/MovieSearch/ContentView.swift +++ /dev/null @@ -1,21 +0,0 @@ -// -// ContentView.swift -// MovieSearch -// -// Created by Ananth Jk on 19/01/2022. -// - -import SwiftUI - -struct ContentView: View { - var body: some View { - Text("Hello, world!") - .padding() - } -} - -struct ContentView_Previews: PreviewProvider { - static var previews: some View { - ContentView() - } -} diff --git a/MovieSearch/Model/Movie.swift b/MovieSearch/Model/Movie.swift index fda6e3f..8a6fa1e 100644 --- a/MovieSearch/Model/Movie.swift +++ b/MovieSearch/Model/Movie.swift @@ -9,14 +9,15 @@ import Foundation struct Movie: Decodable, Identifiable { var id: String { - imdbRating + imdbID } let title: String let year: String let imdbID: String - let plot: String - let imdbRating: String - let genre: String + let plot: String? + let imdbRating: String? + let genre: String? + let poster: String enum CodingKeys: String, CodingKey { case imdbID @@ -25,5 +26,20 @@ struct Movie: Decodable, Identifiable { case year = "Year" case plot = "Plot" case genre = "Genre" + case poster = "Poster" + } +} + +struct Search: Decodable { + var movies: [Movie] + + enum CodingKeys: String, CodingKey { + case movies = "Search" + } +} + +extension Search { + static func search(name: String) -> Request { + Request(method: .get, path: nil, search: name) } } diff --git a/MovieSearch/MovieSearchApp.swift b/MovieSearch/MovieSearchApp.swift index 230f57a..6d299e2 100644 --- a/MovieSearch/MovieSearchApp.swift +++ b/MovieSearch/MovieSearchApp.swift @@ -11,7 +11,7 @@ import SwiftUI struct MovieSearchApp: App { var body: some Scene { WindowGroup { - ContentView() + SearchView(viewModel: SearchViewModel()) } } } diff --git a/MovieSearch/MovieView.swift b/MovieSearch/MovieView.swift new file mode 100644 index 0000000..4ca93c4 --- /dev/null +++ b/MovieSearch/MovieView.swift @@ -0,0 +1,21 @@ +// +// MovieView.swift +// MovieSearch +// +// Created by Ananth Jk on 19/01/2022. +// + +import SwiftUI + +struct MovieView: View { + @Binding var movie: Movie + var body: some View { + Text(movie.title) + } +} + +struct MovieView_Previews: PreviewProvider { + static var previews: some View { + MovieView(movie: .constant(Movie(title: "Guardians of the Galaxy Vol. 2", year: "2017", imdbID: "tt3896198", plot: "The Guardians struggle to keep together as a team while dealing with their personal family issues, notably Star-Lord's encounter with his father the ambitious celestial being Ego.", imdbRating: "7.6", genre: "Action, Adventure, Comedy", poster: "https://m.media-amazon.com/images/M/MV5BNjM0NTc0NzItM2FlYS00YzEwLWE0YmUtNTA2ZWIzODc2OTgxXkEyXkFqcGdeQXVyNTgwNzIyNzg@._V1_SX300.jpg"))) + } +} diff --git a/MovieSearch/SearchView.swift b/MovieSearch/SearchView.swift new file mode 100644 index 0000000..8ce5fd8 --- /dev/null +++ b/MovieSearch/SearchView.swift @@ -0,0 +1,72 @@ +// +// ContentView.swift +// MovieSearch +// +// Created by Ananth Jk on 19/01/2022. +// + +import SwiftUI + +struct SearchView: View { + @ObservedObject var viewModel: SearchViewModel + let columns = [ + GridItem(.flexible()), + GridItem(.flexible()), + GridItem(.flexible()) + ] + var body: some View { + VStack { + HStack(alignment: .center) { + TextField("Enter Movie Name", text: $viewModel.searchParamater) + .textFieldStyle(.roundedBorder) + Button { + if !viewModel.searchParamater.isEmpty { + viewModel.search() + } + } label: { + HStack { + Image(systemName: "magnifyingglass") + Text("Search") + } + } + .buttonStyle(.bordered) + } + LazyVGrid(columns: columns, spacing: 10) { + ForEach(viewModel.history, id: \.self) { value in + Button { + viewModel.search() + } label: { + Text(value) + } + .buttonStyle(.borderedProminent) + + } + } + } + .onAppear { + viewModel.getHistory() + } + } +} + +struct SearchView_Previews: PreviewProvider { + static var previews: some View { + SearchView(viewModel: SearchViewModel()) + .previewInterfaceOrientation(.portraitUpsideDown) + } +} + +extension String { + var array: [String] { + if !self.isEmpty { + return self.components(separatedBy: ",") + }else { + return [] + } + } +} +extension Array where Element == String { + var string: String { + self.joined(separator: ",") + } +} diff --git a/MovieSearch/SearchViewModel.swift b/MovieSearch/SearchViewModel.swift new file mode 100644 index 0000000..5d4ebca --- /dev/null +++ b/MovieSearch/SearchViewModel.swift @@ -0,0 +1,53 @@ +// +// SearchViewModel.swift +// MovieSearch +// +// Created by Ananth Jk on 19/01/2022. +// + +import Foundation +import SwiftUI + +class SearchViewModel: ObservableObject { + @Published var searchParamater: String = "" + @Published var history: [String] = [] + @AppStorage("history") var historyStore: String = "" + + func saveHistory() { + if !history.isEmpty { + historyStore = history[0...10].joined(separator: ",") + } + } + + func getHistory() { + history = historyStore.array + } + + func search() { + updateHistory() + getMovies() + } + + private func updateHistory() { + if history.isEmpty { + history.append(searchParamater) + }else { + history.insert(searchParamater, at: 0) + if history.count > 9 { + history.popLast() + } + } + } + + private func getMovies() { + APIManager.shared.execute(Search.search(name: searchParamater)) { result in + switch result { + case .success(let result): + print(result.movies.first?.title) + case .failure(let error): + print(error.localizedDescription) + } + } + } + +} From 1a343c7582e77257deb2f490c9ef6cbef95a761b Mon Sep 17 00:00:00 2001 From: Ananth Jk Date: Thu, 20 Jan 2022 01:10:14 +0000 Subject: [PATCH 5/9] RemoteTask: Completed basic search and display --- MovieSearch/Model/Movie.swift | 2 ++ MovieSearch/MovieView.swift | 45 +++++++++++++++++++++++-- MovieSearch/SearchView.swift | 55 +++++++++++++++++-------------- MovieSearch/SearchViewModel.swift | 5 ++- 4 files changed, 80 insertions(+), 27 deletions(-) diff --git a/MovieSearch/Model/Movie.swift b/MovieSearch/Model/Movie.swift index 8a6fa1e..4a0de86 100644 --- a/MovieSearch/Model/Movie.swift +++ b/MovieSearch/Model/Movie.swift @@ -17,6 +17,7 @@ struct Movie: Decodable, Identifiable { let plot: String? let imdbRating: String? let genre: String? + let type: String? let poster: String enum CodingKeys: String, CodingKey { @@ -27,6 +28,7 @@ struct Movie: Decodable, Identifiable { case plot = "Plot" case genre = "Genre" case poster = "Poster" + case type = "Type" } } diff --git a/MovieSearch/MovieView.swift b/MovieSearch/MovieView.swift index 4ca93c4..d9efd7f 100644 --- a/MovieSearch/MovieView.swift +++ b/MovieSearch/MovieView.swift @@ -7,15 +7,56 @@ import SwiftUI +struct MovieList: View { + @State var movies: [Movie] + var body: some View { + ScrollView { + VStack(alignment: .leading) { + ForEach($movies) { movie in + MovieView(movie: movie) + } + } + } + } +} + struct MovieView: View { @Binding var movie: Movie + @State var image = UIImage() var body: some View { - Text(movie.title) + HStack(alignment: .top) { + Image(uiImage: image) + .resizable() + .frame(width: 60, height: 100) + .aspectRatio(contentMode: .fill) + VStack(alignment: .leading) { + Text(movie.title) + .font(.title2) + HStack { + Text(movie.year) + Text(movie.type ?? "") + } + .font(.body) + } + } + .onAppear { + getImage() + } + } + func getImage() { + let imageURL = URL(string: movie.poster) + DispatchQueue.global().async { + let data = try? Data(contentsOf: imageURL!) + DispatchQueue.main.async { + guard let data = data else { return } + self.image = UIImage(data: data) ?? UIImage(systemName: "photo")! + } + } } } struct MovieView_Previews: PreviewProvider { static var previews: some View { - MovieView(movie: .constant(Movie(title: "Guardians of the Galaxy Vol. 2", year: "2017", imdbID: "tt3896198", plot: "The Guardians struggle to keep together as a team while dealing with their personal family issues, notably Star-Lord's encounter with his father the ambitious celestial being Ego.", imdbRating: "7.6", genre: "Action, Adventure, Comedy", poster: "https://m.media-amazon.com/images/M/MV5BNjM0NTc0NzItM2FlYS00YzEwLWE0YmUtNTA2ZWIzODc2OTgxXkEyXkFqcGdeQXVyNTgwNzIyNzg@._V1_SX300.jpg"))) + MovieView(movie: .constant(Movie(title: "Guardians of the Galaxy Vol. 2", year: "2017", imdbID: "tt3896198", plot: "The Guardians struggle to keep together as a team while dealing with their personal family issues, notably Star-Lord's encounter with his father the ambitious celestial being Ego.", imdbRating: "7.6", genre: "Action, Adventure, Comedy", type: "Movie", poster: "https://m.media-amazon.com/images/M/MV5BNjM0NTc0NzItM2FlYS00YzEwLWE0YmUtNTA2ZWIzODc2OTgxXkEyXkFqcGdeQXVyNTgwNzIyNzg@._V1_SX300.jpg"))) } } diff --git a/MovieSearch/SearchView.swift b/MovieSearch/SearchView.swift index 8ce5fd8..3867a55 100644 --- a/MovieSearch/SearchView.swift +++ b/MovieSearch/SearchView.swift @@ -15,36 +15,43 @@ struct SearchView: View { GridItem(.flexible()) ] var body: some View { - VStack { - HStack(alignment: .center) { - TextField("Enter Movie Name", text: $viewModel.searchParamater) - .textFieldStyle(.roundedBorder) - Button { - if !viewModel.searchParamater.isEmpty { - viewModel.search() - } - } label: { - HStack { - Image(systemName: "magnifyingglass") - Text("Search") + NavigationView { + VStack { + HStack(alignment: .center) { + TextField("Enter Movie Name", text: $viewModel.searchParamater) + .textFieldStyle(.roundedBorder) + Button { + if !viewModel.searchParamater.isEmpty { + viewModel.search() + } + } label: { + HStack { + Image(systemName: "magnifyingglass") + Text("Search") + } } + .buttonStyle(.bordered) } - .buttonStyle(.bordered) - } - LazyVGrid(columns: columns, spacing: 10) { - ForEach(viewModel.history, id: \.self) { value in - Button { - viewModel.search() - } label: { - Text(value) + LazyVGrid(columns: columns, spacing: 10) { + ForEach(viewModel.history, id: \.self) { value in + Button { + viewModel.search() + } label: { + Text(value) + } + .buttonStyle(.borderedProminent) } - .buttonStyle(.borderedProminent) - } + NavigationLink(isActive: $viewModel.showResult) { + MovieList(movies: viewModel.movies) + } label: { + Text("") } + + } + .onAppear { + viewModel.getHistory() } - .onAppear { - viewModel.getHistory() } } } diff --git a/MovieSearch/SearchViewModel.swift b/MovieSearch/SearchViewModel.swift index 5d4ebca..cbe9bfc 100644 --- a/MovieSearch/SearchViewModel.swift +++ b/MovieSearch/SearchViewModel.swift @@ -12,6 +12,8 @@ class SearchViewModel: ObservableObject { @Published var searchParamater: String = "" @Published var history: [String] = [] @AppStorage("history") var historyStore: String = "" + @Published var movies: [Movie] = [] + @Published var showResult = false func saveHistory() { if !history.isEmpty { @@ -43,7 +45,8 @@ class SearchViewModel: ObservableObject { APIManager.shared.execute(Search.search(name: searchParamater)) { result in switch result { case .success(let result): - print(result.movies.first?.title) + self.movies = result.movies + self.showResult = true case .failure(let error): print(error.localizedDescription) } From c13350bfbcac7aca2651e7842e3efc86e81f4fdf Mon Sep 17 00:00:00 2001 From: Ananth Jk Date: Thu, 20 Jan 2022 22:57:06 +0000 Subject: [PATCH 6/9] RemoteTask: Completed search and display --- MovieSearch/MovieView.swift | 6 ++++++ MovieSearch/SearchView.swift | 32 ++++++++++++++++++++----------- MovieSearch/SearchViewModel.swift | 12 ++++++++---- 3 files changed, 35 insertions(+), 15 deletions(-) diff --git a/MovieSearch/MovieView.swift b/MovieSearch/MovieView.swift index d9efd7f..0388940 100644 --- a/MovieSearch/MovieView.swift +++ b/MovieSearch/MovieView.swift @@ -9,14 +9,18 @@ import SwiftUI struct MovieList: View { @State var movies: [Movie] + var title: String var body: some View { ScrollView { VStack(alignment: .leading) { ForEach($movies) { movie in MovieView(movie: movie) + Divider() + .padding(.horizontal) } } } + .navigationTitle(title) } } @@ -38,7 +42,9 @@ struct MovieView: View { } .font(.body) } + Spacer() } + .padding() .onAppear { getImage() } diff --git a/MovieSearch/SearchView.swift b/MovieSearch/SearchView.swift index 3867a55..d372c97 100644 --- a/MovieSearch/SearchView.swift +++ b/MovieSearch/SearchView.swift @@ -30,28 +30,38 @@ struct SearchView: View { Text("Search") } } + .disabled(viewModel.searchParamater.count < 3) .buttonStyle(.bordered) } - LazyVGrid(columns: columns, spacing: 10) { - ForEach(viewModel.history, id: \.self) { value in - Button { - viewModel.search() - } label: { - Text(value) - } - .buttonStyle(.borderedProminent) + LazyVGrid(columns: columns, spacing: 10) { + ForEach(viewModel.history, id: \.self) { value in + Button { + viewModel.searchParamater = value + viewModel.search() + } label: { + Text(value) } + .buttonStyle(.borderedProminent) } + } NavigationLink(isActive: $viewModel.showResult) { - MovieList(movies: viewModel.movies) + MovieList(movies: viewModel.movies, title: viewModel.searchParamater) } label: { Text("") } - + } + .padding(.horizontal) .onAppear { viewModel.getHistory() - } + } + .onDisappear { + viewModel.saveHistory() + } + .alert(Text("Error"), isPresented: $viewModel.error) { + + } + .navigationTitle("Search Movies") } } } diff --git a/MovieSearch/SearchViewModel.swift b/MovieSearch/SearchViewModel.swift index cbe9bfc..0e7aa28 100644 --- a/MovieSearch/SearchViewModel.swift +++ b/MovieSearch/SearchViewModel.swift @@ -14,10 +14,11 @@ class SearchViewModel: ObservableObject { @AppStorage("history") var historyStore: String = "" @Published var movies: [Movie] = [] @Published var showResult = false + @Published var error = false func saveHistory() { if !history.isEmpty { - historyStore = history[0...10].joined(separator: ",") + historyStore = history[0...(min(10, history.count - 1))].joined(separator: ",") } } @@ -33,7 +34,7 @@ class SearchViewModel: ObservableObject { private func updateHistory() { if history.isEmpty { history.append(searchParamater) - }else { + }else if !history.contains(searchParamater) { history.insert(searchParamater, at: 0) if history.count > 9 { history.popLast() @@ -45,10 +46,13 @@ class SearchViewModel: ObservableObject { APIManager.shared.execute(Search.search(name: searchParamater)) { result in switch result { case .success(let result): - self.movies = result.movies - self.showResult = true + DispatchQueue.main.async { + self.movies = result.movies + self.showResult = true + } case .failure(let error): print(error.localizedDescription) + self.error = true } } } From ae51489fe75177fb4abe3973902317524cf0a252 Mon Sep 17 00:00:00 2001 From: Ananth Jk Date: Sun, 23 Jan 2022 21:46:11 +0000 Subject: [PATCH 7/9] RemoteTask: Completed detailed screen --- MovieSearch.md | 13 +++++ MovieSearch.xcodeproj/project.pbxproj | 10 ++++ MovieSearch/APIManager/APIManager.swift | 3 +- MovieSearch/APIManager/Request.swift | 13 +++-- MovieSearch/Model/Movie.swift | 20 ++++++- MovieSearch/MovieDetails.swift | 71 +++++++++++++++++++++++++ MovieSearch/MovieDetailsViewModel.swift | 42 +++++++++++++++ MovieSearch/MovieView.swift | 19 ++++--- MovieSearch/SearchView.swift | 2 +- MovieSearch/SearchViewModel.swift | 6 ++- 10 files changed, 180 insertions(+), 19 deletions(-) create mode 100644 MovieSearch.md create mode 100644 MovieSearch/MovieDetails.swift create mode 100644 MovieSearch/MovieDetailsViewModel.swift diff --git a/MovieSearch.md b/MovieSearch.md new file mode 100644 index 0000000..0f709d2 --- /dev/null +++ b/MovieSearch.md @@ -0,0 +1,13 @@ +# MovieSearch + +Lets you search for movies + +## Overview + +Text + +## Topics + +### Group + +- ``Symbol`` diff --git a/MovieSearch.xcodeproj/project.pbxproj b/MovieSearch.xcodeproj/project.pbxproj index 050fa29..d6448ef 100644 --- a/MovieSearch.xcodeproj/project.pbxproj +++ b/MovieSearch.xcodeproj/project.pbxproj @@ -7,6 +7,8 @@ objects = { /* Begin PBXBuildFile section */ + 0A436301279A21CE0027CF61 /* MovieDetails.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A436300279A21CE0027CF61 /* MovieDetails.swift */; }; + 0A43634E279DFB950027CF61 /* MovieDetailsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A43634D279DFB950027CF61 /* MovieDetailsViewModel.swift */; }; 0AF34D1D2798BDEE009F97E4 /* MovieSearchApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AF34D1C2798BDEE009F97E4 /* MovieSearchApp.swift */; }; 0AF34D1F2798BDEE009F97E4 /* SearchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AF34D1E2798BDEE009F97E4 /* SearchView.swift */; }; 0AF34D212798BDEF009F97E4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0AF34D202798BDEF009F97E4 /* Assets.xcassets */; }; @@ -40,6 +42,9 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 0A4362FF279A219A0027CF61 /* MovieSearch.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = MovieSearch.md; sourceTree = ""; }; + 0A436300279A21CE0027CF61 /* MovieDetails.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MovieDetails.swift; sourceTree = ""; }; + 0A43634D279DFB950027CF61 /* MovieDetailsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MovieDetailsViewModel.swift; sourceTree = ""; }; 0AF34D192798BDEE009F97E4 /* MovieSearch.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MovieSearch.app; sourceTree = BUILT_PRODUCTS_DIR; }; 0AF34D1C2798BDEE009F97E4 /* MovieSearchApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MovieSearchApp.swift; sourceTree = ""; }; 0AF34D1E2798BDEE009F97E4 /* SearchView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchView.swift; sourceTree = ""; }; @@ -86,6 +91,7 @@ 0AF34D102798BDEE009F97E4 = { isa = PBXGroup; children = ( + 0A4362FF279A219A0027CF61 /* MovieSearch.md */, 0AF34D1B2798BDEE009F97E4 /* MovieSearch */, 0AF34D2C2798BDEF009F97E4 /* MovieSearchTests */, 0AF34D362798BDEF009F97E4 /* MovieSearchUITests */, @@ -110,6 +116,8 @@ 0AF34D1E2798BDEE009F97E4 /* SearchView.swift */, 0AF34D532798D634009F97E4 /* SearchViewModel.swift */, 0AF34D512798C84E009F97E4 /* MovieView.swift */, + 0A436300279A21CE0027CF61 /* MovieDetails.swift */, + 0A43634D279DFB950027CF61 /* MovieDetailsViewModel.swift */, 0AF34D4E2798C371009F97E4 /* Model */, 0AF34D4C2798C303009F97E4 /* APIManager */, 0AF34D202798BDEF009F97E4 /* Assets.xcassets */, @@ -294,10 +302,12 @@ 0AF34D472798C04A009F97E4 /* APIManager.swift in Sources */, 0AF34D542798D634009F97E4 /* SearchViewModel.swift in Sources */, 0AF34D522798C84E009F97E4 /* MovieView.swift in Sources */, + 0A436301279A21CE0027CF61 /* MovieDetails.swift in Sources */, 0AF34D492798C0DA009F97E4 /* Request.swift in Sources */, 0AF34D1F2798BDEE009F97E4 /* SearchView.swift in Sources */, 0AF34D1D2798BDEE009F97E4 /* MovieSearchApp.swift in Sources */, 0AF34D502798C4AE009F97E4 /* Movie.swift in Sources */, + 0A43634E279DFB950027CF61 /* MovieDetailsViewModel.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/MovieSearch/APIManager/APIManager.swift b/MovieSearch/APIManager/APIManager.swift index 47216a2..8cfb9e7 100644 --- a/MovieSearch/APIManager/APIManager.swift +++ b/MovieSearch/APIManager/APIManager.swift @@ -61,7 +61,8 @@ extension URL { } init(_ host: String, _ apiKey: String, _ request: Request) { - let queryItems = [ ("apikey", apiKey), ("s", request.search) ] + + let queryItems = [ ("apikey", apiKey), (request.parameter?.rawValue ?? "s", request.parameterValue) ] .map { name, value in URLQueryItem(name: name, value: "\(value ?? "")") } let url = URL(string: host)! diff --git a/MovieSearch/APIManager/Request.swift b/MovieSearch/APIManager/Request.swift index 361c5c9..d75d39e 100644 --- a/MovieSearch/APIManager/Request.swift +++ b/MovieSearch/APIManager/Request.swift @@ -10,17 +10,24 @@ import Foundation enum Method: String { case get = "GET" } +enum Parameters: String { + case search = "s" + case id = "i" + case title = "t" +} struct Request { var method: Method - var search: String? + var parameterValue: String? var path: String? + var parameter: Parameters? - init(method: Method = .get, path: String?, search: String?) { + init(method: Method = .get, parameter: Parameters = .search, parameterValue: String?, path: String?) { self.method = method self.path = path - self.search = search + self.parameter = parameter + self.parameterValue = parameterValue } } diff --git a/MovieSearch/Model/Movie.swift b/MovieSearch/Model/Movie.swift index 4a0de86..739344a 100644 --- a/MovieSearch/Model/Movie.swift +++ b/MovieSearch/Model/Movie.swift @@ -6,6 +6,7 @@ // import Foundation +import UIKit struct Movie: Decodable, Identifiable { var id: String { @@ -13,7 +14,7 @@ struct Movie: Decodable, Identifiable { } let title: String let year: String - let imdbID: String + var imdbID: String let plot: String? let imdbRating: String? let genre: String? @@ -31,6 +32,21 @@ struct Movie: Decodable, Identifiable { case type = "Type" } } +extension Movie { + static func getMovieDetails(for id: String) -> Request { + Request(method: .get, parameter: .id, parameterValue: id, path: nil) + } + static func getImage(for movie: Movie, completion: @escaping (_ image: UIImage) -> Void) { + let imageURL = URL(string: movie.poster) + DispatchQueue.global().async { + let data = try? Data(contentsOf: imageURL!) + DispatchQueue.main.async { + guard let data = data else { return } + completion(UIImage(data: data) ?? UIImage(systemName: "photo")!) + } + } + } +} struct Search: Decodable { var movies: [Movie] @@ -42,6 +58,6 @@ struct Search: Decodable { extension Search { static func search(name: String) -> Request { - Request(method: .get, path: nil, search: name) + Request(parameterValue: name, path: nil) } } diff --git a/MovieSearch/MovieDetails.swift b/MovieSearch/MovieDetails.swift new file mode 100644 index 0000000..6b354fc --- /dev/null +++ b/MovieSearch/MovieDetails.swift @@ -0,0 +1,71 @@ +// +// MovieDetails.swift +// MovieSearch +// +// Created by Ananth Jk on 20/01/2022. +// + +import SwiftUI + +struct MovieDetails: View { + @ObservedObject var viewModel: MovieDetailsViewModel + var body: some View { + if viewModel.movie == nil { + ProgressView() + .onAppear { + viewModel.getMovieDetails() + } + .navigationBarTitleDisplayMode(.inline) + } else { + ScrollView { + VStack(alignment: .leading, spacing: 10) { + HStack { + Spacer() + Image(uiImage: viewModel.movieImage ?? UIImage()) + .resizable() + .frame(width: 200, height: 300, alignment: .center) + .scaledToFill() + .cornerRadius(10) + Spacer() + } + HStack { + HStack(alignment: .firstTextBaseline) { + Image(systemName: "star.fill") + Text(viewModel.movie?.imdbRating ?? "") + } + .padding(4) + // .padding(.horizontal, 2) + .foregroundColor(.white) + .background(Color.black) + .cornerRadius(5) + Text(viewModel.movie?.title ?? "") + .font(.title3) + .fontWeight(.bold) + } + .padding(.top, 5) + Text(viewModel.movie?.genre ?? "") + .font(.footnote) + Text(viewModel.movie?.plot ?? "") + .font(.body) + .fontWeight(.thin) + .padding(.top, 10) + } + .padding() + .onAppear { + viewModel.getImage() + } + .navigationBarTitleDisplayMode(.inline) + } + + } + } +} + +struct MovieDetails_Previews: PreviewProvider { + static var previews: some View { + MovieDetails(viewModel: MovieDetailsViewModel(id: "123")) + } +} +/* + Movie(title: "Guardians of the Galaxy Vol. 2", year: "2017", imdbID: "tt3896198", plot: "The Guardians struggle to keep together as a team while dealing with their personal family issues, notably Star-Lord's encounter with his father the ambitious celestial being Ego.", imdbRating: "7.6", genre: "Action, Adventure, Comedy", type: "Movie", poster: "https://m.media-amazon.com/images/M/MV5BNjM0NTc0NzItM2FlYS00YzEwLWE0YmUtNTA2ZWIzODc2OTgxXkEyXkFqcGdeQXVyNTgwNzIyNzg@._V1_SX300.jpg") + */ diff --git a/MovieSearch/MovieDetailsViewModel.swift b/MovieSearch/MovieDetailsViewModel.swift new file mode 100644 index 0000000..47b1998 --- /dev/null +++ b/MovieSearch/MovieDetailsViewModel.swift @@ -0,0 +1,42 @@ +// +// MovieDetailsViewModel.swift +// MovieSearch +// +// Created by Ananth Jk on 23/01/2022. +// + +import SwiftUI + +class MovieDetailsViewModel: ObservableObject { + @Published var movie: Movie? + @Published var movieImage: UIImage? + var movieID: String + + init(id movieID: String) { + self.movieID = movieID + } + + func getMovieDetails() { + APIManager.shared.execute(Movie.getMovieDetails(for: movieID)) { result in + switch result { + case .success(let movie): + DispatchQueue.main.async { + self.movie = movie + } + case .failure(let error): + print(error) + } + } + } + + func getImage() { + if let movie = movie { + Movie.getImage(for: movie) { image in + DispatchQueue.main.async { + self.movieImage = image + } + } + } + + } +} diff --git a/MovieSearch/MovieView.swift b/MovieSearch/MovieView.swift index 0388940..4a0fa56 100644 --- a/MovieSearch/MovieView.swift +++ b/MovieSearch/MovieView.swift @@ -14,7 +14,12 @@ struct MovieList: View { ScrollView { VStack(alignment: .leading) { ForEach($movies) { movie in + NavigationLink { + MovieDetails(viewModel: MovieDetailsViewModel(id: movie.id)) + } label: { MovieView(movie: movie) + } + Divider() .padding(.horizontal) } @@ -46,16 +51,10 @@ struct MovieView: View { } .padding() .onAppear { - getImage() - } - } - func getImage() { - let imageURL = URL(string: movie.poster) - DispatchQueue.global().async { - let data = try? Data(contentsOf: imageURL!) - DispatchQueue.main.async { - guard let data = data else { return } - self.image = UIImage(data: data) ?? UIImage(systemName: "photo")! + Movie.getImage(for: movie) { image in + DispatchQueue.main.async { + self.image = image + } } } } diff --git a/MovieSearch/SearchView.swift b/MovieSearch/SearchView.swift index d372c97..6764020 100644 --- a/MovieSearch/SearchView.swift +++ b/MovieSearch/SearchView.swift @@ -58,7 +58,7 @@ struct SearchView: View { .onDisappear { viewModel.saveHistory() } - .alert(Text("Error"), isPresented: $viewModel.error) { + .alert(Text("Movie details not found"), isPresented: $viewModel.error) { } .navigationTitle("Search Movies") diff --git a/MovieSearch/SearchViewModel.swift b/MovieSearch/SearchViewModel.swift index 0e7aa28..abe198c 100644 --- a/MovieSearch/SearchViewModel.swift +++ b/MovieSearch/SearchViewModel.swift @@ -47,12 +47,14 @@ class SearchViewModel: ObservableObject { switch result { case .success(let result): DispatchQueue.main.async { - self.movies = result.movies + self.movies = result.movies.sorted { $0.year > $1.year } self.showResult = true } case .failure(let error): print(error.localizedDescription) - self.error = true + DispatchQueue.main.async { + self.error = true + } } } } From 6a3a9e4492fd4ae5764dbd694c8278c8823b2b07 Mon Sep 17 00:00:00 2001 From: Ananth Jk Date: Sun, 23 Jan 2022 21:52:31 +0000 Subject: [PATCH 8/9] RemoteTest: Completed test cases --- MovieSearchTests/APITest.swift | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/MovieSearchTests/APITest.swift b/MovieSearchTests/APITest.swift index 5b13893..ed02375 100644 --- a/MovieSearchTests/APITest.swift +++ b/MovieSearchTests/APITest.swift @@ -17,9 +17,17 @@ class APITest: XCTestCase { } func test_full_url_builder() { - let request: Request = Request(method: .get, path: "/testing") - let url = URL("http://www.omdbapi.com", "testKey", request) - XCTAssertEqual(url.absoluteString, "http://www.omdbapi.com/testing?apikey=testKey") + let searchRequest: Request = Request(method: .get, parameter: .search, parameterValue: "aven", path: nil) + let searchUrl = URL("http://www.omdbapi.com", "testKey", searchRequest) + XCTAssertEqual(searchUrl.absoluteString, "http://www.omdbapi.com/?apikey=testKey&s=aven") + + let movieRequest: Request = Request(method: .get, parameter: .id, parameterValue: "12345", path: nil) + let movieUrl = URL("http://www.omdbapi.com", "testKey", movieRequest) + XCTAssertEqual(movieUrl.absoluteString, "http://www.omdbapi.com/?apikey=testKey&i=12345") + + let titleRequest: Request = Request(method: .get, parameter: .title, parameterValue: "avengers", path: nil) + let titleUrl = URL("http://www.omdbapi.com", "testKey", titleRequest) + XCTAssertEqual(titleUrl.absoluteString, "http://www.omdbapi.com/?apikey=testKey&t=avengers") } } From 597284304fbb74414bf9c7b6fb6047cd9a5dfea5 Mon Sep 17 00:00:00 2001 From: jkananth Date: Sun, 23 Jan 2022 22:28:04 +0000 Subject: [PATCH 9/9] RemoteTest: Updated read me file --- MovieSearch.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/MovieSearch.md b/MovieSearch.md index 0f709d2..b57b197 100644 --- a/MovieSearch.md +++ b/MovieSearch.md @@ -4,10 +4,12 @@ Lets you search for movies ## Overview -Text +Let you search for movies by name. ## Topics -### Group +### Technology Choise + +1. Used Swift UI instead of UI Kit just to showcase I can code in Swift UI as well. +2. Used User defaults to presist search history, as the information is not huge. -- ``Symbol``