Skip to content

Commit

Permalink
Version 6.1.5 (#3179)
Browse files Browse the repository at this point in the history
  • Loading branch information
marinofaggiana authored Nov 11, 2024
1 parent c38d042 commit 6656230
Show file tree
Hide file tree
Showing 28 changed files with 120 additions and 371 deletions.
11 changes: 0 additions & 11 deletions .github/workflows/additional-targets.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,6 @@ jobs:
- name: Set env var
run: echo "DEVELOPER_DIR=$(xcode-select --print-path)" >> $GITHUB_ENV
- uses: actions/checkout@v4
- name: Restore Carhage Cache
uses: actions/cache@v3
id: carthage-cache
with:
path: Carthage
key: ${{ runner.os }}-carthage-${{ hashFiles('**/Cartfile.resolved') }}
restore-keys: |
${{ runner.os }}-carthage-
- name: Carthage
if: steps.carthage-cache.outputs.cache-hit != 'true'
run: carthage bootstrap --use-xcframeworks --platform iOS
- name: Download GoogleService-Info.plist
run: wget "https://raw.githubusercontent.com/firebase/quickstart-ios/master/mock-GoogleService-Info.plist" -O GoogleService-Info.plist
- name: Build iOS Share
Expand Down
19 changes: 3 additions & 16 deletions .github/workflows/xcode.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,33 +13,20 @@ on:

env:
PROJECT: Nextcloud.xcodeproj
DESTINATION: platform=iOS Simulator,name=iPhone 15,OS=17.2
DESTINATION: platform=iOS Simulator,name=iPhone 16,OS=18.1
SCHEME: Nextcloud
SERVER_BRANCH: stable28
PHP_VERSION: 8.2

jobs:
build:
name: Build
runs-on: macos-13
runs-on: macos-15
if: github.event.pull_request.draft == false

steps:
- uses: actions/checkout@v4

- name: Restore Carhage Cache
uses: actions/cache@v3
id: carthage-cache
with:
path: Carthage
key: ${{ runner.os }}-carthage-${{ hashFiles('**/Cartfile.resolved') }}
restore-keys: |
${{ runner.os }}-carthage-
- name: Carthage
if: steps.carthage-cache.outputs.cache-hit != 'true'
run: carthage bootstrap --use-xcframeworks --platform iOS

- name: Download GoogleService-Info.plist
run: wget "https://raw.githubusercontent.com/firebase/quickstart-ios/master/mock-GoogleService-Info.plist" -O GoogleService-Info.plist

Expand All @@ -61,7 +48,7 @@ jobs:

test:
name: Test
runs-on: macos-13
runs-on: macos-15
needs: [build]

if: github.event.pull_request.draft == false
Expand Down
2 changes: 0 additions & 2 deletions AUTHORS

This file was deleted.

10 changes: 10 additions & 0 deletions AUTHORS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<!--
- SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
- SPDX-License-Identifier: GPL-3.0-or-later
-->
# Authors

- Marino Faggiana <[email protected]>
- Henrik Storch <[email protected]>
- Milen Pivchev <[email protected]>
- Philippe Weidmann <[email protected]>
234 changes: 5 additions & 229 deletions Nextcloud.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
allowLocationSimulation = "NO">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
Expand Down
43 changes: 11 additions & 32 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,43 +81,22 @@ Do you want to try the latest version in development of Nextcloud iOS ? Simple,
There are currently no preresquites for unit testing that need to be done. Mock everything that's not needed.

### Integration tests:
To run integration tests, we need a docker instance of a Nextcloud test server.
The CI does all this automatically, but to do it manually:
1. Run `docker run --rm -d -p 8080:80 ghcr.io/juliushaertl/nextcloud-dev-php80:latest` to spin up a docker container of the Nextcloud test server.
2. Log in on the test server and generate an app password for device. There are a couple test accounts, but `admin` as username and password works best.
3. Build the iOS project once. This will generate an `.env-vars` file in the root directory. It contains env vars that the project will use for testing.
4. Provide proper values for the env vars inside the file. Here is an example:
```
export TEST_SERVER_URL=http://localhost:8080
export TEST_USER=nextcloud
export TEST_PASSWORD=FAeSR-6Jk7s-DzLny-CCQHL-f49BP
```
5. Build the iOS project again. If all the values are set correctly you will see a generated file called `EnvVars.generated.swift`. It contains the env vars as Swift fields that can be easily used in code:
To run integration tests, you need a docker instance of a Nextcloud test server. [This](https://github.com/szaimen/nextcloud-easy-test) is a good start.

1. In `TestConstants.swift` you must specify your instance credentials. App Token is automatically generated.

```
/**
This is generated from the .env-vars file in the root directory. If there is an environment variable here that is needed and not filled, please look into this file.
*/
public struct EnvVars {
static let testUser = "nextcloud"
static let testPassword = "FAeSR-6Jk7s-DzLny-CCQHL-f49BP"
static let testServerUrl = "http://localhost:8080"
public class TestConstants {
static let timeoutLong: Double = 400
static let server = "http://localhost:8080"
static let username = "admin"
static let password = "admin"
static let account = "\(username) \(server)"
}
```
6. You can now run the integration tests. They will use the env vars to connect to the test server to do the testing.

2. Run the integration tests.

### UI tests

UI tests also use the docker server, but besides that there is nothing else you need to do.

### Snapshot tests

Snapshot tests are made via this library: https://github.com/pointfreeco/swift-snapshot-testing and these 2 extensions:
1. https://github.com/doordash-oss/swiftui-preview-snapshots - for creating SwiftUI snapshot tests via previews.
2. https://github.com/alexey1312/SnapshotTestingHEIC - makes snapshot images HEIC instead of PNGs for much reduced size.

Snapshot tests are a great way to test if UI elements are consistent with designs and don't break with new commits, but they can be very finicky and the smallest change can cause them to fail. Keep in mind:

- For SwiftUI snapshot tests, It's always a good idea to utilize previews, as they do not depend on device/app state and it has less chances to fail due to wrong state.

- For UIKit snapshot tests, try to include mock dependencies to always make sure the UI is rendered the same way. Even a text change can cause the tests to fail.
1 change: 1 addition & 0 deletions Share/NCShareExtension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ class NCShareExtension: UIViewController {
}

func showAlert(title: String = "_error_", description: String, onDismiss: (() -> Void)? = nil) {
let description = description.replacingOccurrences(of: "\t", with: "\n")
let alertController = UIAlertController(title: NSLocalizedString(title, comment: ""), message: NSLocalizedString(description, comment: ""), preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: NSLocalizedString("_ok_", comment: ""), style: .default, handler: { _ in
onDismiss?()
Expand Down
2 changes: 1 addition & 1 deletion Tests/Common/TestConstants.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import Foundation
import UIKit

public class TestConstants {
static let timeoutLong: Double = 600
static let timeoutLong: Double = 400
static let server = "http://localhost:8080"
static let username = "admin"
static let password = "admin"
Expand Down
121 changes: 62 additions & 59 deletions Tests/NextcloudIntegrationTests/FilesIntegrationTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,63 +29,66 @@ final class FilesIntegrationTests: BaseIntegrationXCTestCase {
NCAccount().deleteAllAccounts()
}

func test_createReadDeleteFolder_withProperParams_shouldCreateReadDeleteFolder() throws {
let expectation = expectation(description: "Should finish last callback")

let folderName = "TestFolder\(randomInt)"
let serverUrl = "\(TestConstants.server)/remote.php/dav/files/\(TestConstants.username)"
let serverUrlFileName = "\(serverUrl)/\(folderName)"
let domain = NCDomain.Domain(account: TestConstants.account, urlBase: TestConstants.server, user: TestConstants.username, userId: TestConstants.username, sceneIdentifier: "")

NextcloudKit.shared.setup(delegate: NCNetworking.shared)
NextcloudKit.shared.appendAccount(TestConstants.account, urlBase: TestConstants.server, user: TestConstants.username, userId: TestConstants.username, password: appToken, userAgent: userAgent, nextcloudVersion: 0, groupIdentifier: NCBrandOptions.shared.capabilitiesGroup)

// Test creating folder
NCNetworking.shared.createFolder(fileName: folderName, serverUrl: serverUrl, overwrite: true, withPush: true, sceneIdentifier: nil, domain: domain) { error in

XCTAssertEqual(NKError.success.errorCode, error.errorCode)
XCTAssertEqual(NKError.success.errorDescription, error.errorDescription)

Thread.sleep(forTimeInterval: 1)

// Test reading folder, should exist
NCNetworking.shared.readFolder(serverUrl: serverUrlFileName, account: TestConstants.username) { account, metadataFolder, _, _, _, _ in
XCTAssertEqual(TestConstants.account, account)
XCTAssertEqual(NKError.success.errorCode, error.errorCode)
XCTAssertEqual(NKError.success.errorDescription, error.errorDescription)
XCTAssertEqual(metadataFolder?.fileName, folderName)

// Check Realm directory, should exist
let directory = NCManageDatabase.shared.getTableDirectory(predicate: NSPredicate(format: "serverUrl == %@", serverUrlFileName))
XCTAssertNotNil(directory)

Thread.sleep(forTimeInterval: 1)

Task {
// Test deleting folder
await _ = NCNetworking.shared.deleteMetadata(metadataFolder!)

XCTAssertEqual(NKError.success.errorCode, error.errorCode)
XCTAssertEqual(NKError.success.errorDescription, error.errorDescription)

try await Task.sleep(for: .seconds(1))

// Test reading folder, should NOT exist
NCNetworking.shared.readFolder(serverUrl: serverUrlFileName, account: TestConstants.username) { account, metadataFolder, _, _, _, _ in

defer { expectation.fulfill() }

XCTAssertEqual(0, error.errorCode)
XCTAssertNil(metadataFolder?.fileName)

// Check Realm directory, should NOT exist
let directory = NCManageDatabase.shared.getTableDirectory(predicate: NSPredicate(format: "serverUrl == %@", serverUrlFileName))
XCTAssertNil(directory)
}
}
}
}

waitForExpectations(timeout: TestConstants.timeoutLong)
}
// func test_createReadDeleteFolder_withProperParams_shouldCreateReadDeleteFolder() throws {
// let expectation = expectation(description: "Should finish last callback")
//
// let folderName = "TestFolder\(randomInt)"
// let serverUrl = "\(TestConstants.server)/remote.php/dav/files/\(TestConstants.username)"
// let serverUrlFileName = "\(serverUrl)/\(folderName)"
//
// NCSession.shared.appendSession(account: TestConstants.account, urlBase: TestConstants.server, user: TestConstants.username, userId: TestConstants.username)
// let session = NCSession.shared.getSession(account: TestConstants.account)
//
// NextcloudKit.shared.setup(delegate: NCNetworking.shared)
// NextcloudKit.shared.appendSession(account: TestConstants.account, urlBase: TestConstants.server, user: TestConstants.username, userId: TestConstants.username, password: appToken, userAgent: userAgent, nextcloudVersion: 0, groupIdentifier: NCBrandOptions.shared.capabilitiesGroup)
//
// // Test creating folder
// NCNetworking.shared.createFolder(fileName: folderName, serverUrl: serverUrl, overwrite: true, withPush: true, metadata: nil, sceneIdentifier: nil, session: session ) { error in
//
// XCTAssertEqual(NKError.success.errorCode, error.errorCode)
// XCTAssertEqual(NKError.success.errorDescription, error.errorDescription)
//
// Thread.sleep(forTimeInterval: 1)
//
// // Test reading folder, should exist
// NCNetworking.shared.readFolder(serverUrl: serverUrlFileName, account: TestConstants.username, checkResponseDataChanged: false, queue: .main) { account, metadataFolder, _, _, _ in
//
// XCTAssertEqual(TestConstants.account, account)
// XCTAssertEqual(NKError.success.errorCode, error.errorCode)
// XCTAssertEqual(NKError.success.errorDescription, error.errorDescription)
// XCTAssertEqual(metadataFolder?.fileName, folderName)
//
// // Check Realm directory, should exist
// let directory = NCManageDatabase.shared.getTableDirectory(predicate: NSPredicate(format: "serverUrl == %@", serverUrlFileName))
// XCTAssertNotNil(directory)
//
// Thread.sleep(forTimeInterval: 1)
//
// Task {
// // Test deleting folder
// await _ = NCNetworking.shared.deleteFileOrFolder(serverUrlFileName: serverUrlFileName, account: TestConstants.account)
//
// XCTAssertEqual(NKError.success.errorCode, error.errorCode)
// XCTAssertEqual(NKError.success.errorDescription, error.errorDescription)
//
// try await Task.sleep(for: .seconds(1))
//
// // Test reading folder, should NOT exist
// NCNetworking.shared.readFolder(serverUrl: serverUrlFileName, account: TestConstants.username, checkResponseDataChanged: false, queue: .main) { account, metadataFolder, _, _, _ in
//
// defer { expectation.fulfill() }
//
// XCTAssertEqual(0, error.errorCode)
// XCTAssertNil(metadataFolder?.fileName)
//
// // Check Realm directory, should NOT exist
// let directory = NCManageDatabase.shared.getTableDirectory(predicate: NSPredicate(format: "serverUrl == %@", serverUrlFileName))
// XCTAssertNil(directory)
// }
// }
// }
// }
//
// waitForExpectations(timeout: TestConstants.timeoutLong)
// }
}
5 changes: 3 additions & 2 deletions iOSClient/Data/NCManageDatabase+Metadata.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1073,18 +1073,19 @@ extension NCManageDatabase {

if layout.sort == "fileName" {
let sortedResults = results.sorted {
let ordered = layout.ascending ? ComparisonResult.orderedAscending : ComparisonResult.orderedDescending
// 1. favorite order
if $0.favorite == $1.favorite {
// 2. directory order TOP
if layout.directoryOnTop {
if $0.directory == $1.directory {
// 3. natural fileName
return $0.fileNameView.localizedStandardCompare($1.fileNameView) == .orderedAscending
return $0.fileNameView.localizedStandardCompare($1.fileNameView) == ordered
} else {
return $0.directory && !$1.directory
}
} else {
return $0.fileNameView.localizedStandardCompare($1.fileNameView) == .orderedAscending
return $0.fileNameView.localizedStandardCompare($1.fileNameView) == ordered
}
} else {
return $0.favorite && !$1.favorite
Expand Down
10 changes: 8 additions & 2 deletions iOSClient/Extensions/UIAlertController+Extension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,13 @@ extension UIAlertController {
}
#endif
} else {
#if EXTENSION
NCNetworking.shared.createFolder(fileName: fileNameFolder, serverUrl: serverUrl, overwrite: false, withPush: true, sceneIdentifier: sceneIdentifier, session: session) { error in
if let completion {
DispatchQueue.main.async { completion(error) }
}
}
#else
let metadataForCreateFolder = NCManageDatabase.shared.createMetadata(fileName: fileNameFolder,
fileNameView: fileNameFolder,
ocId: NSUUID().uuidString,
Expand All @@ -76,6 +83,7 @@ extension UIAlertController {
metadataForCreateFolder.sessionDate = Date()
NCManageDatabase.shared.addMetadata(metadataForCreateFolder)
NotificationCenter.default.postOnMainThread(name: NCGlobal.shared.notificationCenterCreateFolder, userInfo: ["ocId": metadataForCreateFolder.ocId, "serverUrl": metadataForCreateFolder.serverUrl, "account": metadataForCreateFolder.account, "withPush": true, "sceneIdentifier": sceneIdentifier as Any])
#endif
}
})

Expand All @@ -94,8 +102,6 @@ extension UIAlertController {
queue: .main) { _ in
guard let text = alertController.textFields?.first?.text else { return }
let folderName = text.trimmingCharacters(in: .whitespaces)

let newExtension = text.fileExtension
let isFileHidden = FileNameValidator.shared.isFileHidden(text)
let textCheck = FileNameValidator.shared.checkFileName(folderName, account: session.account)

Expand Down
1 change: 0 additions & 1 deletion iOSClient/Media/NCMedia+Command.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ extension NCMedia {

func setSelectcancelButton() {
fileSelect.removeAll()
fileDeleted.removeAll()
tabBarSelect.selectCount = fileSelect.count

if let visibleCells = self.collectionView?.indexPathsForVisibleItems.compactMap({ self.collectionView?.cellForItem(at: $0) }) {
Expand Down
7 changes: 4 additions & 3 deletions iOSClient/Media/NCMedia.swift
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ class NCMedia: UIViewController {
var isEditMode = false
var fileSelect: [String] = []
var filesExists: [String] = []
var fileDeleted: [String] = []
var attributesZoomIn: UIMenuElement.Attributes = []
var attributesZoomOut: UIMenuElement.Attributes = []
let gradient: CAGradientLayer = CAGradientLayer()
Expand Down Expand Up @@ -236,7 +235,6 @@ class NCMedia: UIViewController {
timerSearchNewMedia?.invalidate()
timerSearchNewMedia = nil
filesExists.removeAll()
fileDeleted.removeAll()

NCNetworking.shared.fileExistsQueue.cancelAll()
NCNetworking.shared.downloadThumbnailQueue.cancelAll()
Expand All @@ -257,7 +255,10 @@ class NCMedia: UIViewController {
guard let userInfo = notification.userInfo as NSDictionary?,
let error = userInfo["error"] as? NKError else { return }

if error != .success {
if error.errorCode == self.global.errorResourceNotFound, let ocId = userInfo["ocId"] as? String {
self.database.deleteMetadataOcId(ocId)
self.loadDataSource()
} else if error != .success {
NCContentPresenter().showError(error: error)
self.loadDataSource()
}
Expand Down
8 changes: 0 additions & 8 deletions iOSClient/Media/NCMediaDataSource.swift
Original file line number Diff line number Diff line change
Expand Up @@ -112,14 +112,6 @@ extension NCMedia {
options: options) { account, files, _, error in

if error == .success, let files, session.account == account, !self.showOnlyImages, !self.showOnlyVideos {

/// Removes all files in `files` that have an `ocId` present in `fileDeleted`
var files = files
files.removeAll { file in
self.fileDeleted.contains(file.ocId)
}
self.fileDeleted.removeAll()

/// No files, remove all
if lessDate == Date.distantFuture, greaterDate == Date.distantPast, files.isEmpty {
self.dataSource.metadatas.removeAll()
Expand Down
Loading

0 comments on commit 6656230

Please sign in to comment.