ShareExtension target copies shared files into group.dev.ayushya.noo and leaves a manifest; the app consumes it on launch/activation through the existing share_intent channel into the destination picker. Extension is embedded before Flutter's script phases; versions follow FLUTTER_BUILD_*. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
101 lines
4.1 KiB
Swift
101 lines
4.1 KiB
Swift
import Flutter
|
|
import UIKit
|
|
import XCTest
|
|
|
|
@testable import Runner
|
|
|
|
class RunnerTests: XCTestCase {
|
|
|
|
func testFileURLEncodesEachSegment() {
|
|
let url = WebDAV.fileURL(
|
|
serverUrl: "https://cloud.example.com", username: "alice",
|
|
remotePath: "/Tax Forms/2026 #1/a&b.pdf")
|
|
XCTAssertEqual(
|
|
url?.absoluteString,
|
|
"https://cloud.example.com/remote.php/dav/files/alice/Tax%20Forms/2026%20%231/a&b.pdf")
|
|
}
|
|
|
|
func testFileURLKeepsServerSubPathAndDropsTrailingSlash() {
|
|
let url = WebDAV.fileURL(
|
|
serverUrl: "https://example.com/nextcloud/", username: "bob@home", remotePath: "docs/x.txt")
|
|
XCTAssertEqual(
|
|
url?.absoluteString,
|
|
"https://example.com/nextcloud/remote.php/dav/files/bob@home/docs/x.txt")
|
|
}
|
|
|
|
func testFileURLForRoot() {
|
|
XCTAssertEqual(
|
|
WebDAV.fileURL(serverUrl: "https://c.io", username: "u", remotePath: "/")?.absoluteString,
|
|
"https://c.io/remote.php/dav/files/u")
|
|
}
|
|
|
|
func testJoinUsesOneSlash() {
|
|
XCTAssertEqual(WebDAV.join("/", "a.txt"), "/a.txt")
|
|
XCTAssertEqual(WebDAV.join("/docs", "a.txt"), "/docs/a.txt")
|
|
XCTAssertEqual(WebDAV.join("/docs/", "a.txt"), "/docs/a.txt")
|
|
}
|
|
|
|
func testUniqueURLNumbersCollisions() throws {
|
|
let dir = FileManager.default.temporaryDirectory
|
|
.appendingPathComponent("noo-tests-\(UUID().uuidString)", isDirectory: true)
|
|
try FileManager.default.createDirectory(at: dir, withIntermediateDirectories: true)
|
|
defer { try? FileManager.default.removeItem(at: dir) }
|
|
|
|
XCTAssertEqual(LocalFiles.uniqueURL(in: dir, name: "a.txt").lastPathComponent, "a.txt")
|
|
FileManager.default.createFile(atPath: dir.appendingPathComponent("a.txt").path, contents: nil)
|
|
XCTAssertEqual(LocalFiles.uniqueURL(in: dir, name: "a.txt").lastPathComponent, "a (1).txt")
|
|
FileManager.default.createFile(atPath: dir.appendingPathComponent("a (1).txt").path, contents: nil)
|
|
XCTAssertEqual(LocalFiles.uniqueURL(in: dir, name: "a.txt").lastPathComponent, "a (2).txt")
|
|
FileManager.default.createFile(atPath: dir.appendingPathComponent("README").path, contents: nil)
|
|
XCTAssertEqual(LocalFiles.uniqueURL(in: dir, name: "README").lastPathComponent, "README (1)")
|
|
}
|
|
|
|
// MARK: - SharedInbox (Share Extension hand-off)
|
|
|
|
private func makeRoot() throws -> URL {
|
|
let root = FileManager.default.temporaryDirectory
|
|
.appendingPathComponent("noo-inbox-\(UUID().uuidString)", isDirectory: true)
|
|
try FileManager.default.createDirectory(at: root, withIntermediateDirectories: true)
|
|
addTeardownBlock { try? FileManager.default.removeItem(at: root) }
|
|
return root
|
|
}
|
|
|
|
private func makeSharedFile(in root: URL, name: String, contents: String = "hi") throws -> SharedItem {
|
|
let batch = try SharedInbox.makeBatchDirectory(in: root)
|
|
let file = batch.appendingPathComponent(name)
|
|
try contents.write(to: file, atomically: true, encoding: .utf8)
|
|
return SharedItem(path: file.path, name: name, mimeType: "text/plain", size: Int64(contents.utf8.count))
|
|
}
|
|
|
|
func testInboxConsumeReturnsAppendedItemsOnceThenNothing() throws {
|
|
let root = try makeRoot()
|
|
let a = try makeSharedFile(in: root, name: "a.txt")
|
|
let b = try makeSharedFile(in: root, name: "b.txt")
|
|
try SharedInbox.append([a], in: root)
|
|
try SharedInbox.append([b], in: root)
|
|
|
|
XCTAssertEqual(SharedInbox.consume(in: root), [a, b])
|
|
XCTAssertEqual(SharedInbox.consume(in: root), [], "each share is delivered once")
|
|
}
|
|
|
|
func testInboxConsumeDropsFilesThatNoLongerExist() throws {
|
|
let root = try makeRoot()
|
|
let kept = try makeSharedFile(in: root, name: "kept.txt")
|
|
let gone = try makeSharedFile(in: root, name: "gone.txt")
|
|
try SharedInbox.append([kept, gone], in: root)
|
|
try FileManager.default.removeItem(atPath: gone.path)
|
|
|
|
XCTAssertEqual(SharedInbox.consume(in: root), [kept])
|
|
}
|
|
|
|
func testInboxConsumeWithNothingPendingIsEmpty() throws {
|
|
XCTAssertEqual(SharedInbox.consume(in: try makeRoot()), [])
|
|
}
|
|
|
|
func testInboxAppendOfNothingCreatesNoManifest() throws {
|
|
let root = try makeRoot()
|
|
try SharedInbox.append([], in: root)
|
|
XCTAssertEqual(SharedInbox.consume(in: root), [])
|
|
}
|
|
}
|