From aac8537fa9f7e3b9715d23b34ab67bdaaaf0bb60 Mon Sep 17 00:00:00 2001 From: Vlad Velicu Date: Fri, 4 Oct 2024 15:33:12 +0100 Subject: [PATCH] Swift tests and api update --- Objective-C/Internal/CBLCollection+Swift.h | 2 + Swift/Collection.swift | 4 ++ Swift/IndexConfiguration.swift | 7 +- Swift/Tests/UnnestArrayTest.swift | 81 ++++++++++++++++++++++ 4 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 Swift/Tests/UnnestArrayTest.swift diff --git a/Objective-C/Internal/CBLCollection+Swift.h b/Objective-C/Internal/CBLCollection+Swift.h index a92e4c1a4..4e9edc917 100644 --- a/Objective-C/Internal/CBLCollection+Swift.h +++ b/Objective-C/Internal/CBLCollection+Swift.h @@ -28,6 +28,8 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, readonly) BOOL isValid; +- (nullable NSArray*) indexesInfo: (NSError**)error; + @end NS_ASSUME_NONNULL_END diff --git a/Swift/Collection.swift b/Swift/Collection.swift index 18791674c..50d61b2f0 100644 --- a/Swift/Collection.swift +++ b/Swift/Collection.swift @@ -352,6 +352,10 @@ public final class Collection : CollectionChangeObservable, Indexable, Equatable // MARK: Internal + func indexesInfo() throws -> [[String: Any]]? { + return try impl.indexesInfo() as? [[String: Any]] + } + init(_ impl: CBLCollection, db: Database) { self.impl = impl self.database = db diff --git a/Swift/IndexConfiguration.swift b/Swift/IndexConfiguration.swift index d77f5b847..4577b6b44 100644 --- a/Swift/IndexConfiguration.swift +++ b/Swift/IndexConfiguration.swift @@ -88,7 +88,12 @@ public struct ArrayIndexConfiguration: IndexConfiguration, IndexConfigConvertabl /// represents an expression defining the values within the array to be indexed. /// If the array specified by the path contains scalar values, this parameter can be null. /// - Returns The ArrayIndexConfiguration object. - public init(path: String, _ expressions: [String]?) { + public init(path: String, _ expressions: [String]? = nil) { + if let expressions = expressions, expressions.isEmpty { + NSException(name: .invalidArgumentException, + reason: "Empty expressions is not allowed, use nil instead", + userInfo: nil).raise() + } self.path = path self.expressions = expressions } diff --git a/Swift/Tests/UnnestArrayTest.swift b/Swift/Tests/UnnestArrayTest.swift new file mode 100644 index 000000000..fb39d6499 --- /dev/null +++ b/Swift/Tests/UnnestArrayTest.swift @@ -0,0 +1,81 @@ +// +// UnnestArrayTest.swift +// CouchbaseLite +// +// Copyright (c) 2024 Couchbase, Inc. All rights reserved. +// +// Licensed under the Couchbase License Agreement (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// https://info.couchbase.com/rs/302-GJY-034/images/2017-10-30_License_Agreement.pdf +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import XCTest +@testable import CouchbaseLiteSwift + +/// Test Spec v1.0.1: +/// https://github.com/couchbaselabs/couchbase-lite-api/blob/master/spec/tests/T0004-Unnest-Array-Index.md + +class UnnestArrayTest: CBLTestCase { + /// 1. TestArrayIndexConfigInvalidExpressions + /// Description + /// Test that creating an ArrayIndexConfiguration with invalid expressions which are an empty expressions or contain null. + /// Steps + /// 1. Create a ArrayIndexConfiguration object. + /// - path: "contacts" + /// - expressions: [] + /// 2. Check that an invalid arument exception is thrown. + func testArrayIndexConfigInvalidExpressions() throws { + expectException(exception: .invalidArgumentException) { + _ = ArrayIndexConfiguration(path: "contacts", []) + } + } + + /// 2. TestCreateArrayIndexWithPath + /// Description + /// Test that creating an ArrayIndexConfiguration with invalid expressions which are an empty expressions or contain null. + /// Steps + /// 1. Load profiles.json into the collection named "_default.profiles". + /// 2. Create a ArrayIndexConfiguration object. + /// - path: "contacts" + /// - expressions: null + /// 3. Create an array index named "contacts" in the profiles collection. + /// 4. Get index names from the profiles collection and check that the index named "contacts" exists. + /// 5. Get info of the index named "contacts" using an internal API and check that the index has path and expressions as configured. + func testCreateArrayIndexWithPath() throws { + let profiles = try db.createCollection(name: "profiles") + try loadJSONResource("profiles_100", collection: profiles) + let config = ArrayIndexConfiguration(path: "contacts") + try profiles.createIndex(withName: "contacts", config: config) + let indexes = try profiles.indexesInfo() + XCTAssertEqual(indexes!.count, 1) + XCTAssertEqual(indexes![0]["expr"] as! String, "") + } + + /// 3. TestCreateArrayIndexWithPathAndExpressions + /// Description + /// Test that creating an array index with path and expressions works as expected. + /// Steps + /// 1. Load profiles.json into the collection named "_default.profiles". + /// 2. Create a ArrayIndexConfiguration object. + /// - path: "contacts" + /// - expressions: ["address.city", "address.state"] + /// 3. Create an array index named "contacts" in the profiles collection. + /// 4. Get index names from the profiles collection and check that the index named "contacts" exists. + /// 5. Get info of the index named "contacts" using an internal API and check that the index has path and expressions as configured. + func testCreateArrayIndexWithPathAndExpressions() throws { + let profiles = try db.createCollection(name: "profiles") + try loadJSONResource("profiles_100", collection: profiles) + let config = ArrayIndexConfiguration(path: "contacts", ["address.city", "address.state"]) + try profiles.createIndex(withName: "contacts", config: config) + let indexes = try profiles.indexesInfo() + XCTAssertEqual(indexes!.count, 1) + XCTAssertEqual(indexes![0]["expr"] as! String, "address.city,address.state") + } +}