From 401297de69bc50e0403d2fb44e9cdcd6e3200dcc Mon Sep 17 00:00:00 2001 From: reeshika-h Date: Wed, 5 Nov 2025 11:47:24 +0530 Subject: [PATCH] Add new test cases and update project file references --- ContentstackSwift.xcodeproj/project.pbxproj | 96 +++++ Tests/CSDefinitionsTest.swift | 214 ++++++++++ Tests/DecodableTest.swift | 444 ++++++++++++++++++++ Tests/EndPointTest.swift | 123 ++++++ Tests/ErrorTest.swift | 380 +++++++++++++++++ Tests/ImageTransformErrorTest.swift | 72 ++++ Tests/ParameterEncodingTest.swift | 335 +++++++++++++++ Tests/QueryOperationTest.swift | 325 ++++++++++++++ Tests/QueryParameterTest.swift | 221 ++++++++++ Tests/QueryableRangeTest.swift | 217 ++++++++++ Tests/StackInitializationTest.swift | 196 +++++++++ Tests/TaxonomyUnitTest.swift | 155 +++++++ Tests/XCTestManifests.swift | 14 +- 13 files changed, 2791 insertions(+), 1 deletion(-) create mode 100644 Tests/CSDefinitionsTest.swift create mode 100644 Tests/DecodableTest.swift create mode 100644 Tests/EndPointTest.swift create mode 100644 Tests/ErrorTest.swift create mode 100644 Tests/ImageTransformErrorTest.swift create mode 100644 Tests/ParameterEncodingTest.swift create mode 100644 Tests/QueryOperationTest.swift create mode 100644 Tests/QueryParameterTest.swift create mode 100644 Tests/QueryableRangeTest.swift create mode 100644 Tests/StackInitializationTest.swift create mode 100644 Tests/TaxonomyUnitTest.swift diff --git a/ContentstackSwift.xcodeproj/project.pbxproj b/ContentstackSwift.xcodeproj/project.pbxproj index 80d20c4d..c5bfbcea 100644 --- a/ContentstackSwift.xcodeproj/project.pbxproj +++ b/ContentstackSwift.xcodeproj/project.pbxproj @@ -269,6 +269,42 @@ 672F769A2E55ADBE00C248D6 /* AsyncAwaitAPITest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 672F76982E55ADBE00C248D6 /* AsyncAwaitAPITest.swift */; }; 672F769B2E55ADBE00C248D6 /* AsyncAwaitAPITest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 672F76982E55ADBE00C248D6 /* AsyncAwaitAPITest.swift */; }; 6750778E2D3E256A0076A066 /* DVR in Frameworks */ = {isa = PBXBuildFile; productRef = 6750778D2D3E256A0076A066 /* DVR */; }; + 67AA38EA2EB9D44800C0E2C0 /* CSDefinitionsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67AA38E92EB9D44800C0E2C0 /* CSDefinitionsTest.swift */; }; + 67AA38EB2EB9D44800C0E2C0 /* CSDefinitionsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67AA38E92EB9D44800C0E2C0 /* CSDefinitionsTest.swift */; }; + 67AA38EC2EB9D44800C0E2C0 /* CSDefinitionsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67AA38E92EB9D44800C0E2C0 /* CSDefinitionsTest.swift */; }; + 67AA38EE2EB9D46200C0E2C0 /* QueryParameterTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67AA38ED2EB9D46200C0E2C0 /* QueryParameterTest.swift */; }; + 67AA38EF2EB9D46200C0E2C0 /* QueryParameterTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67AA38ED2EB9D46200C0E2C0 /* QueryParameterTest.swift */; }; + 67AA38F02EB9D46200C0E2C0 /* QueryParameterTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67AA38ED2EB9D46200C0E2C0 /* QueryParameterTest.swift */; }; + 67AA38F22EB9D46800C0E2C0 /* QueryOperationTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67AA38F12EB9D46800C0E2C0 /* QueryOperationTest.swift */; }; + 67AA38F32EB9D46800C0E2C0 /* QueryOperationTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67AA38F12EB9D46800C0E2C0 /* QueryOperationTest.swift */; }; + 67AA38F42EB9D46800C0E2C0 /* QueryOperationTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67AA38F12EB9D46800C0E2C0 /* QueryOperationTest.swift */; }; + 67AA38F62EB9D46D00C0E2C0 /* QueryableRangeTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67AA38F52EB9D46D00C0E2C0 /* QueryableRangeTest.swift */; }; + 67AA38F72EB9D46D00C0E2C0 /* QueryableRangeTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67AA38F52EB9D46D00C0E2C0 /* QueryableRangeTest.swift */; }; + 67AA38F82EB9D46D00C0E2C0 /* QueryableRangeTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67AA38F52EB9D46D00C0E2C0 /* QueryableRangeTest.swift */; }; + 67AA38FA2EB9D47100C0E2C0 /* ParameterEncodingTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67AA38F92EB9D47100C0E2C0 /* ParameterEncodingTest.swift */; }; + 67AA38FB2EB9D47100C0E2C0 /* ParameterEncodingTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67AA38F92EB9D47100C0E2C0 /* ParameterEncodingTest.swift */; }; + 67AA38FC2EB9D47100C0E2C0 /* ParameterEncodingTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67AA38F92EB9D47100C0E2C0 /* ParameterEncodingTest.swift */; }; + 67AA38FE2EB9D47800C0E2C0 /* ImageTransformErrorTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67AA38FD2EB9D47800C0E2C0 /* ImageTransformErrorTest.swift */; }; + 67AA38FF2EB9D47800C0E2C0 /* ImageTransformErrorTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67AA38FD2EB9D47800C0E2C0 /* ImageTransformErrorTest.swift */; }; + 67AA39002EB9D47800C0E2C0 /* ImageTransformErrorTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67AA38FD2EB9D47800C0E2C0 /* ImageTransformErrorTest.swift */; }; + 67AA39022EB9D47C00C0E2C0 /* ErrorTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67AA39012EB9D47C00C0E2C0 /* ErrorTest.swift */; }; + 67AA39032EB9D47C00C0E2C0 /* ErrorTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67AA39012EB9D47C00C0E2C0 /* ErrorTest.swift */; }; + 67AA39042EB9D47C00C0E2C0 /* ErrorTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67AA39012EB9D47C00C0E2C0 /* ErrorTest.swift */; }; + 67AA39062EB9D48000C0E2C0 /* EndPointTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67AA39052EB9D48000C0E2C0 /* EndPointTest.swift */; }; + 67AA39072EB9D48000C0E2C0 /* EndPointTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67AA39052EB9D48000C0E2C0 /* EndPointTest.swift */; }; + 67AA39082EB9D48000C0E2C0 /* EndPointTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67AA39052EB9D48000C0E2C0 /* EndPointTest.swift */; }; + 67AA390A2EB9D48400C0E2C0 /* DecodableTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67AA39092EB9D48400C0E2C0 /* DecodableTest.swift */; }; + 67AA390B2EB9D48400C0E2C0 /* DecodableTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67AA39092EB9D48400C0E2C0 /* DecodableTest.swift */; }; + 67AA390C2EB9D48400C0E2C0 /* DecodableTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67AA39092EB9D48400C0E2C0 /* DecodableTest.swift */; }; + 67AA390E2EB9D49600C0E2C0 /* CSDefinitionsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67AA390D2EB9D49600C0E2C0 /* CSDefinitionsTest.swift */; }; + 67AA390F2EB9D49600C0E2C0 /* CSDefinitionsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67AA390D2EB9D49600C0E2C0 /* CSDefinitionsTest.swift */; }; + 67AA39102EB9D49600C0E2C0 /* CSDefinitionsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67AA390D2EB9D49600C0E2C0 /* CSDefinitionsTest.swift */; }; + 67AA39122EBA063300C0E2C0 /* TaxonomyUnitTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67AA39112EBA063300C0E2C0 /* TaxonomyUnitTest.swift */; }; + 67AA39132EBA063300C0E2C0 /* TaxonomyUnitTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67AA39112EBA063300C0E2C0 /* TaxonomyUnitTest.swift */; }; + 67AA39142EBA063300C0E2C0 /* TaxonomyUnitTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67AA39112EBA063300C0E2C0 /* TaxonomyUnitTest.swift */; }; + 67AA39162EBA065000C0E2C0 /* StackInitializationTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67AA39152EBA065000C0E2C0 /* StackInitializationTest.swift */; }; + 67AA39172EBA065000C0E2C0 /* StackInitializationTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67AA39152EBA065000C0E2C0 /* StackInitializationTest.swift */; }; + 67AA39182EBA065000C0E2C0 /* StackInitializationTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67AA39152EBA065000C0E2C0 /* StackInitializationTest.swift */; }; 67EE21DF2DDB4013005AC119 /* CSURLSessionDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67EE21DE2DDB3FFE005AC119 /* CSURLSessionDelegate.swift */; }; 67EE21E02DDB4013005AC119 /* CSURLSessionDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67EE21DE2DDB3FFE005AC119 /* CSURLSessionDelegate.swift */; }; 67EE21E12DDB4013005AC119 /* CSURLSessionDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67EE21DE2DDB3FFE005AC119 /* CSURLSessionDelegate.swift */; }; @@ -420,6 +456,18 @@ 47B4DC612C232A8200370CFC /* TaxonomyTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaxonomyTest.swift; sourceTree = ""; }; 47C6EFC12C0B5B9400F0D5CF /* Taxonomy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Taxonomy.swift; sourceTree = ""; }; 672F76982E55ADBE00C248D6 /* AsyncAwaitAPITest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AsyncAwaitAPITest.swift; sourceTree = ""; }; + 67AA38E92EB9D44800C0E2C0 /* CSDefinitionsTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CSDefinitionsTest.swift; sourceTree = ""; }; + 67AA38ED2EB9D46200C0E2C0 /* QueryParameterTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QueryParameterTest.swift; sourceTree = ""; }; + 67AA38F12EB9D46800C0E2C0 /* QueryOperationTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QueryOperationTest.swift; sourceTree = ""; }; + 67AA38F52EB9D46D00C0E2C0 /* QueryableRangeTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QueryableRangeTest.swift; sourceTree = ""; }; + 67AA38F92EB9D47100C0E2C0 /* ParameterEncodingTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParameterEncodingTest.swift; sourceTree = ""; }; + 67AA38FD2EB9D47800C0E2C0 /* ImageTransformErrorTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageTransformErrorTest.swift; sourceTree = ""; }; + 67AA39012EB9D47C00C0E2C0 /* ErrorTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorTest.swift; sourceTree = ""; }; + 67AA39052EB9D48000C0E2C0 /* EndPointTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EndPointTest.swift; sourceTree = ""; }; + 67AA39092EB9D48400C0E2C0 /* DecodableTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DecodableTest.swift; sourceTree = ""; }; + 67AA390D2EB9D49600C0E2C0 /* CSDefinitionsTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CSDefinitionsTest.swift; sourceTree = ""; }; + 67AA39112EBA063300C0E2C0 /* TaxonomyUnitTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaxonomyUnitTest.swift; sourceTree = ""; }; + 67AA39152EBA065000C0E2C0 /* StackInitializationTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StackInitializationTest.swift; sourceTree = ""; }; 67EE21DE2DDB3FFE005AC119 /* CSURLSessionDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CSURLSessionDelegate.swift; sourceTree = ""; }; 67EE222B2DE4868F005AC119 /* GlobalField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlobalField.swift; sourceTree = ""; }; 67EE22302DE58B51005AC119 /* GlobalFieldModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlobalFieldModel.swift; sourceTree = ""; }; @@ -649,10 +697,22 @@ 0FFA5D49241F4DED003B3AF5 /* ContentstackConfigTest.swift */, 0FFA5D88241F8113003B3AF5 /* StackTest.swift */, 0F4A7641241BB3C600E3A024 /* ContentstackTests.swift */, + 67AA390D2EB9D49600C0E2C0 /* CSDefinitionsTest.swift */, 0FFA5D9E241F8FFE003B3AF5 /* ContentTypeTest.swift */, 0F4FBC9F2420B0E4007B8CAE /* DateTest.swift */, 0F4FBCA82420B615007B8CAE /* UtilsTest.swift */, 0FD39D4924237A0400E34826 /* ContentTypeQueryTest.swift */, + 67AA38E92EB9D44800C0E2C0 /* CSDefinitionsTest.swift */, + 67AA38ED2EB9D46200C0E2C0 /* QueryParameterTest.swift */, + 67AA38F12EB9D46800C0E2C0 /* QueryOperationTest.swift */, + 67AA38F52EB9D46D00C0E2C0 /* QueryableRangeTest.swift */, + 67AA38F92EB9D47100C0E2C0 /* ParameterEncodingTest.swift */, + 67AA38FD2EB9D47800C0E2C0 /* ImageTransformErrorTest.swift */, + 67AA39012EB9D47C00C0E2C0 /* ErrorTest.swift */, + 67AA39052EB9D48000C0E2C0 /* EndPointTest.swift */, + 67AA39092EB9D48400C0E2C0 /* DecodableTest.swift */, + 67AA39112EBA063300C0E2C0 /* TaxonomyUnitTest.swift */, + 67AA39152EBA065000C0E2C0 /* StackInitializationTest.swift */, 0F7138C42424A70C00B314B0 /* AssetQueryTest.swift */, 0F7138CC2424A94000B314B0 /* QueryTest.swift */, 0F60CA2E2428949C00ED67E6 /* EntryTest.swift */, @@ -1143,13 +1203,19 @@ 4706575C2B5E78B300BBFF88 /* AssetQueryAPITest.swift in Sources */, 0F60CA2F2428949C00ED67E6 /* EntryTest.swift in Sources */, 0F244FA724406A4A003C3F26 /* EntryQueriableTest.swift in Sources */, + 67AA38EB2EB9D44800C0E2C0 /* CSDefinitionsTest.swift in Sources */, 0F463113243B044F001CE1FA /* SyncTest.swift in Sources */, + 67AA39142EBA063300C0E2C0 /* TaxonomyUnitTest.swift in Sources */, + 67AA38F72EB9D46D00C0E2C0 /* QueryableRangeTest.swift in Sources */, 0FFA5DBC241F9A6C003B3AF5 /* XCTestCase+Extension.swift in Sources */, 0F4FBCA02420B0E4007B8CAE /* DateTest.swift in Sources */, + 67AA390A2EB9D48400C0E2C0 /* DecodableTest.swift in Sources */, 0FFA5D4A241F4DED003B3AF5 /* ContentstackConfigTest.swift in Sources */, + 67AA39182EBA065000C0E2C0 /* StackInitializationTest.swift in Sources */, 67EE22382DE5BAFE005AC119 /* GlobalFieldAPITest.swift in Sources */, 47B4DC622C232A8200370CFC /* TaxonomyTest.swift in Sources */, 0F50EA1D244ED88C00E5D705 /* StackCacheAPITest.swift in Sources */, + 67AA38EE2EB9D46200C0E2C0 /* QueryParameterTest.swift in Sources */, 470657582B5E788400BBFF88 /* EntryAPITest.swift in Sources */, 672F76992E55ADBE00C248D6 /* AsyncAwaitAPITest.swift in Sources */, 0F096B14243610470094F042 /* ImageTransformTestAdditional.swift in Sources */, @@ -1158,16 +1224,22 @@ 0F77CFB824373B8A00C57764 /* ImageTransformEquatableTest.swift in Sources */, 0F02466B243201B500F72181 /* ImageTransformTest.swift in Sources */, 47AAE0902B60420E0098655A /* SyncAPITest.swift in Sources */, + 67AA390F2EB9D49600C0E2C0 /* CSDefinitionsTest.swift in Sources */, 470657542B5E785C00BBFF88 /* ContentTypeQueryAPITest.swift in Sources */, 470657602B5E797300BBFF88 /* ContentstackTest.swift in Sources */, 0F4FBCA92420B615007B8CAE /* UtilsTest.swift in Sources */, 0F7138CD2424A94000B314B0 /* QueryTest.swift in Sources */, + 67AA38FA2EB9D47100C0E2C0 /* ParameterEncodingTest.swift in Sources */, 0F50EA0E244EC3DD00E5D705 /* Session.swift in Sources */, 0FFA5D9F241F8FFE003B3AF5 /* ContentTypeTest.swift in Sources */, 0F4A7646241BB3CB00E3A024 /* ContentstackTests.swift in Sources */, + 67AA39072EB9D48000C0E2C0 /* EndPointTest.swift in Sources */, 0F7138C52424A70C00B314B0 /* AssetQueryTest.swift in Sources */, 0FFA5D8F241F8123003B3AF5 /* StackTest.swift in Sources */, + 67AA39022EB9D47C00C0E2C0 /* ErrorTest.swift in Sources */, + 67AA38F32EB9D46800C0E2C0 /* QueryOperationTest.swift in Sources */, 0FFA5DA3241F90BF003B3AF5 /* SutBuilder.swift in Sources */, + 67AA39002EB9D47800C0E2C0 /* ImageTransformErrorTest.swift in Sources */, 0F38D7E0242C7C9E00232D7F /* Product.swift in Sources */, 0F38D7E4242C831300232D7F /* AssetTest.swift in Sources */, ); @@ -1226,13 +1298,19 @@ 470657552B5E785C00BBFF88 /* ContentTypeQueryAPITest.swift in Sources */, 0F60CA302428949C00ED67E6 /* EntryTest.swift in Sources */, 0F244FA824406A4A003C3F26 /* EntryQueriableTest.swift in Sources */, + 67AA38EC2EB9D44800C0E2C0 /* CSDefinitionsTest.swift in Sources */, 0F463114243B044F001CE1FA /* SyncTest.swift in Sources */, + 67AA39132EBA063300C0E2C0 /* TaxonomyUnitTest.swift in Sources */, + 67AA38F62EB9D46D00C0E2C0 /* QueryableRangeTest.swift in Sources */, 47AAE0912B60420E0098655A /* SyncAPITest.swift in Sources */, 0FFA5DBD241F9A6C003B3AF5 /* XCTestCase+Extension.swift in Sources */, + 67AA390B2EB9D48400C0E2C0 /* DecodableTest.swift in Sources */, 0F4FBCA12420B0E4007B8CAE /* DateTest.swift in Sources */, + 67AA39162EBA065000C0E2C0 /* StackInitializationTest.swift in Sources */, 67EE22362DE5BAFE005AC119 /* GlobalFieldAPITest.swift in Sources */, 47B4DC632C232A8200370CFC /* TaxonomyTest.swift in Sources */, 0FFA5D90241F8126003B3AF5 /* ContentstackConfigTest.swift in Sources */, + 67AA38EF2EB9D46200C0E2C0 /* QueryParameterTest.swift in Sources */, 0F50EA1E244ED88C00E5D705 /* StackCacheAPITest.swift in Sources */, 672F769B2E55ADBE00C248D6 /* AsyncAwaitAPITest.swift in Sources */, 0F096B15243610470094F042 /* ImageTransformTestAdditional.swift in Sources */, @@ -1241,16 +1319,22 @@ 4706575D2B5E78B300BBFF88 /* AssetQueryAPITest.swift in Sources */, 0F77CFB924373B8F00C57764 /* ImageTransformEquatableTest.swift in Sources */, 0F02466C243201B500F72181 /* ImageTransformTest.swift in Sources */, + 67AA390E2EB9D49600C0E2C0 /* CSDefinitionsTest.swift in Sources */, 0F4FBCAA2420B615007B8CAE /* UtilsTest.swift in Sources */, 470657592B5E788400BBFF88 /* EntryAPITest.swift in Sources */, 0F50EA0F244EC3DD00E5D705 /* Session.swift in Sources */, 0F7138CE2424A94000B314B0 /* QueryTest.swift in Sources */, + 67AA38FB2EB9D47100C0E2C0 /* ParameterEncodingTest.swift in Sources */, 0FFA5DA0241F8FFE003B3AF5 /* ContentTypeTest.swift in Sources */, 0FFA5D8E241F8122003B3AF5 /* StackTest.swift in Sources */, 470657612B5E797300BBFF88 /* ContentstackTest.swift in Sources */, + 67AA39082EB9D48000C0E2C0 /* EndPointTest.swift in Sources */, 0F7138C62424A70C00B314B0 /* AssetQueryTest.swift in Sources */, 0F4A7647241BB3CC00E3A024 /* ContentstackTests.swift in Sources */, + 67AA39042EB9D47C00C0E2C0 /* ErrorTest.swift in Sources */, + 67AA38F22EB9D46800C0E2C0 /* QueryOperationTest.swift in Sources */, 0FFA5DA4241F90BF003B3AF5 /* SutBuilder.swift in Sources */, + 67AA38FF2EB9D47800C0E2C0 /* ImageTransformErrorTest.swift in Sources */, 0F38D7E1242C7C9E00232D7F /* Product.swift in Sources */, 0F38D7E5242C831A00232D7F /* AssetTest.swift in Sources */, ); @@ -1309,13 +1393,19 @@ 470657562B5E785C00BBFF88 /* ContentTypeQueryAPITest.swift in Sources */, 0F60CA312428949C00ED67E6 /* EntryTest.swift in Sources */, 0F244FA924406A4A003C3F26 /* EntryQueriableTest.swift in Sources */, + 67AA38EA2EB9D44800C0E2C0 /* CSDefinitionsTest.swift in Sources */, 0F463115243B044F001CE1FA /* SyncTest.swift in Sources */, + 67AA39122EBA063300C0E2C0 /* TaxonomyUnitTest.swift in Sources */, + 67AA38F82EB9D46D00C0E2C0 /* QueryableRangeTest.swift in Sources */, 47AAE0922B60420E0098655A /* SyncAPITest.swift in Sources */, 0FFA5DBE241F9A6C003B3AF5 /* XCTestCase+Extension.swift in Sources */, + 67AA390C2EB9D48400C0E2C0 /* DecodableTest.swift in Sources */, 0F4FBCA22420B0E4007B8CAE /* DateTest.swift in Sources */, + 67AA39172EBA065000C0E2C0 /* StackInitializationTest.swift in Sources */, 67EE22372DE5BAFE005AC119 /* GlobalFieldAPITest.swift in Sources */, 47B4DC642C232A8200370CFC /* TaxonomyTest.swift in Sources */, 0FFA5D91241F8127003B3AF5 /* ContentstackConfigTest.swift in Sources */, + 67AA38F02EB9D46200C0E2C0 /* QueryParameterTest.swift in Sources */, 0F50EA1F244ED88C00E5D705 /* StackCacheAPITest.swift in Sources */, 672F769A2E55ADBE00C248D6 /* AsyncAwaitAPITest.swift in Sources */, 0F096B16243610470094F042 /* ImageTransformTestAdditional.swift in Sources */, @@ -1324,16 +1414,22 @@ 4706575E2B5E78B300BBFF88 /* AssetQueryAPITest.swift in Sources */, 0F77CFBA24373B9000C57764 /* ImageTransformEquatableTest.swift in Sources */, 0F02466D243201B500F72181 /* ImageTransformTest.swift in Sources */, + 67AA39102EB9D49600C0E2C0 /* CSDefinitionsTest.swift in Sources */, 0F4FBCAB2420B615007B8CAE /* UtilsTest.swift in Sources */, 4706575A2B5E788400BBFF88 /* EntryAPITest.swift in Sources */, 0F50EA10244EC3DD00E5D705 /* Session.swift in Sources */, 0F7138CF2424A94000B314B0 /* QueryTest.swift in Sources */, + 67AA38FC2EB9D47100C0E2C0 /* ParameterEncodingTest.swift in Sources */, 0FFA5DA1241F8FFE003B3AF5 /* ContentTypeTest.swift in Sources */, 0FFA5D8D241F8122003B3AF5 /* StackTest.swift in Sources */, 470657622B5E797300BBFF88 /* ContentstackTest.swift in Sources */, + 67AA39062EB9D48000C0E2C0 /* EndPointTest.swift in Sources */, 0F7138C72424A70C00B314B0 /* AssetQueryTest.swift in Sources */, 0F4A7648241BB3CE00E3A024 /* ContentstackTests.swift in Sources */, + 67AA39032EB9D47C00C0E2C0 /* ErrorTest.swift in Sources */, + 67AA38F42EB9D46800C0E2C0 /* QueryOperationTest.swift in Sources */, 0FFA5DA5241F90BF003B3AF5 /* SutBuilder.swift in Sources */, + 67AA38FE2EB9D47800C0E2C0 /* ImageTransformErrorTest.swift in Sources */, 0F38D7E2242C7C9E00232D7F /* Product.swift in Sources */, 0F38D7E6242C831B00232D7F /* AssetTest.swift in Sources */, ); diff --git a/Tests/CSDefinitionsTest.swift b/Tests/CSDefinitionsTest.swift new file mode 100644 index 00000000..7b0933ea --- /dev/null +++ b/Tests/CSDefinitionsTest.swift @@ -0,0 +1,214 @@ +// +// CSDefinitionsTest.swift +// Contentstack +// +// Created for improved test coverage +// + +import XCTest +@testable import ContentstackSwift + +class CSDefinitionsTest: XCTestCase { + + // MARK: - HTTPMethod Tests + + func testHTTPMethod_get() { + let method = HTTPMethod.get + XCTAssertEqual(method.rawValue, "GET") + XCTAssertEqual(method.httpMethod, "GET") + } + + func testHTTPMethod_post() { + let method = HTTPMethod.post + XCTAssertEqual(method.rawValue, "POST") + XCTAssertEqual(method.httpMethod, "POST") + } + + func testHTTPMethod_put() { + let method = HTTPMethod.put + XCTAssertEqual(method.rawValue, "PUT") + XCTAssertEqual(method.httpMethod, "PUT") + } + + func testHTTPMethod_delete() { + let method = HTTPMethod.delete + XCTAssertEqual(method.rawValue, "DELETE") + XCTAssertEqual(method.httpMethod, "DELETE") + } + + // MARK: - ContentstackRegion Tests + + func testContentstackRegion_us() { + let region = ContentstackRegion.us + XCTAssertEqual(region.rawValue, "us") + } + + func testContentstackRegion_eu() { + let region = ContentstackRegion.eu + XCTAssertEqual(region.rawValue, "eu") + } + + func testContentstackRegion_azureNA() { + let region = ContentstackRegion.azure_na + XCTAssertEqual(region.rawValue, "azure-na") + } + + func testContentstackRegion_azureEU() { + let region = ContentstackRegion.azure_eu + XCTAssertEqual(region.rawValue, "azure-eu") + } + + func testContentstackRegion_gcpNA() { + let region = ContentstackRegion.gcp_na + XCTAssertEqual(region.rawValue, "gcp-na") + } + + func testContentstackRegion_gcpEU() { + let region = ContentstackRegion.gcp_eu + XCTAssertEqual(region.rawValue, "gcp-eu") + } + + func testContentstackRegion_au() { + let region = ContentstackRegion.au + XCTAssertEqual(region.rawValue, "au") + } + + func testContentstackRegion_equality() { + let region1 = ContentstackRegion.us + let region2 = ContentstackRegion.us + + XCTAssertEqual(region1, region2) + } + + func testContentstackRegion_inequality() { + let region1 = ContentstackRegion.us + let region2 = ContentstackRegion.eu + + XCTAssertNotEqual(region1, region2) + } + + // MARK: - CachePolicy Tests + + func testCachePolicy_networkOnly() { + let policy = CachePolicy.networkOnly + + switch policy { + case .networkOnly: + XCTAssertTrue(true) + default: + XCTFail("Expected networkOnly policy") + } + } + + func testCachePolicy_cacheOnly() { + let policy = CachePolicy.cacheOnly + + switch policy { + case .cacheOnly: + XCTAssertTrue(true) + default: + XCTFail("Expected cacheOnly policy") + } + } + + func testCachePolicy_cacheElseNetwork() { + let policy = CachePolicy.cacheElseNetwork + + switch policy { + case .cacheElseNetwork: + XCTAssertTrue(true) + default: + XCTFail("Expected cacheElseNetwork policy") + } + } + + func testCachePolicy_networkElseCache() { + let policy = CachePolicy.networkElseCache + + switch policy { + case .networkElseCache: + XCTAssertTrue(true) + default: + XCTFail("Expected networkElseCache policy") + } + } + + func testCachePolicy_cacheThenNetwork() { + let policy = CachePolicy.cacheThenNetwork + + switch policy { + case .cacheThenNetwork: + XCTAssertTrue(true) + default: + XCTFail("Expected cacheThenNetwork policy") + } + } + + // MARK: - ResponseType Tests + + func testResponseType_cache() { + let responseType = ResponseType.cache + + switch responseType { + case .cache: + XCTAssertTrue(true) + default: + XCTFail("Expected cache response type") + } + } + + func testResponseType_network() { + let responseType = ResponseType.network + + switch responseType { + case .network: + XCTAssertTrue(true) + default: + XCTFail("Expected network response type") + } + } + + // MARK: - All Regions Test + + func testAllRegions_uniqueRawValues() { + let regions = [ + ContentstackRegion.us, + ContentstackRegion.eu, + ContentstackRegion.azure_na, + ContentstackRegion.azure_eu, + ContentstackRegion.gcp_na, + ContentstackRegion.gcp_eu, + ContentstackRegion.au + ] + + let rawValues = regions.map { $0.rawValue } + let uniqueRawValues = Set(rawValues) + + XCTAssertEqual(rawValues.count, uniqueRawValues.count, "All regions should have unique raw values") + } + + static var allTests = [ + ("testHTTPMethod_get", testHTTPMethod_get), + ("testHTTPMethod_post", testHTTPMethod_post), + ("testHTTPMethod_put", testHTTPMethod_put), + ("testHTTPMethod_delete", testHTTPMethod_delete), + ("testContentstackRegion_us", testContentstackRegion_us), + ("testContentstackRegion_eu", testContentstackRegion_eu), + ("testContentstackRegion_azureNA", testContentstackRegion_azureNA), + ("testContentstackRegion_azureEU", testContentstackRegion_azureEU), + ("testContentstackRegion_gcpNA", testContentstackRegion_gcpNA), + ("testContentstackRegion_gcpEU", testContentstackRegion_gcpEU), + ("testContentstackRegion_au", testContentstackRegion_au), + ("testContentstackRegion_equality", testContentstackRegion_equality), + ("testContentstackRegion_inequality", testContentstackRegion_inequality), + ("testCachePolicy_networkOnly", testCachePolicy_networkOnly), + ("testCachePolicy_cacheOnly", testCachePolicy_cacheOnly), + ("testCachePolicy_cacheElseNetwork", testCachePolicy_cacheElseNetwork), + ("testCachePolicy_networkElseCache", testCachePolicy_networkElseCache), + ("testCachePolicy_cacheThenNetwork", testCachePolicy_cacheThenNetwork), + ("testResponseType_cache", testResponseType_cache), + ("testResponseType_network", testResponseType_network), + ("testAllRegions_uniqueRawValues", testAllRegions_uniqueRawValues) + ] +} + diff --git a/Tests/DecodableTest.swift b/Tests/DecodableTest.swift new file mode 100644 index 00000000..eb4b7487 --- /dev/null +++ b/Tests/DecodableTest.swift @@ -0,0 +1,444 @@ +// +// DecodableTest.swift +// Contentstack +// +// Created for improved test coverage +// + +import XCTest +@testable import ContentstackSwift + +class DecodableTest: XCTestCase { + + // MARK: - JSONDecoder dateDecodingStrategy Tests + + func testJSONDecoder_dateDecodingStrategy() { + let decoder = JSONDecoder.dateDecodingStrategy() + + XCTAssertNotNil(decoder) + // Verify it's configured correctly + XCTAssertTrue(decoder is JSONDecoder) + } + + func testJSONDecoder_dateDecodingStrategy_withISO8601Date() { + let json = """ + { + "created_at": "2021-01-01T00:00:00.000Z" + } + """ + + struct TestModel: Decodable { + let created_at: Date + } + + let data = json.data(using: .utf8)! + let decoder = JSONDecoder.dateDecodingStrategy() + + do { + let model = try decoder.decode(TestModel.self, from: data) + XCTAssertNotNil(model.created_at) + } catch { + XCTFail("Failed to decode date: \(error)") + } + } + + // MARK: - JSONCodingKeys Tests + + func testJSONCodingKeys_stringValue() { + let key = JSONCodingKeys(stringValue: "test_key") + + XCTAssertNotNil(key) + XCTAssertEqual(key?.stringValue, "test_key") + } + + func testJSONCodingKeys_intValue() { + let key = JSONCodingKeys(intValue: 42) + + XCTAssertNotNil(key) + XCTAssertEqual(key?.intValue, 42) + XCTAssertEqual(key?.stringValue, "42") + } + + func testJSONCodingKeys_intValueToStringValue() { + let key = JSONCodingKeys(intValue: 100) + + XCTAssertEqual(key?.stringValue, "100") + } + + // MARK: - CodingUserInfoKey Tests + + func testCodingUserInfoKey_linkResolverContextKey() { + let key = CodingUserInfoKey.linkResolverContextKey + + XCTAssertNotNil(key) + XCTAssertEqual(key.rawValue, "linkResolverContext") + } + + func testCodingUserInfoKey_timeZoneContextKey() { + let key = CodingUserInfoKey.timeZoneContextKey + + XCTAssertNotNil(key) + XCTAssertEqual(key.rawValue, "timeZoneContext") + } + + func testCodingUserInfoKey_contentTypesContextKey() { + let key = CodingUserInfoKey.contentTypesContextKey + + XCTAssertNotNil(key) + XCTAssertEqual(key.rawValue, "contentTypesContext") + } + + func testCodingUserInfoKey_localizationContextKey() { + let key = CodingUserInfoKey.localizationContextKey + + XCTAssertNotNil(key) + XCTAssertEqual(key.rawValue, "localizationContext") + } + + // MARK: - Decoder Extension Tests + + func testDecoder_timeZone() { + struct TestContainer: Decodable { + let testValue: String + var decoderTimeZone: TimeZone? + + init(from decoder: Decoder) throws { + self.decoderTimeZone = decoder.timeZone + let container = try decoder.container(keyedBy: CodingKeys.self) + self.testValue = try container.decode(String.self, forKey: .testValue) + } + + enum CodingKeys: String, CodingKey { + case testValue + } + } + + let json = """ + { + "testValue": "test" + } + """ + + let data = json.data(using: .utf8)! + let decoder = JSONDecoder() + decoder.userInfo[.timeZoneContextKey] = TimeZone(identifier: "America/New_York") + + do { + let model = try decoder.decode(TestContainer.self, from: data) + XCTAssertNotNil(model.decoderTimeZone) + XCTAssertEqual(model.decoderTimeZone?.identifier, "America/New_York") + } catch { + XCTFail("Failed to decode: \(error)") + } + } + + func testDecoder_timeZone_nil() { + struct TestContainer: Decodable { + let testValue: String + var decoderTimeZone: TimeZone? + + init(from decoder: Decoder) throws { + self.decoderTimeZone = decoder.timeZone + let container = try decoder.container(keyedBy: CodingKeys.self) + self.testValue = try container.decode(String.self, forKey: .testValue) + } + + enum CodingKeys: String, CodingKey { + case testValue + } + } + + let json = """ + { + "testValue": "test" + } + """ + + let data = json.data(using: .utf8)! + let decoder = JSONDecoder() + + do { + let model = try decoder.decode(TestContainer.self, from: data) + XCTAssertNil(model.decoderTimeZone) + } catch { + XCTFail("Failed to decode: \(error)") + } + } + + // MARK: - KeyedDecodingContainer Dictionary Decoding Tests + + func testKeyedDecodingContainer_decodeDictionary() { + struct TestModel: Decodable { + let data: [String: Any] + + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + self.data = try container.decode([String: Any].self, forKey: .data) + } + + enum CodingKeys: String, CodingKey { + case data + } + } + + let json = """ + { + "data": { + "name": "John", + "age": 30, + "active": true + } + } + """ + + let data = json.data(using: .utf8)! + let decoder = JSONDecoder() + + do { + let model = try decoder.decode(TestModel.self, from: data) + XCTAssertEqual(model.data["name"] as? String, "John") + XCTAssertEqual(model.data["age"] as? Int, 30) + XCTAssertEqual(model.data["active"] as? Bool, true) + } catch { + XCTFail("Failed to decode dictionary: \(error)") + } + } + + func testKeyedDecodingContainer_decodeIfPresentDictionary() { + struct TestModel: Decodable { + let data: [String: Any]? + + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + self.data = try container.decodeIfPresent([String: Any].self, forKey: .data) + } + + enum CodingKeys: String, CodingKey { + case data + } + } + + let json = """ + { + "data": { + "name": "John" + } + } + """ + + let data = json.data(using: .utf8)! + let decoder = JSONDecoder() + + do { + let model = try decoder.decode(TestModel.self, from: data) + XCTAssertNotNil(model.data) + XCTAssertEqual(model.data?["name"] as? String, "John") + } catch { + XCTFail("Failed to decode: \(error)") + } + } + + func testKeyedDecodingContainer_decodeIfPresentDictionary_missing() { + struct TestModel: Decodable { + let data: [String: Any]? + + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + self.data = try container.decodeIfPresent([String: Any].self, forKey: .data) + } + + enum CodingKeys: String, CodingKey { + case data + } + } + + let json = """ + { + "other_field": "value" + } + """ + + let data = json.data(using: .utf8)! + let decoder = JSONDecoder() + + do { + let model = try decoder.decode(TestModel.self, from: data) + XCTAssertNil(model.data) + } catch { + XCTFail("Failed to decode: \(error)") + } + } + + // MARK: - KeyedDecodingContainer Array Decoding Tests + + func testKeyedDecodingContainer_decodeArray() { + struct TestModel: Decodable { + let items: [Any] + + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + self.items = try container.decode([Any].self, forKey: .items) + } + + enum CodingKeys: String, CodingKey { + case items + } + } + + let json = """ + { + "items": [1, "text", true, 3.14] + } + """ + + let data = json.data(using: .utf8)! + let decoder = JSONDecoder() + + do { + let model = try decoder.decode(TestModel.self, from: data) + XCTAssertEqual(model.items.count, 4) + } catch { + XCTFail("Failed to decode array: \(error)") + } + } + + func testKeyedDecodingContainer_decodeIfPresentArray() { + struct TestModel: Decodable { + let items: [Any]? + + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + self.items = try container.decodeIfPresent([Any].self, forKey: .items) + } + + enum CodingKeys: String, CodingKey { + case items + } + } + + let json = """ + { + "items": [1, 2, 3] + } + """ + + let data = json.data(using: .utf8)! + let decoder = JSONDecoder() + + do { + let model = try decoder.decode(TestModel.self, from: data) + XCTAssertNotNil(model.items) + XCTAssertEqual(model.items?.count, 3) + } catch { + XCTFail("Failed to decode: \(error)") + } + } + + // MARK: - KeyedDecodingContainer Complex Types Tests + + func testKeyedDecodingContainer_decodeNestedDictionaries() { + struct TestModel: Decodable { + let nested: [String: Any] + + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + self.nested = try container.decode([String: Any].self, forKey: .nested) + } + + enum CodingKeys: String, CodingKey { + case nested + } + } + + let json = """ + { + "nested": { + "level1": { + "level2": "value" + } + } + } + """ + + let data = json.data(using: .utf8)! + let decoder = JSONDecoder() + + do { + let model = try decoder.decode(TestModel.self, from: data) + let level1 = model.nested["level1"] as? [String: Any] + XCTAssertNotNil(level1) + XCTAssertEqual(level1?["level2"] as? String, "value") + } catch { + XCTFail("Failed to decode nested dictionary: \(error)") + } + } + + func testKeyedDecodingContainer_decodeMixedTypes() { + struct TestModel: Decodable { + let data: [String: Any] + + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + self.data = try container.decode([String: Any].self, forKey: .data) + } + + enum CodingKeys: String, CodingKey { + case data + } + } + + let json = """ + { + "data": { + "string": "text", + "int": 42, + "double": 3.14, + "bool": true, + "array": [1, 2, 3], + "nested": {"key": "value"} + } + } + """ + + let data = json.data(using: .utf8)! + let decoder = JSONDecoder() + + do { + let model = try decoder.decode(TestModel.self, from: data) + XCTAssertEqual(model.data["string"] as? String, "text") + XCTAssertEqual(model.data["int"] as? Int, 42) + if let doubleValue = model.data["double"] as? Double { + XCTAssertEqual(doubleValue, 3.14, accuracy: 0.001) + } else { + XCTFail("Double value not found or wrong type") + } + XCTAssertEqual(model.data["bool"] as? Bool, true) + XCTAssertNotNil(model.data["array"]) + XCTAssertNotNil(model.data["nested"]) + } catch { + XCTFail("Failed to decode mixed types: \(error)") + } + } + + static var allTests = [ + ("testJSONDecoder_dateDecodingStrategy", testJSONDecoder_dateDecodingStrategy), + ("testJSONDecoder_dateDecodingStrategy_withISO8601Date", testJSONDecoder_dateDecodingStrategy_withISO8601Date), + ("testJSONCodingKeys_stringValue", testJSONCodingKeys_stringValue), + ("testJSONCodingKeys_intValue", testJSONCodingKeys_intValue), + ("testJSONCodingKeys_intValueToStringValue", testJSONCodingKeys_intValueToStringValue), + ("testCodingUserInfoKey_linkResolverContextKey", testCodingUserInfoKey_linkResolverContextKey), + ("testCodingUserInfoKey_timeZoneContextKey", testCodingUserInfoKey_timeZoneContextKey), + ("testCodingUserInfoKey_contentTypesContextKey", testCodingUserInfoKey_contentTypesContextKey), + ("testCodingUserInfoKey_localizationContextKey", testCodingUserInfoKey_localizationContextKey), + ("testDecoder_timeZone", testDecoder_timeZone), + ("testDecoder_timeZone_nil", testDecoder_timeZone_nil), + ("testKeyedDecodingContainer_decodeDictionary", testKeyedDecodingContainer_decodeDictionary), + ("testKeyedDecodingContainer_decodeIfPresentDictionary", testKeyedDecodingContainer_decodeIfPresentDictionary), + ("testKeyedDecodingContainer_decodeIfPresentDictionary_missing", testKeyedDecodingContainer_decodeIfPresentDictionary_missing), + ("testKeyedDecodingContainer_decodeArray", testKeyedDecodingContainer_decodeArray), + ("testKeyedDecodingContainer_decodeIfPresentArray", testKeyedDecodingContainer_decodeIfPresentArray), + ("testKeyedDecodingContainer_decodeNestedDictionaries", testKeyedDecodingContainer_decodeNestedDictionaries), + ("testKeyedDecodingContainer_decodeMixedTypes", testKeyedDecodingContainer_decodeMixedTypes) + ] +} + diff --git a/Tests/EndPointTest.swift b/Tests/EndPointTest.swift new file mode 100644 index 00000000..58be9417 --- /dev/null +++ b/Tests/EndPointTest.swift @@ -0,0 +1,123 @@ +// +// EndPointTest.swift +// Contentstack +// +// Created for improved test coverage +// + +import XCTest +@testable import ContentstackSwift + +class EndPointTest: XCTestCase { + + // MARK: - Endpoint Tests + + func testEndpoint_stack() { + let endpoint = Endpoint.stack + XCTAssertEqual(endpoint.rawValue, "stack") + XCTAssertEqual(endpoint.pathComponent, "stack") + } + + func testEndpoint_contenttype() { + let endpoint = Endpoint.contenttype + XCTAssertEqual(endpoint.rawValue, "content_types") + XCTAssertEqual(endpoint.pathComponent, "content_types") + } + + func testEndpoint_entries() { + let endpoint = Endpoint.entries + XCTAssertEqual(endpoint.rawValue, "entries") + XCTAssertEqual(endpoint.pathComponent, "entries") + } + + func testEndpoint_assets() { + let endpoint = Endpoint.assets + XCTAssertEqual(endpoint.rawValue, "assets") + XCTAssertEqual(endpoint.pathComponent, "assets") + } + + func testEndpoint_sync() { + let endpoint = Endpoint.sync + XCTAssertEqual(endpoint.rawValue, "stacks/sync") + XCTAssertEqual(endpoint.pathComponent, "stacks/sync") + } + + func testEndpoint_taxonomies() { + let endpoint = Endpoint.taxnomies + XCTAssertEqual(endpoint.rawValue, "taxonomies") + XCTAssertEqual(endpoint.pathComponent, "taxonomies") + } + + func testEndpoint_globalfields() { + let endpoint = Endpoint.globalfields + XCTAssertEqual(endpoint.rawValue, "global_fields") + XCTAssertEqual(endpoint.pathComponent, "global_fields") + } + + // MARK: - Endpoint Comparison Tests + + func testEndpoint_equality() { + let endpoint1 = Endpoint.entries + let endpoint2 = Endpoint.entries + + XCTAssertEqual(endpoint1, endpoint2) + } + + func testEndpoint_inequality() { + let endpoint1 = Endpoint.entries + let endpoint2 = Endpoint.assets + + XCTAssertNotEqual(endpoint1, endpoint2) + } + + // MARK: - All Endpoints Test + + func testAllEndpoints_uniqueRawValues() { + let endpoints = [ + Endpoint.stack, + Endpoint.contenttype, + Endpoint.entries, + Endpoint.assets, + Endpoint.sync, + Endpoint.taxnomies, + Endpoint.globalfields + ] + + let rawValues = endpoints.map { $0.rawValue } + let uniqueRawValues = Set(rawValues) + + XCTAssertEqual(rawValues.count, uniqueRawValues.count, "All endpoints should have unique raw values") + } + + func testAllEndpoints_uniquePathComponents() { + let endpoints = [ + Endpoint.stack, + Endpoint.contenttype, + Endpoint.entries, + Endpoint.assets, + Endpoint.sync, + Endpoint.taxnomies, + Endpoint.globalfields + ] + + let pathComponents = endpoints.map { $0.pathComponent } + let uniquePathComponents = Set(pathComponents) + + XCTAssertEqual(pathComponents.count, uniquePathComponents.count, "All endpoints should have unique path components") + } + + static var allTests = [ + ("testEndpoint_stack", testEndpoint_stack), + ("testEndpoint_contenttype", testEndpoint_contenttype), + ("testEndpoint_entries", testEndpoint_entries), + ("testEndpoint_assets", testEndpoint_assets), + ("testEndpoint_sync", testEndpoint_sync), + ("testEndpoint_taxonomies", testEndpoint_taxonomies), + ("testEndpoint_globalfields", testEndpoint_globalfields), + ("testEndpoint_equality", testEndpoint_equality), + ("testEndpoint_inequality", testEndpoint_inequality), + ("testAllEndpoints_uniqueRawValues", testAllEndpoints_uniqueRawValues), + ("testAllEndpoints_uniquePathComponents", testAllEndpoints_uniquePathComponents) + ] +} + diff --git a/Tests/ErrorTest.swift b/Tests/ErrorTest.swift new file mode 100644 index 00000000..5e200112 --- /dev/null +++ b/Tests/ErrorTest.swift @@ -0,0 +1,380 @@ +// +// ErrorTest.swift +// Contentstack +// +// Created for improved test coverage +// + +import XCTest +@testable import ContentstackSwift + +class ErrorTest: XCTestCase { + + // MARK: - SDKError Tests + + func testSDKError_invalidHTTPResponse() { + let response = URLResponse(url: URL(string: "https://example.com")!, + mimeType: nil, + expectedContentLength: 0, + textEncodingName: nil) + let error = SDKError.invalidHTTPResponse(response: response) + + XCTAssertTrue(error.message.contains("corrupted HTTP response")) + XCTAssertEqual(error.debugDescription, error.message) + } + + func testSDKError_invalidHTTPResponse_nil() { + let error = SDKError.invalidHTTPResponse(response: nil) + + XCTAssertTrue(error.message.contains("corrupted HTTP response")) + XCTAssertTrue(error.message.contains("nil")) + } + + func testSDKError_invalidURL() { + let invalidURLString = "not a valid url" + let error = SDKError.invalidURL(string: invalidURLString) + + XCTAssertEqual(error.message, invalidURLString) + XCTAssertEqual(error.debugDescription, invalidURLString) + } + + func testSDKError_invalidUID() { + let invalidUID = "invalid_uid_123" + let error = SDKError.invalidUID(string: invalidUID) + + XCTAssertEqual(error.message, "The uid \(invalidUID) is not valid.") + XCTAssertTrue(error.message.contains(invalidUID)) + } + + func testSDKError_unparseableJSON() { + let data = "invalid json".data(using: .utf8) + let errorMessage = "Failed to parse JSON" + let error = SDKError.unparseableJSON(data: data, errorMessage: errorMessage) + + XCTAssertEqual(error.message, errorMessage) + } + + func testSDKError_unparseableJSON_nilData() { + let errorMessage = "Failed to parse JSON with nil data" + let error = SDKError.unparseableJSON(data: nil, errorMessage: errorMessage) + + XCTAssertEqual(error.message, errorMessage) + } + + func testSDKError_stackError() { + let error = SDKError.stackError + + XCTAssertEqual(error.message, "The Stack not found.") + } + + func testSDKError_syncError() { + let error = SDKError.syncError + + XCTAssertEqual(error.message, "The Stack sync faile to retrive.") + } + + func testSDKError_cacheError() { + let error = SDKError.cacheError + + XCTAssertEqual(error.message, "Failed to retreive data from Cache.") + } + + // MARK: - APIError Tests + + func testAPIError_decoding() { + let json = """ + { + "error_message": "The access token is invalid.", + "error_code": 104, + "errors": { + "access_token": ["Invalid access token"] + } + } + """ + + let data = json.data(using: .utf8)! + let decoder = JSONDecoder() + + do { + let apiError = try decoder.decode(APIError.self, from: data) + XCTAssertEqual(apiError.errorMessage, "The access token is invalid.") + XCTAssertEqual(apiError.errorCode, 104) + XCTAssertNotNil(apiError.errorInfo) + XCTAssertEqual(apiError.errorInfo.deliveryToken?.first, "Invalid access token") + } catch { + XCTFail("Failed to decode APIError: \(error)") + } + } + + func testAPIError_withAPIKey() { + let json = """ + { + "error_message": "Invalid API key", + "error_code": 105, + "errors": { + "api_key": ["The API key is not valid"] + } + } + """ + + let data = json.data(using: .utf8)! + let decoder = JSONDecoder() + + do { + let apiError = try decoder.decode(APIError.self, from: data) + XCTAssertEqual(apiError.errorMessage, "Invalid API key") + XCTAssertEqual(apiError.errorCode, 105) + XCTAssertNotNil(apiError.errorInfo.apiKey) + XCTAssertEqual(apiError.errorInfo.apiKey?.first, "The API key is not valid") + } catch { + XCTFail("Failed to decode APIError: \(error)") + } + } + + func testAPIError_withEnvironment() { + let json = """ + { + "error_message": "Invalid environment", + "error_code": 106, + "errors": { + "environment": ["The environment is not valid"] + } + } + """ + + let data = json.data(using: .utf8)! + let decoder = JSONDecoder() + + do { + let apiError = try decoder.decode(APIError.self, from: data) + XCTAssertNotNil(apiError.errorInfo.environment) + XCTAssertEqual(apiError.errorInfo.environment?.first, "The environment is not valid") + } catch { + XCTFail("Failed to decode APIError: \(error)") + } + } + + func testAPIError_withUID() { + let json = """ + { + "error_message": "Invalid UID", + "error_code": 107, + "errors": { + "uid": ["The UID is not valid"] + } + } + """ + + let data = json.data(using: .utf8)! + let decoder = JSONDecoder() + + do { + let apiError = try decoder.decode(APIError.self, from: data) + XCTAssertNotNil(apiError.errorInfo.uid) + XCTAssertEqual(apiError.errorInfo.uid?.first, "The UID is not valid") + } catch { + XCTFail("Failed to decode APIError: \(error)") + } + } + + func testAPIError_withAuthtoken() { + let json = """ + { + "error_message": "Invalid authtoken", + "error_code": 108, + "errors": { + "authtoken": ["The authtoken is not valid"] + } + } + """ + + let data = json.data(using: .utf8)! + let decoder = JSONDecoder() + + do { + let apiError = try decoder.decode(APIError.self, from: data) + // authtoken should map to apiKey + XCTAssertNotNil(apiError.errorInfo.apiKey) + XCTAssertEqual(apiError.errorInfo.apiKey?.first, "The authtoken is not valid") + } catch { + XCTFail("Failed to decode APIError: \(error)") + } + } + + func testAPIError_debugDescription() { + let json = """ + { + "error_message": "Test error", + "error_code": 999, + "errors": { + "api_key": ["Error 1"], + "access_token": ["Error 2"] + } + } + """ + + let data = json.data(using: .utf8)! + let decoder = JSONDecoder() + + do { + let apiError = try decoder.decode(APIError.self, from: data) + apiError.statusCode = 400 + + let debugDescription = apiError.debugDescription + XCTAssertTrue(debugDescription.contains("HTTP status code 400")) + XCTAssertTrue(debugDescription.contains("Test error")) + XCTAssertTrue(debugDescription.contains("999")) + } catch { + XCTFail("Failed to decode APIError: \(error)") + } + } + + func testAPIError_errorInfo_debugDescription() { + let json = """ + { + "error_message": "Multiple errors", + "error_code": 999, + "errors": { + "api_key": ["API Key Error"], + "access_token": ["Token Error"], + "environment": ["Env Error"], + "uid": ["UID Error"] + } + } + """ + + let data = json.data(using: .utf8)! + let decoder = JSONDecoder() + + do { + let apiError = try decoder.decode(APIError.self, from: data) + let errorInfoDebug = apiError.errorInfo.debugDescription + + XCTAssertTrue(errorInfoDebug.contains("API Key")) + XCTAssertTrue(errorInfoDebug.contains("Delivery token")) + XCTAssertTrue(errorInfoDebug.contains("Environment")) + XCTAssertTrue(errorInfoDebug.contains("UID")) + } catch { + XCTFail("Failed to decode APIError: \(error)") + } + } + + func testAPIError_errorWithDecoder() { + let json = """ + { + "error_message": "Test error", + "error_code": 999, + "errors": { + "api_key": ["Error"] + } + } + """ + + let data = json.data(using: .utf8)! + let decoder = JSONDecoder() + + let apiError = APIError.error(with: decoder, data: data, statusCode: 400) + + XCTAssertNotNil(apiError) + XCTAssertEqual(apiError?.errorMessage, "Test error") + XCTAssertEqual(apiError?.statusCode, 400) + } + + func testAPIError_errorWithDecoder_invalidData() { + let invalidData = "not valid json".data(using: .utf8)! + let decoder = JSONDecoder() + + let apiError = APIError.error(with: decoder, data: invalidData, statusCode: 400) + + XCTAssertNil(apiError) + } + + func testAPIError_errorWithDecoder_missingErrorInfo() { + let json = """ + { + "error_message": "Test error", + "error_code": 999 + } + """ + + let data = json.data(using: .utf8)! + let decoder = JSONDecoder() + + // This should fail because errorInfo is required + do { + _ = try decoder.decode(APIError.self, from: data) + XCTFail("Should have thrown an error") + } catch { + // Expected to fail + XCTAssertTrue(true) + } + } + + func testAPIError_handleError_withValidAPIError() { + let json = """ + { + "error_message": "Test API error", + "error_code": 999, + "errors": { + "api_key": ["Error"] + } + } + """ + + let data = json.data(using: .utf8)! + let decoder = JSONDecoder() + let url = URL(string: "https://api.contentstack.io/v3/content_types")! + let response = HTTPURLResponse(url: url, statusCode: 400, httpVersion: nil, headerFields: nil)! + + let error = APIError.handleError(for: url, jsonDecoder: decoder, data: data, response: response) + + XCTAssertTrue(error is APIError) + if let apiError = error as? APIError { + XCTAssertEqual(apiError.errorMessage, "Test API error") + XCTAssertEqual(apiError.statusCode, 400) + } + } + + func testAPIError_handleError_withInvalidData() { + let invalidData = "not valid json".data(using: .utf8)! + let decoder = JSONDecoder() + let url = URL(string: "https://api.contentstack.io/v3/content_types")! + let response = HTTPURLResponse(url: url, statusCode: 500, httpVersion: nil, headerFields: nil)! + + let error = APIError.handleError(for: url, jsonDecoder: decoder, data: invalidData, response: response) + + XCTAssertTrue(error is SDKError) + if let sdkError = error as? SDKError { + if case let .unparseableJSON(_, errorMessage) = sdkError { + XCTAssertTrue(errorMessage.contains("unable to parse")) + } else { + XCTFail("Expected unparseableJSON error") + } + } + } + + static var allTests = [ + ("testSDKError_invalidHTTPResponse", testSDKError_invalidHTTPResponse), + ("testSDKError_invalidHTTPResponse_nil", testSDKError_invalidHTTPResponse_nil), + ("testSDKError_invalidURL", testSDKError_invalidURL), + ("testSDKError_invalidUID", testSDKError_invalidUID), + ("testSDKError_unparseableJSON", testSDKError_unparseableJSON), + ("testSDKError_unparseableJSON_nilData", testSDKError_unparseableJSON_nilData), + ("testSDKError_stackError", testSDKError_stackError), + ("testSDKError_syncError", testSDKError_syncError), + ("testSDKError_cacheError", testSDKError_cacheError), + ("testAPIError_decoding", testAPIError_decoding), + ("testAPIError_withAPIKey", testAPIError_withAPIKey), + ("testAPIError_withEnvironment", testAPIError_withEnvironment), + ("testAPIError_withUID", testAPIError_withUID), + ("testAPIError_withAuthtoken", testAPIError_withAuthtoken), + ("testAPIError_debugDescription", testAPIError_debugDescription), + ("testAPIError_errorInfo_debugDescription", testAPIError_errorInfo_debugDescription), + ("testAPIError_errorWithDecoder", testAPIError_errorWithDecoder), + ("testAPIError_errorWithDecoder_invalidData", testAPIError_errorWithDecoder_invalidData), + ("testAPIError_errorWithDecoder_missingErrorInfo", testAPIError_errorWithDecoder_missingErrorInfo), + ("testAPIError_handleError_withValidAPIError", testAPIError_handleError_withValidAPIError), + ("testAPIError_handleError_withInvalidData", testAPIError_handleError_withInvalidData) + ] +} + diff --git a/Tests/ImageTransformErrorTest.swift b/Tests/ImageTransformErrorTest.swift new file mode 100644 index 00000000..ee3961f0 --- /dev/null +++ b/Tests/ImageTransformErrorTest.swift @@ -0,0 +1,72 @@ +// +// ImageTransformErrorTest.swift +// Contentstack +// +// Created for improved test coverage +// + +import XCTest +@testable import ContentstackSwift + +class ImageTransformErrorTest: XCTestCase { + + // MARK: - ImageTransformError Tests + + func testImageTransformError_initialization() { + let errorMessage = "Invalid image URL" + let error = ImageTransformError(message: errorMessage) + + XCTAssertEqual(error.message, errorMessage) + } + + func testImageTransformError_debugDescription() { + let errorMessage = "Transform operation failed" + let error = ImageTransformError(message: errorMessage) + + XCTAssertEqual(error.debugDescription, errorMessage) + } + + func testImageTransformError_asError() { + let errorMessage = "Test error" + let error: Error = ImageTransformError(message: errorMessage) + + XCTAssertTrue(error is ImageTransformError) + if let transformError = error as? ImageTransformError { + XCTAssertEqual(transformError.message, errorMessage) + } else { + XCTFail("Error should be of type ImageTransformError") + } + } + + func testImageTransformError_emptyMessage() { + let error = ImageTransformError(message: "") + + XCTAssertEqual(error.message, "") + XCTAssertEqual(error.debugDescription, "") + } + + func testImageTransformError_longMessage() { + let longMessage = String(repeating: "a", count: 1000) + let error = ImageTransformError(message: longMessage) + + XCTAssertEqual(error.message, longMessage) + XCTAssertEqual(error.debugDescription, longMessage) + } + + func testImageTransformError_specialCharacters() { + let errorMessage = "Error with special chars: @#$%^&*()" + let error = ImageTransformError(message: errorMessage) + + XCTAssertEqual(error.message, errorMessage) + } + + static var allTests = [ + ("testImageTransformError_initialization", testImageTransformError_initialization), + ("testImageTransformError_debugDescription", testImageTransformError_debugDescription), + ("testImageTransformError_asError", testImageTransformError_asError), + ("testImageTransformError_emptyMessage", testImageTransformError_emptyMessage), + ("testImageTransformError_longMessage", testImageTransformError_longMessage), + ("testImageTransformError_specialCharacters", testImageTransformError_specialCharacters) + ] +} + diff --git a/Tests/ParameterEncodingTest.swift b/Tests/ParameterEncodingTest.swift new file mode 100644 index 00000000..b886b1f3 --- /dev/null +++ b/Tests/ParameterEncodingTest.swift @@ -0,0 +1,335 @@ +// +// ParameterEncodingTest.swift +// Contentstack +// +// Created for improved test coverage +// + +import XCTest +@testable import ContentstackSwift + +class ParameterEncodingTest: XCTestCase { + + // MARK: - Dictionary Addition Operator Tests + + func testDictionaryAdditionOperator() { + let left = ["key1": "value1", "key2": "value2"] + let right = ["key3": "value3", "key4": "value4"] + + let result = left + right + + XCTAssertEqual(result.count, 4) + XCTAssertEqual(result["key1"], "value1") + XCTAssertEqual(result["key2"], "value2") + XCTAssertEqual(result["key3"], "value3") + XCTAssertEqual(result["key4"], "value4") + } + + func testDictionaryAdditionOperator_withOverlap() { + let left = ["key1": "value1", "key2": "value2"] + let right = ["key2": "newValue2", "key3": "value3"] + + let result = left + right + + XCTAssertEqual(result.count, 3) + XCTAssertEqual(result["key1"], "value1") + XCTAssertEqual(result["key2"], "newValue2") // Right overwrites left + XCTAssertEqual(result["key3"], "value3") + } + + func testDictionaryAdditionOperator_emptyDictionaries() { + let left: [String: String] = [:] + let right: [String: String] = [:] + + let result = left + right + + XCTAssertTrue(result.isEmpty) + } + + func testDictionaryAdditionOperator_leftEmpty() { + let left: [String: String] = [:] + let right = ["key1": "value1"] + + let result = left + right + + XCTAssertEqual(result.count, 1) + XCTAssertEqual(result["key1"], "value1") + } + + func testDictionaryAdditionOperator_rightEmpty() { + let left = ["key1": "value1"] + let right: [String: String] = [:] + + let result = left + right + + XCTAssertEqual(result.count, 1) + XCTAssertEqual(result["key1"], "value1") + } + + // MARK: - Query String Generation Tests + + func testParametersQuery_simpleString() { + let params: Parameters = ["name": "John"] + let queryString = params.query() + + XCTAssertEqual(queryString, "name=John") + } + + func testParametersQuery_multipleParams() { + let params: Parameters = ["name": "John", "age": 30] + let queryString = params.query() + + // Keys are sorted, so we can predict the order + XCTAssertTrue(queryString.contains("age=30")) + XCTAssertTrue(queryString.contains("name=John")) + XCTAssertTrue(queryString.contains("&")) + } + + func testParametersQuery_skipQueryParameter() { + let params: Parameters = ["query": "test", "name": "John"] + let queryString = params.query() + + // "query" key should be skipped + XCTAssertEqual(queryString, "name=John") + XCTAssertFalse(queryString.contains("query")) + } + + func testParametersQuery_skipUIDParameter() { + let params: Parameters = ["uid": "test_uid", "name": "John"] + let queryString = params.query() + + // "uid" key should be skipped + XCTAssertEqual(queryString, "name=John") + XCTAssertFalse(queryString.contains("uid")) + } + + func testParametersQuery_skipContentTypeParameter() { + let params: Parameters = ["content_type": "test", "name": "John"] + let queryString = params.query() + + // "content_type" key should be skipped + XCTAssertEqual(queryString, "name=John") + XCTAssertFalse(queryString.contains("content_type")) + } + + func testParametersQuery_withNumber() { + let params: Parameters = ["count": 42] + let queryString = params.query() + + XCTAssertEqual(queryString, "count=42") + } + + func testParametersQuery_withDouble() { + let params: Parameters = ["price": 19.99] + let queryString = params.query() + + XCTAssertEqual(queryString, "price=19.99") + } + + func testParametersQuery_withBool() { + let params: Parameters = ["active": true, "deleted": false] + let queryString = params.query() + + XCTAssertTrue(queryString.contains("active=true")) + XCTAssertTrue(queryString.contains("deleted=false")) + } + + func testParametersQuery_withNSNumber() { + let params: Parameters = ["value": NSNumber(value: 123)] + let queryString = params.query() + + XCTAssertEqual(queryString, "value=123") + } + + func testParametersQuery_withNSNumberBool() { + let params: Parameters = ["flag": NSNumber(value: true)] + let queryString = params.query() + + XCTAssertEqual(queryString, "flag=true") + } + + func testParametersQuery_withArray() { + let params: Parameters = ["tags": ["swift", "ios", "mobile"]] + let queryString = params.query() + + // Arrays are encoded with [] + XCTAssertTrue(queryString.contains("tags")) + XCTAssertTrue(queryString.contains("swift")) + XCTAssertTrue(queryString.contains("ios")) + XCTAssertTrue(queryString.contains("mobile")) + } + + func testParametersQuery_withNestedDictionary() { + let params: Parameters = ["filter": ["status": "active", "type": "user"]] + let queryString = params.query() + + // Nested dictionaries are encoded with bracket notation + XCTAssertTrue(queryString.contains("filter")) + XCTAssertTrue(queryString.contains("status")) + XCTAssertTrue(queryString.contains("active")) + XCTAssertTrue(queryString.contains("type")) + XCTAssertTrue(queryString.contains("user")) + } + + func testParametersQuery_withDeepNestedDictionary() { + let params: Parameters = [ + "user": [ + "profile": [ + "name": "John" + ] + ] + ] + let queryString = params.query() + + // Deep nested dictionaries + XCTAssertTrue(queryString.contains("user")) + XCTAssertTrue(queryString.contains("profile")) + XCTAssertTrue(queryString.contains("name")) + XCTAssertTrue(queryString.contains("John")) + } + + func testParametersQuery_withDate() { + let date = Date(timeIntervalSince1970: 1609459200) // 2021-01-01 00:00:00 UTC + let params: Parameters = ["created_at": date] + let queryString = params.query() + + XCTAssertTrue(queryString.contains("created_at=")) + // Date should be converted to ISO8601 string + } + + func testParametersQuery_specialCharactersEncoding() { + let params: Parameters = ["name": "John Doe"] + let queryString = params.query() + + XCTAssertTrue(queryString.contains("name=John%20Doe")) + } + + func testParametersQuery_withSpecialCharacters() { + let params: Parameters = ["email": "test@example.com"] + let queryString = params.query() + + XCTAssertTrue(queryString.contains("email=test@example.com")) + } + + func testParametersQuery_complexMixedTypes() { + let params: Parameters = [ + "name": "John", + "age": 30, + "active": true, + "score": 95.5, + "tags": ["ios", "swift"], + "metadata": ["key": "value"] + ] + let queryString = params.query() + + // Complex mixed types should encode all values + XCTAssertTrue(queryString.contains("name")) + XCTAssertTrue(queryString.contains("John")) + XCTAssertTrue(queryString.contains("age")) + XCTAssertTrue(queryString.contains("30")) + XCTAssertTrue(queryString.contains("active")) + XCTAssertTrue(queryString.contains("true")) + XCTAssertTrue(queryString.contains("score")) + XCTAssertTrue(queryString.contains("95.5")) + XCTAssertTrue(queryString.contains("tags")) + XCTAssertTrue(queryString.contains("ios")) + XCTAssertTrue(queryString.contains("swift")) + XCTAssertTrue(queryString.contains("metadata")) + XCTAssertTrue(queryString.contains("key")) + XCTAssertTrue(queryString.contains("value")) + } + + func testParametersQuery_emptyDictionary() { + let params: Parameters = [:] + let queryString = params.query() + + XCTAssertTrue(queryString.isEmpty) + } + + func testParametersQuery_arrayWithNumbers() { + let params: Parameters = ["ids": [1, 2, 3]] + let queryString = params.query() + + // Arrays with numbers - check that array is encoded + XCTAssertFalse(queryString.isEmpty) + // Should contain ids[] notation and the numbers + let containsIds = queryString.contains("ids") + let containsNumber = queryString.contains("1") || queryString.contains("2") || queryString.contains("3") + XCTAssertTrue(containsIds || containsNumber, "Query should contain array data") + } + + func testParametersQuery_arrayWithMixedTypes() { + let params: Parameters = ["values": [1, "text", true]] + let queryString = params.query() + + // Arrays with mixed types - check that array is encoded + XCTAssertFalse(queryString.isEmpty) + let containsValues = queryString.contains("values") + let containsData = queryString.contains("text") || queryString.contains("1") || queryString.contains("true") + XCTAssertTrue(containsValues || containsData, "Query should contain array data") + } + + func testParametersQuery_nestedArrays() { + let params: Parameters = ["matrix": [[1, 2], [3, 4]]] + let queryString = params.query() + + // Nested arrays should be encoded + XCTAssertTrue(queryString.contains("matrix")) + XCTAssertFalse(queryString.isEmpty) + } + + func testParametersQuery_urlSafeCharacters() { + let params: Parameters = ["url": "https://example.com/path?param=value"] + let queryString = params.query() + + XCTAssertTrue(queryString.contains("url=")) + // URL should be percent-encoded appropriately + } + + func testParametersQuery_sortingOrder() { + let params: Parameters = [ + "zebra": "z", + "alpha": "a", + "beta": "b" + ] + let queryString = params.query() + + // Should be sorted alphabetically + let components = queryString.components(separatedBy: "&") + XCTAssertEqual(components[0], "alpha=a") + XCTAssertEqual(components[1], "beta=b") + XCTAssertEqual(components[2], "zebra=z") + } + + static var allTests = [ + ("testDictionaryAdditionOperator", testDictionaryAdditionOperator), + ("testDictionaryAdditionOperator_withOverlap", testDictionaryAdditionOperator_withOverlap), + ("testDictionaryAdditionOperator_emptyDictionaries", testDictionaryAdditionOperator_emptyDictionaries), + ("testDictionaryAdditionOperator_leftEmpty", testDictionaryAdditionOperator_leftEmpty), + ("testDictionaryAdditionOperator_rightEmpty", testDictionaryAdditionOperator_rightEmpty), + ("testParametersQuery_simpleString", testParametersQuery_simpleString), + ("testParametersQuery_multipleParams", testParametersQuery_multipleParams), + ("testParametersQuery_skipQueryParameter", testParametersQuery_skipQueryParameter), + ("testParametersQuery_skipUIDParameter", testParametersQuery_skipUIDParameter), + ("testParametersQuery_skipContentTypeParameter", testParametersQuery_skipContentTypeParameter), + ("testParametersQuery_withNumber", testParametersQuery_withNumber), + ("testParametersQuery_withDouble", testParametersQuery_withDouble), + ("testParametersQuery_withBool", testParametersQuery_withBool), + ("testParametersQuery_withNSNumber", testParametersQuery_withNSNumber), + ("testParametersQuery_withNSNumberBool", testParametersQuery_withNSNumberBool), + ("testParametersQuery_withArray", testParametersQuery_withArray), + ("testParametersQuery_withNestedDictionary", testParametersQuery_withNestedDictionary), + ("testParametersQuery_withDeepNestedDictionary", testParametersQuery_withDeepNestedDictionary), + ("testParametersQuery_withDate", testParametersQuery_withDate), + ("testParametersQuery_specialCharactersEncoding", testParametersQuery_specialCharactersEncoding), + ("testParametersQuery_withSpecialCharacters", testParametersQuery_withSpecialCharacters), + ("testParametersQuery_complexMixedTypes", testParametersQuery_complexMixedTypes), + ("testParametersQuery_emptyDictionary", testParametersQuery_emptyDictionary), + ("testParametersQuery_arrayWithNumbers", testParametersQuery_arrayWithNumbers), + ("testParametersQuery_arrayWithMixedTypes", testParametersQuery_arrayWithMixedTypes), + ("testParametersQuery_nestedArrays", testParametersQuery_nestedArrays), + ("testParametersQuery_urlSafeCharacters", testParametersQuery_urlSafeCharacters), + ("testParametersQuery_sortingOrder", testParametersQuery_sortingOrder) + ] +} + diff --git a/Tests/QueryOperationTest.swift b/Tests/QueryOperationTest.swift new file mode 100644 index 00000000..902a639e --- /dev/null +++ b/Tests/QueryOperationTest.swift @@ -0,0 +1,325 @@ +// +// QueryOperationTest.swift +// Contentstack +// +// Created for improved test coverage +// + +import XCTest +@testable import ContentstackSwift + +class QueryOperationTest: XCTestCase { + + var stack: Stack! + var query: Query! + + override func setUp() { + super.setUp() + // file deepcode ignore NoHardcodedCredentials/test: + stack = Contentstack.stack(apiKey: "test_api_key", + deliveryToken: "test_token", + environment: "test") + query = stack.contentType(uid: "test_content_type").entry().query() + } + + // MARK: - Query.Operator Tests + + func testQueryOperator_and() { + let query1 = stack.contentType(uid: "test").entry().query() + query1.queryParameter = ["field1": "value1"] + + let query2 = stack.contentType(uid: "test").entry().query() + query2.queryParameter = ["field2": "value2"] + + let andOperator = Query.Operator.and([query1, query2]) + + XCTAssertEqual(andOperator.string, "$and") + XCTAssertEqual(andOperator.value.count, 2) + } + + func testQueryOperator_or() { + let query1 = stack.contentType(uid: "test").entry().query() + query1.queryParameter = ["field1": "value1"] + + let query2 = stack.contentType(uid: "test").entry().query() + query2.queryParameter = ["field2": "value2"] + + let orOperator = Query.Operator.or([query1, query2]) + + XCTAssertEqual(orOperator.string, "$or") + XCTAssertEqual(orOperator.value.count, 2) + } + + func testQueryOperator_and_multipleQueries() { + let queries = (0..<5).map { _ in + let q = stack.contentType(uid: "test").entry().query() + q.queryParameter = ["test": "value"] + return q + } + + let andOperator = Query.Operator.and(queries) + + XCTAssertEqual(andOperator.value.count, 5) + } + + // MARK: - Query.Reference Tests + + func testQueryReference_include() { + let refQuery = stack.contentType(uid: "test").entry().query() + refQuery.queryParameter = ["uid": "test_uid"] + + let reference = Query.Reference.include(refQuery) + + XCTAssertEqual(reference.string, "$in") + XCTAssertNotNil(reference.value) + XCTAssertNotNil(reference.query) + } + + func testQueryReference_notInclude() { + let refQuery = stack.contentType(uid: "test").entry().query() + refQuery.queryParameter = ["uid": "test_uid"] + + let reference = Query.Reference.notInclude(refQuery) + + XCTAssertEqual(reference.string, "$nin") + XCTAssertNotNil(reference.value) + XCTAssertNotNil(reference.query) + } + + // MARK: - Query.Operation Tests + + func testQueryOperation_equals_string() { + let operation = Query.Operation.equals("test_value") + + XCTAssertEqual(operation.string, "") + if let value = operation.value as? String { + XCTAssertEqual(value, "test_value") + } else { + XCTFail("Value should be a string") + } + } + + func testQueryOperation_equals_int() { + let operation = Query.Operation.equals(42) + + if let value = operation.value as? Int { + XCTAssertEqual(value, 42) + } else { + XCTFail("Value should be an int") + } + } + + func testQueryOperation_equals_double() { + let operation = Query.Operation.equals(3.14) + + if let value = operation.value as? Double { + XCTAssertEqual(value, 3.14, accuracy: 0.001) + } else { + XCTFail("Value should be a double") + } + } + + func testQueryOperation_equals_bool() { + let operation = Query.Operation.equals(true) + + if let value = operation.value as? Bool { + XCTAssertTrue(value) + } else { + XCTFail("Value should be a bool") + } + } + + func testQueryOperation_notEquals() { + let operation = Query.Operation.notEquals("test_value") + + XCTAssertEqual(operation.string, "$ne") + if let value = operation.value as? String { + XCTAssertEqual(value, "test_value") + } + } + + func testQueryOperation_notEquals_int() { + let operation = Query.Operation.notEquals(100) + + XCTAssertEqual(operation.string, "$ne") + if let value = operation.value as? Int { + XCTAssertEqual(value, 100) + } + } + + func testQueryOperation_includes() { + let operation = Query.Operation.includes(["tag1", "tag2", "tag3"]) + + XCTAssertEqual(operation.string, "$in") + } + + func testQueryOperation_excludes() { + let operation = Query.Operation.excludes(["tag1", "tag2"]) + + XCTAssertEqual(operation.string, "$nin") + } + + func testQueryOperation_isLessThan_int() { + let operation = Query.Operation.isLessThan(100) + + XCTAssertEqual(operation.string, "$lt") + if let value = operation.value as? Int { + XCTAssertEqual(value, 100) + } + } + + func testQueryOperation_isLessThan_string() { + let operation = Query.Operation.isLessThan("z") + + XCTAssertEqual(operation.string, "$lt") + if let value = operation.value as? String { + XCTAssertEqual(value, "z") + } + } + + func testQueryOperation_isLessThanOrEqual() { + let operation = Query.Operation.isLessThanOrEqual(50) + + XCTAssertEqual(operation.string, "$lte") + if let value = operation.value as? Int { + XCTAssertEqual(value, 50) + } + } + + func testQueryOperation_isGreaterThan() { + let operation = Query.Operation.isGreaterThan(10) + + XCTAssertEqual(operation.string, "$gt") + if let value = operation.value as? Int { + XCTAssertEqual(value, 10) + } + } + + func testQueryOperation_isGreaterThanOrEqual() { + let operation = Query.Operation.isGreaterThanOrEqual(25) + + XCTAssertEqual(operation.string, "$gte") + if let value = operation.value as? Int { + XCTAssertEqual(value, 25) + } + } + + func testQueryOperation_exists_true() { + let operation = Query.Operation.exists(true) + + XCTAssertEqual(operation.string, "$exists") + if let value = operation.value as? Bool { + XCTAssertTrue(value) + } + } + + func testQueryOperation_exists_false() { + let operation = Query.Operation.exists(false) + + XCTAssertEqual(operation.string, "$exists") + if let value = operation.value as? Bool { + XCTAssertFalse(value) + } + } + + func testQueryOperation_matches() { + let operation = Query.Operation.matches("^test.*") + + XCTAssertEqual(operation.string, "$regex") + if let value = operation.value as? String { + XCTAssertEqual(value, "^test.*") + } + } + + func testQueryOperation_eqBelow() { + let operation = Query.Operation.eqBelow("taxonomy_uid") + + XCTAssertEqual(operation.string, "$eq_below") + if let value = operation.value as? String { + XCTAssertEqual(value, "taxonomy_uid") + } + } + + func testQueryOperation_below() { + let operation = Query.Operation.below("taxonomy_uid") + + XCTAssertEqual(operation.string, "$below") + if let value = operation.value as? String { + XCTAssertEqual(value, "taxonomy_uid") + } + } + + func testQueryOperation_eqAbove() { + let operation = Query.Operation.eqAbove("taxonomy_uid") + + XCTAssertEqual(operation.string, "$eq_above") + if let value = operation.value as? String { + XCTAssertEqual(value, "taxonomy_uid") + } + } + + func testQueryOperation_above() { + let operation = Query.Operation.above("taxonomy_uid") + + XCTAssertEqual(operation.string, "$above") + if let value = operation.value as? String { + XCTAssertEqual(value, "taxonomy_uid") + } + } + + func testQueryOperation_query_equals() { + let operation = Query.Operation.equals("test") + + if let query = operation.query as? String { + XCTAssertEqual(query, "test") + } + } + + func testQueryOperation_query_notEquals() { + let operation = Query.Operation.notEquals("test") + + if let query = operation.query as? [String: Any] { + XCTAssertNotNil(query["$ne"]) + } + } + + func testQueryOperation_query_complexOperation() { + let operation = Query.Operation.isGreaterThan(10) + + if let query = operation.query as? [String: Any] { + XCTAssertNotNil(query["$gt"]) + } + } + + static var allTests = [ + ("testQueryOperator_and", testQueryOperator_and), + ("testQueryOperator_or", testQueryOperator_or), + ("testQueryOperator_and_multipleQueries", testQueryOperator_and_multipleQueries), + ("testQueryReference_include", testQueryReference_include), + ("testQueryReference_notInclude", testQueryReference_notInclude), + ("testQueryOperation_equals_string", testQueryOperation_equals_string), + ("testQueryOperation_equals_int", testQueryOperation_equals_int), + ("testQueryOperation_equals_double", testQueryOperation_equals_double), + ("testQueryOperation_equals_bool", testQueryOperation_equals_bool), + ("testQueryOperation_notEquals", testQueryOperation_notEquals), + ("testQueryOperation_notEquals_int", testQueryOperation_notEquals_int), + ("testQueryOperation_includes", testQueryOperation_includes), + ("testQueryOperation_excludes", testQueryOperation_excludes), + ("testQueryOperation_isLessThan_int", testQueryOperation_isLessThan_int), + ("testQueryOperation_isLessThan_string", testQueryOperation_isLessThan_string), + ("testQueryOperation_isLessThanOrEqual", testQueryOperation_isLessThanOrEqual), + ("testQueryOperation_isGreaterThan", testQueryOperation_isGreaterThan), + ("testQueryOperation_isGreaterThanOrEqual", testQueryOperation_isGreaterThanOrEqual), + ("testQueryOperation_exists_true", testQueryOperation_exists_true), + ("testQueryOperation_exists_false", testQueryOperation_exists_false), + ("testQueryOperation_matches", testQueryOperation_matches), + ("testQueryOperation_eqBelow", testQueryOperation_eqBelow), + ("testQueryOperation_below", testQueryOperation_below), + ("testQueryOperation_eqAbove", testQueryOperation_eqAbove), + ("testQueryOperation_above", testQueryOperation_above), + ("testQueryOperation_query_equals", testQueryOperation_query_equals), + ("testQueryOperation_query_notEquals", testQueryOperation_query_notEquals), + ("testQueryOperation_query_complexOperation", testQueryOperation_query_complexOperation) + ] +} + diff --git a/Tests/QueryParameterTest.swift b/Tests/QueryParameterTest.swift new file mode 100644 index 00000000..1d879621 --- /dev/null +++ b/Tests/QueryParameterTest.swift @@ -0,0 +1,221 @@ +// +// QueryParameterTest.swift +// Contentstack +// +// Created for improved test coverage +// + +import XCTest +@testable import ContentstackSwift + +class QueryParameterTest: XCTestCase { + + // MARK: - Query.Include Tests + + func testQueryInclude_count() { + let include = Query.Include.count + XCTAssertEqual(include.rawValue, 1) + } + + func testQueryInclude_unpublished() { + let include = Query.Include.unpublished + XCTAssertEqual(include.rawValue, 2) + } + + func testQueryInclude_contentType() { + let include = Query.Include.contentType + XCTAssertEqual(include.rawValue, 4) + } + + func testQueryInclude_globalField() { + let include = Query.Include.globalField + XCTAssertEqual(include.rawValue, 8) + } + + func testQueryInclude_refContentTypeUID() { + let include = Query.Include.refContentTypeUID + XCTAssertEqual(include.rawValue, 16) + } + + func testQueryInclude_fallback() { + let include = Query.Include.fallback + XCTAssertEqual(include.rawValue, 32) + } + + func testQueryInclude_embeddedItems() { + let include = Query.Include.embeddedItems + XCTAssertEqual(include.rawValue, 64) + } + + func testQueryInclude_metadata() { + let include = Query.Include.metadata + XCTAssertEqual(include.rawValue, 128) + } + + func testQueryInclude_all() { + let all = Query.Include.all + XCTAssertTrue(all.contains(.count)) + XCTAssertTrue(all.contains(.unpublished)) + XCTAssertTrue(all.contains(.contentType)) + XCTAssertTrue(all.contains(.globalField)) + XCTAssertTrue(all.contains(.refContentTypeUID)) + XCTAssertTrue(all.contains(.fallback)) + XCTAssertTrue(all.contains(.embeddedItems)) + XCTAssertTrue(all.contains(.metadata)) + } + + func testQueryInclude_combination() { + let include: Query.Include = [.count, .contentType] + XCTAssertTrue(include.contains(.count)) + XCTAssertTrue(include.contains(.contentType)) + XCTAssertFalse(include.contains(.unpublished)) + } + + func testQueryInclude_multipleOptions() { + let include: Query.Include = [.count, .unpublished, .fallback] + XCTAssertTrue(include.contains(.count)) + XCTAssertTrue(include.contains(.unpublished)) + XCTAssertTrue(include.contains(.fallback)) + XCTAssertFalse(include.contains(.contentType)) + } + + // MARK: - ContentTypeQuery.Include Tests + + func testContentTypeQueryInclude_count() { + let include = ContentTypeQuery.Include.count + XCTAssertEqual(include.rawValue, 1) + } + + func testContentTypeQueryInclude_globalFields() { + let include = ContentTypeQuery.Include.globalFields + XCTAssertEqual(include.rawValue, 2) + } + + func testContentTypeQueryInclude_all() { + let all = ContentTypeQuery.Include.all + XCTAssertTrue(all.contains(.count)) + XCTAssertTrue(all.contains(.globalFields)) + } + + func testContentTypeQueryInclude_combination() { + let include: ContentTypeQuery.Include = [.count, .globalFields] + XCTAssertTrue(include.contains(.count)) + XCTAssertTrue(include.contains(.globalFields)) + } + + // MARK: - AssetQuery.Include Tests + + func testAssetQueryInclude_count() { + let include = AssetQuery.Include.count + XCTAssertEqual(include.rawValue, 1) + } + + func testAssetQueryInclude_relativeURL() { + let include = AssetQuery.Include.relativeURL + XCTAssertEqual(include.rawValue, 2) + } + + func testAssetQueryInclude_dimension() { + let include = AssetQuery.Include.dimension + XCTAssertEqual(include.rawValue, 4) + } + + func testAssetQueryInclude_fallback() { + let include = AssetQuery.Include.fallback + XCTAssertEqual(include.rawValue, 8) + } + + func testAssetQueryInclude_metadata() { + let include = AssetQuery.Include.metadata + XCTAssertEqual(include.rawValue, 16) + } + + func testAssetQueryInclude_all() { + let all = AssetQuery.Include.all + XCTAssertTrue(all.contains(.count)) + XCTAssertTrue(all.contains(.relativeURL)) + XCTAssertTrue(all.contains(.dimension)) + XCTAssertTrue(all.contains(.fallback)) + XCTAssertTrue(all.contains(.metadata)) + } + + func testAssetQueryInclude_combination() { + let include: AssetQuery.Include = [.count, .dimension] + XCTAssertTrue(include.contains(.count)) + XCTAssertTrue(include.contains(.dimension)) + XCTAssertFalse(include.contains(.relativeURL)) + } + + func testAssetQueryInclude_multipleOptions() { + let include: AssetQuery.Include = [.relativeURL, .dimension, .metadata] + XCTAssertTrue(include.contains(.relativeURL)) + XCTAssertTrue(include.contains(.dimension)) + XCTAssertTrue(include.contains(.metadata)) + XCTAssertFalse(include.contains(.count)) + } + + // MARK: - QueryConstants Tests + + func testQueryConstants_maxLimit() { + XCTAssertEqual(QueryConstants.maxLimit, 1000) + } + + // MARK: - Query.Include Edge Cases + + func testQueryInclude_emptySet() { + let include = Query.Include() + XCTAssertFalse(include.contains(.count)) + XCTAssertFalse(include.contains(.unpublished)) + } + + func testQueryInclude_rawValueInit() { + let include = Query.Include(rawValue: 5) // count + contentType + XCTAssertTrue(include.contains(.count)) + XCTAssertTrue(include.contains(.contentType)) + XCTAssertFalse(include.contains(.unpublished)) + } + + func testContentTypeQueryInclude_emptySet() { + let include = ContentTypeQuery.Include() + XCTAssertFalse(include.contains(.count)) + XCTAssertFalse(include.contains(.globalFields)) + } + + func testAssetQueryInclude_emptySet() { + let include = AssetQuery.Include() + XCTAssertFalse(include.contains(.count)) + XCTAssertFalse(include.contains(.dimension)) + } + + static var allTests = [ + ("testQueryInclude_count", testQueryInclude_count), + ("testQueryInclude_unpublished", testQueryInclude_unpublished), + ("testQueryInclude_contentType", testQueryInclude_contentType), + ("testQueryInclude_globalField", testQueryInclude_globalField), + ("testQueryInclude_refContentTypeUID", testQueryInclude_refContentTypeUID), + ("testQueryInclude_fallback", testQueryInclude_fallback), + ("testQueryInclude_embeddedItems", testQueryInclude_embeddedItems), + ("testQueryInclude_metadata", testQueryInclude_metadata), + ("testQueryInclude_all", testQueryInclude_all), + ("testQueryInclude_combination", testQueryInclude_combination), + ("testQueryInclude_multipleOptions", testQueryInclude_multipleOptions), + ("testContentTypeQueryInclude_count", testContentTypeQueryInclude_count), + ("testContentTypeQueryInclude_globalFields", testContentTypeQueryInclude_globalFields), + ("testContentTypeQueryInclude_all", testContentTypeQueryInclude_all), + ("testContentTypeQueryInclude_combination", testContentTypeQueryInclude_combination), + ("testAssetQueryInclude_count", testAssetQueryInclude_count), + ("testAssetQueryInclude_relativeURL", testAssetQueryInclude_relativeURL), + ("testAssetQueryInclude_dimension", testAssetQueryInclude_dimension), + ("testAssetQueryInclude_fallback", testAssetQueryInclude_fallback), + ("testAssetQueryInclude_metadata", testAssetQueryInclude_metadata), + ("testAssetQueryInclude_all", testAssetQueryInclude_all), + ("testAssetQueryInclude_combination", testAssetQueryInclude_combination), + ("testAssetQueryInclude_multipleOptions", testAssetQueryInclude_multipleOptions), + ("testQueryConstants_maxLimit", testQueryConstants_maxLimit), + ("testQueryInclude_emptySet", testQueryInclude_emptySet), + ("testQueryInclude_rawValueInit", testQueryInclude_rawValueInit), + ("testContentTypeQueryInclude_emptySet", testContentTypeQueryInclude_emptySet), + ("testAssetQueryInclude_emptySet", testAssetQueryInclude_emptySet) + ] +} + diff --git a/Tests/QueryableRangeTest.swift b/Tests/QueryableRangeTest.swift new file mode 100644 index 00000000..96f4f578 --- /dev/null +++ b/Tests/QueryableRangeTest.swift @@ -0,0 +1,217 @@ +// +// QueryableRangeTest.swift +// Contentstack +// +// Created for improved test coverage +// + +import XCTest +@testable import ContentstackSwift + +class QueryableRangeTest: XCTestCase { + + // MARK: - Int QueryableRange Tests + + func testInt_stringValue() { + let value: Int = 42 + XCTAssertEqual(value.stringValue, "42") + } + + func testInt_negativeValue() { + let value: Int = -100 + XCTAssertEqual(value.stringValue, "-100") + } + + func testInt_zero() { + let value: Int = 0 + XCTAssertEqual(value.stringValue, "0") + } + + // MARK: - Bool QueryableRange Tests + + func testBool_trueValue() { + let value: Bool = true + XCTAssertEqual(value.stringValue, "true") + } + + func testBool_falseValue() { + let value: Bool = false + XCTAssertEqual(value.stringValue, "false") + } + + // MARK: - Double QueryableRange Tests + + func testDouble_stringValue() { + let value: Double = 3.14159 + XCTAssertEqual(value.stringValue, "3.14159") + } + + func testDouble_negativeValue() { + let value: Double = -99.99 + XCTAssertEqual(value.stringValue, "-99.99") + } + + func testDouble_zero() { + let value: Double = 0.0 + XCTAssertEqual(value.stringValue, "0.0") + } + + func testDouble_largeValue() { + let value: Double = 1234567.89 + XCTAssertEqual(value.stringValue, "1234567.89") + } + + // MARK: - String QueryableRange Tests + + func testString_stringValue() { + let value: String = "Hello World" + XCTAssertEqual(value.stringValue, "Hello World") + } + + func testString_emptyString() { + let value: String = "" + XCTAssertEqual(value.stringValue, "") + } + + func testString_specialCharacters() { + let value: String = "test@example.com" + XCTAssertEqual(value.stringValue, "test@example.com") + } + + // MARK: - Date QueryableRange Tests + + func testDate_stringValue() { + let date = Date(timeIntervalSince1970: 1609459200) // 2021-01-01 00:00:00 UTC + let stringValue = date.stringValue + + // Should be ISO8601 formatted + XCTAssertFalse(stringValue.isEmpty) + XCTAssertTrue(stringValue.contains("2021")) + } + + func testDate_currentDate() { + let date = Date() + let stringValue = date.stringValue + + XCTAssertFalse(stringValue.isEmpty) + } + + // MARK: - QueryableRange isEquals Tests + + func testQueryableRange_isEquals_sameInts() { + let value1: Int = 42 + let value2: Int = 42 + + XCTAssertTrue(value1.isEquals(to: value2)) + } + + func testQueryableRange_isEquals_differentInts() { + let value1: Int = 42 + let value2: Int = 100 + + XCTAssertFalse(value1.isEquals(to: value2)) + } + + func testQueryableRange_isEquals_sameStrings() { + let value1: String = "test" + let value2: String = "test" + + XCTAssertTrue(value1.isEquals(to: value2)) + } + + func testQueryableRange_isEquals_differentStrings() { + let value1: String = "test1" + let value2: String = "test2" + + XCTAssertFalse(value1.isEquals(to: value2)) + } + + func testQueryableRange_isEquals_sameBools() { + let value1: Bool = true + let value2: Bool = true + + XCTAssertTrue(value1.isEquals(to: value2)) + } + + func testQueryableRange_isEquals_differentBools() { + let value1: Bool = true + let value2: Bool = false + + XCTAssertFalse(value1.isEquals(to: value2)) + } + + func testQueryableRange_isEquals_sameDoubles() { + let value1: Double = 3.14 + let value2: Double = 3.14 + + XCTAssertTrue(value1.isEquals(to: value2)) + } + + func testQueryableRange_isEquals_differentDoubles() { + let value1: Double = 3.14 + let value2: Double = 2.71 + + XCTAssertFalse(value1.isEquals(to: value2)) + } + + func testQueryableRange_isEquals_differentTypes_intAndDouble() { + let value1: Int = 42 + let value2: Double = 42.0 + + // Different types should not be equal even if string values match + XCTAssertFalse(value1.isEquals(to: value2)) + } + + func testQueryableRange_isEquals_differentTypes_intAndString() { + let value1: Int = 42 + let value2: String = "42" + + // Int requires type matching, so Int vs String should not be equal + XCTAssertFalse(value1.isEquals(to: value2)) + } + + func testQueryableRange_isEquals_sameDates() { + let date = Date(timeIntervalSince1970: 1609459200) + let value1 = date + let value2 = date + + XCTAssertTrue(value1.isEquals(to: value2)) + } + + func testQueryableRange_isEquals_differentDates() { + let value1 = Date(timeIntervalSince1970: 1609459200) + let value2 = Date(timeIntervalSince1970: 1609545600) + + XCTAssertFalse(value1.isEquals(to: value2)) + } + + static var allTests = [ + ("testInt_stringValue", testInt_stringValue), + ("testInt_negativeValue", testInt_negativeValue), + ("testInt_zero", testInt_zero), + ("testBool_trueValue", testBool_trueValue), + ("testBool_falseValue", testBool_falseValue), + ("testDouble_stringValue", testDouble_stringValue), + ("testDouble_negativeValue", testDouble_negativeValue), + ("testDouble_zero", testDouble_zero), + ("testDouble_largeValue", testDouble_largeValue), + ("testString_stringValue", testString_stringValue), + ("testString_emptyString", testString_emptyString), + ("testString_specialCharacters", testString_specialCharacters), + ("testDate_stringValue", testDate_stringValue), + ("testDate_currentDate", testDate_currentDate), + ("testQueryableRange_isEquals_sameInts", testQueryableRange_isEquals_sameInts), + ("testQueryableRange_isEquals_differentInts", testQueryableRange_isEquals_differentInts), + ("testQueryableRange_isEquals_sameStrings", testQueryableRange_isEquals_sameStrings), + ("testQueryableRange_isEquals_differentStrings", testQueryableRange_isEquals_differentStrings), + ("testQueryableRange_isEquals_sameBools", testQueryableRange_isEquals_sameBools), + ("testQueryableRange_isEquals_differentBools", testQueryableRange_isEquals_differentBools), + ("testQueryableRange_isEquals_sameDoubles", testQueryableRange_isEquals_sameDoubles), + ("testQueryableRange_isEquals_differentDoubles", testQueryableRange_isEquals_differentDoubles), + ("testQueryableRange_isEquals_differentTypes_intAndDouble", testQueryableRange_isEquals_differentTypes_intAndDouble), + ("testQueryableRange_isEquals_differentTypes_intAndString", testQueryableRange_isEquals_differentTypes_intAndString), + ("testQueryableRange_isEquals_sameDates", testQueryableRange_isEquals_sameDates), + ("testQueryableRange_isEquals_differentDates", testQueryableRange_isEquals_differentDates) + ] +} + diff --git a/Tests/StackInitializationTest.swift b/Tests/StackInitializationTest.swift new file mode 100644 index 00000000..838f4f90 --- /dev/null +++ b/Tests/StackInitializationTest.swift @@ -0,0 +1,196 @@ +// +// StackInitializationTest.swift +// Contentstack +// +// Created for improved test coverage +// + +import XCTest +@testable import ContentstackSwift + +class StackInitializationTest: XCTestCase { + + // MARK: - Stack Properties Tests + + func testStack_initialization() { + let stack = makeStackSut( + // file deepcode ignore NoHardcodedCredentials/test: + apiKey: "test_key", + deliveryToken: "test_token", + environment: "test_env" + ) + + XCTAssertEqual(stack.apiKey, "test_key") + XCTAssertEqual(stack.deliveryToken, "test_token") + XCTAssertEqual(stack.environment, "test_env") + XCTAssertNotNil(stack.jsonDecoder) + } + + func testStack_cachePolicy_default() { + let stack = makeStackSut() + + XCTAssertEqual(stack.cachePolicy, .networkOnly) + } + + func testStack_cachePolicy_modification() { + let stack = makeStackSut() + stack.cachePolicy = .cacheOnly + + XCTAssertEqual(stack.cachePolicy, .cacheOnly) + } + + func testStack_contentType_withoutUID() { + let stack = makeStackSut() + let contentType = stack.contentType(uid: nil) + + XCTAssertNil(contentType.uid) + XCTAssertNotNil(contentType) + } + + func testStack_contentType_withUID() { + let stack = makeStackSut() + let uid = "test_content_type_uid" + let contentType = stack.contentType(uid: uid) + + XCTAssertEqual(contentType.uid, uid) + } + + func testStack_asset_withoutUID() { + let stack = makeStackSut() + let asset = stack.asset(uid: nil) + + XCTAssertNil(asset.uid) + XCTAssertNotNil(asset) + } + + func testStack_asset_withUID() { + let stack = makeStackSut() + let uid = "test_asset_uid" + let asset = stack.asset(uid: uid) + + XCTAssertEqual(asset.uid, uid) + } + + func testStack_taxonomy() { + let stack = makeStackSut() + let taxonomy = stack.taxonomy() + + XCTAssertNotNil(taxonomy) + XCTAssertEqual(taxonomy.cachePolicy, .networkOnly) + } + + func testStack_hasURLSession() { + let stack = makeStackSut() + + XCTAssertNotNil(stack.urlSession) + } + + func testStack_hasJSONDecoder() { + let stack = makeStackSut() + + XCTAssertNotNil(stack.jsonDecoder) + } + + func testStack_regionProperty() { + let stack = makeStackSut(region: .eu) + + XCTAssertEqual(stack.region, .eu) + } + + func testStack_apiVersionProperty() { + let stack = makeStackSut(apiVersion: "v4") + + XCTAssertEqual(stack.apiVersion, "v4") + } + + func testStack_hostProperty() { + let customHost = "custom.host.com" + let stack = makeStackSut(host: customHost) + + XCTAssertEqual(stack.host, customHost) + } + + func testStack_environmentProperty() { + let environment = "production" + let stack = makeStackSut(environment: environment) + + XCTAssertEqual(stack.environment, environment) + } + + func testStack_deliveryTokenProperty() { + let token = "test_delivery_token" + let stack = makeStackSut(deliveryToken: token) + + XCTAssertEqual(stack.deliveryToken, token) + } + + func testStack_globalField() { + let stack = makeStackSut() + let uid = "test_global_field_uid" + let globalField = stack.globalField(uid: uid) + + XCTAssertNotNil(globalField) + XCTAssertEqual(globalField.uid, uid) + } + + func testStack_allRegions() { + let regions: [ContentstackRegion] = [.us, .eu, .azure_na, .azure_eu, .gcp_na, .gcp_eu, .au] + + for region in regions { + let stack = makeStackSut(region: region) + XCTAssertEqual(stack.region, region) + } + } + + func testStack_withBranch() { + let branch = "feature-branch" + let stack = makeStackSut(branch: branch) + + XCTAssertEqual(stack.branch, branch) + } + + func testStack_withoutBranch() { + let stack = makeStackSut(branch: nil) + + XCTAssertNil(stack.branch) + } + + func testStack_customHost() { + let customHost = "custom.example.com" + let stack = makeStackSut(host: customHost) + + XCTAssertEqual(stack.host, customHost) + } + + func testStack_customAPIVersion() { + let apiVersion = "v4" + let stack = makeStackSut(apiVersion: apiVersion) + + XCTAssertEqual(stack.apiVersion, apiVersion) + } + + static var allTests = [ + ("testStack_initialization", testStack_initialization), + ("testStack_cachePolicy_default", testStack_cachePolicy_default), + ("testStack_cachePolicy_modification", testStack_cachePolicy_modification), + ("testStack_contentType_withoutUID", testStack_contentType_withoutUID), + ("testStack_contentType_withUID", testStack_contentType_withUID), + ("testStack_asset_withoutUID", testStack_asset_withoutUID), + ("testStack_asset_withUID", testStack_asset_withUID), + ("testStack_taxonomy", testStack_taxonomy), + ("testStack_hasURLSession", testStack_hasURLSession), + ("testStack_hasJSONDecoder", testStack_hasJSONDecoder), + ("testStack_regionProperty", testStack_regionProperty), + ("testStack_apiVersionProperty", testStack_apiVersionProperty), + ("testStack_hostProperty", testStack_hostProperty), + ("testStack_environmentProperty", testStack_environmentProperty), + ("testStack_deliveryTokenProperty", testStack_deliveryTokenProperty), + ("testStack_globalField", testStack_globalField), + ("testStack_allRegions", testStack_allRegions), + ("testStack_withBranch", testStack_withBranch), + ("testStack_withoutBranch", testStack_withoutBranch), + ("testStack_customHost", testStack_customHost), + ("testStack_customAPIVersion", testStack_customAPIVersion) + ] +} + diff --git a/Tests/TaxonomyUnitTest.swift b/Tests/TaxonomyUnitTest.swift new file mode 100644 index 00000000..c3f6b1e5 --- /dev/null +++ b/Tests/TaxonomyUnitTest.swift @@ -0,0 +1,155 @@ +// +// TaxonomyUnitTest.swift +// Contentstack +// +// Created for improved test coverage +// + +import XCTest +@testable import ContentstackSwift + +class TaxonomyUnitTest: XCTestCase { + + var stack: Stack! + var taxonomy: Taxonomy! + + override func setUp() { + super.setUp() + stack = makeStackSut() + taxonomy = stack.taxonomy() + } + + override func tearDown() { + taxonomy = nil + stack = nil + super.tearDown() + } + + // MARK: - Initialization Tests + + func testTaxonomy_initialization() { + XCTAssertNotNil(taxonomy) + XCTAssertNotNil(taxonomy.stack) + } + + func testTaxonomy_defaultCachePolicy() { + XCTAssertEqual(taxonomy.cachePolicy, .networkOnly) + } + + func testTaxonomy_defaultParameters() { + XCTAssertTrue(taxonomy.parameters.isEmpty) + } + + func testTaxonomy_defaultHeaders() { + XCTAssertTrue(taxonomy.headers.isEmpty) + } + + func testTaxonomy_defaultQueryParameter() { + XCTAssertTrue(taxonomy.queryParameter.isEmpty) + } + + func testTaxonomy_defaultUID() { + XCTAssertNil(taxonomy.uid) + } + + // MARK: - Query Tests + + func testTaxonomy_query() { + let query = taxonomy.query() + + XCTAssertNotNil(query) + XCTAssertEqual(query.cachePolicy, .networkOnly) + } + + func testTaxonomy_query_inheritsStack() { + let query = taxonomy.query() + + XCTAssertEqual(query.stack.apiKey, stack.apiKey) + } + + // MARK: - Header Tests + + func testTaxonomy_addHeader() { + let taxonomy = self.taxonomy.addValue("test_value", forHTTPHeaderField: "X-Custom-Header") + + XCTAssertEqual(taxonomy.headers["X-Custom-Header"], "test_value") + } + + func testTaxonomy_addMultipleHeaders() { + let taxonomy = self.taxonomy + .addValue("value1", forHTTPHeaderField: "Header1") + .addValue("value2", forHTTPHeaderField: "Header2") + .addValue("value3", forHTTPHeaderField: "Header3") + + XCTAssertEqual(taxonomy.headers.count, 3) + XCTAssertEqual(taxonomy.headers["Header1"], "value1") + XCTAssertEqual(taxonomy.headers["Header2"], "value2") + XCTAssertEqual(taxonomy.headers["Header3"], "value3") + } + + func testTaxonomy_overwriteHeader() { + let taxonomy = self.taxonomy + .addValue("old_value", forHTTPHeaderField: "X-Test") + .addValue("new_value", forHTTPHeaderField: "X-Test") + + XCTAssertEqual(taxonomy.headers["X-Test"], "new_value") + } + + // MARK: - Cache Policy Tests + + func testTaxonomy_cachePolicyModification() { + taxonomy.cachePolicy = .cacheOnly + + XCTAssertEqual(taxonomy.cachePolicy, .cacheOnly) + } + + func testTaxonomy_cachePolicyTypes() { + let policies: [CachePolicy] = [ + .networkOnly, + .cacheOnly, + .cacheElseNetwork, + .networkElseCache, + .cacheThenNetwork + ] + + for policy in policies { + taxonomy.cachePolicy = policy + XCTAssertEqual(taxonomy.cachePolicy, policy) + } + } + + // MARK: - Parameters Tests + + func testTaxonomy_setParameters() { + taxonomy.parameters = ["key": "value"] + + XCTAssertEqual(taxonomy.parameters.count, 1) + XCTAssertEqual(taxonomy.parameters["key"] as? String, "value") + } + + func testTaxonomy_setQueryParameters() { + taxonomy.queryParameter = ["query_key": "query_value"] + + XCTAssertEqual(taxonomy.queryParameter.count, 1) + XCTAssertEqual(taxonomy.queryParameter["query_key"] as? String, "query_value") + } + + static var allTests = [ + ("testTaxonomy_initialization", testTaxonomy_initialization), + ("testTaxonomy_defaultCachePolicy", testTaxonomy_defaultCachePolicy), + ("testTaxonomy_defaultParameters", testTaxonomy_defaultParameters), + ("testTaxonomy_defaultHeaders", testTaxonomy_defaultHeaders), + ("testTaxonomy_defaultQueryParameter", testTaxonomy_defaultQueryParameter), + ("testTaxonomy_defaultUID", testTaxonomy_defaultUID), + ("testTaxonomy_query", testTaxonomy_query), + ("testTaxonomy_query_inheritsStack", testTaxonomy_query_inheritsStack), + ("testTaxonomy_addHeader", testTaxonomy_addHeader), + ("testTaxonomy_addMultipleHeaders", testTaxonomy_addMultipleHeaders), + ("testTaxonomy_overwriteHeader", testTaxonomy_overwriteHeader), + ("testTaxonomy_cachePolicyModification", testTaxonomy_cachePolicyModification), + ("testTaxonomy_cachePolicyTypes", testTaxonomy_cachePolicyTypes), + ("testTaxonomy_setParameters", testTaxonomy_setParameters), + ("testTaxonomy_setQueryParameters", testTaxonomy_setQueryParameters) + ] +} + diff --git a/Tests/XCTestManifests.swift b/Tests/XCTestManifests.swift index fd9de081..8bb2eee1 100644 --- a/Tests/XCTestManifests.swift +++ b/Tests/XCTestManifests.swift @@ -3,7 +3,19 @@ import XCTest #if !canImport(ObjectiveC) public func allTests() -> [XCTestCaseEntry] { return [ - testCase(ContentstackTests.allTests) + testCase(ContentstackTests.allTests), + testCase(ErrorTest.allTests), + testCase(ParameterEncodingTest.allTests), + testCase(QueryableRangeTest.allTests), + testCase(QueryOperationTest.allTests), + testCase(QueryParameterTest.allTests), + testCase(EndPointTest.allTests), + testCase(DecodableTest.allTests), + testCase(CSDefinitionsTest.allTests), + testCase(ImageTransformErrorTest.allTests), + testCase(ContentstackTest.allTests), + testCase(StackInitializationTest.allTests), + testCase(TaxonomyUnitTest.allTests) ] } #endif