Skip to content

Commit

Permalink
Add Integration tests
Browse files Browse the repository at this point in the history
  • Loading branch information
DominikBucher12 committed Jan 19, 2024
1 parent 81ddf87 commit a32fb8e
Show file tree
Hide file tree
Showing 4 changed files with 245 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -78,40 +78,40 @@ private extension RichTextCoordinator {
func subscribeToAlignment() {
richTextContext.$textAlignment
.sink(
receiveCompletion: { _ in },
receiveValue: { [weak self] in
self?.textView.setRichTextAlignment($0)
})
}
)
.store(in: &cancellables)
}

func subscribeToFontName() {
richTextContext.$fontName
.sink(
receiveCompletion: { _ in },
receiveValue: { [weak self] in
self?.textView.setRichTextFontName($0)
})
}
)
.store(in: &cancellables)
}

func subscribeToFontSize() {
richTextContext.$fontSize
.sink(
receiveCompletion: { _ in },
receiveValue: { [weak self] in
self?.textView.setRichTextFontSize($0)
})
}
)
.store(in: &cancellables)
}

func subscribeToIsEditingText() {
richTextContext.$isEditingText
.sink(
receiveCompletion: { _ in },
receiveValue: { [weak self] in
self?.setIsEditing(to: $0)
})
}
)
.store(in: &cancellables)
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
//
// RichTextCoordinatorIntegrationTests+UIKit.swift
//
//
// Created by Dominik Bucher on 19.1.2024.
//
#if os(iOS)
import UIKit

import CoreGraphics
import SwiftUI
@testable import RichTextKit
import XCTest

final class RichTextCoordinatorIntegrationTests: XCTestCase {
private var text: NSAttributedString!
private var textBinding: Binding<NSAttributedString>!
private var textView: RichTextView!
private var textContext: RichTextContext!
private var coordinator: RichTextCoordinator!

static let initialAttributedString: NSAttributedString = {
let text = NSMutableAttributedString(string: "This is red text")
text.addAttributes([.foregroundColor: ColorRepresentable.red], range: text.richTextRange)
text.addAttributes([.font: FontRepresentable.systemFont(ofSize: 16)], range: text.richTextRange)
return text
}()


override func setUp() {
super.setUp()

text = Self.initialAttributedString
textBinding = Binding(get: { self.text }, set: { self.text = $0 })
textView = RichTextView(string: text)
textContext = RichTextContext()
coordinator = RichTextCoordinator(
text: textBinding,
textView: textView,
richTextContext: textContext)
textView.selectedRange = NSRange(location: 0, length: 0)
textView.setup(with: text, format: .archivedData)
}

override func tearDown() {
text = nil
textBinding = nil
textView = nil
textContext = nil
coordinator = nil

super.tearDown()
}

private let firstTypingPart = "String without any attributes"
private let imageToPaste = UIGraphicsImageRenderer(size: .init(width: 20, height: 20)).image { rendererContext in
UIColor.gray.setFill()
rendererContext.fill(CGRect(origin: .zero, size: .init(width: 20, height: 20)))
}

func test_behavior_whenInitialState_keepsConfiguration() {
// When starting RichTextEditor we want to check if the font and color is set correctly.
textContext.selectRange(.init(location: 0, length: Self.initialAttributedString.length))

// Only ArchivedData textView format support images...
coordinator.pasteImage(.init(content: imageToPaste, at: textView.richText.length, moveCursor: true))

XCTAssertTrue(textView.richText.containsAttachments(in: textView.richTextRange))

textView.simulateTyping(of: firstTypingPart)

textContext.selectRange(NSRange(location: Self.initialAttributedString.length, length: firstTypingPart.count))
XCTAssertEqual(textView.richTextAttributes[.font] as? FontRepresentable, FontRepresentable.systemFont(ofSize: 16))
XCTAssertEqual(textView.richTextAttributes[.foregroundColor] as? ColorRepresentable, ColorRepresentable.red)

textView.setRichTextStyle(.strikethrough, to: true, at: textView.selectedRange)
XCTAssertEqual(textView.richTextAttributes[.strikethroughStyle] as? Int, 1)
}
}
#endif
125 changes: 125 additions & 0 deletions Tests/RichTextKitTests/RichTextViewIntegrationTests+UIKit.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
//
// RichTextViewIntegrationTests+UIKit.swift
//
//
// Created by Dominik Bucher on 19.1.2024.
//

#if os(iOS)
import UIKit

import CoreGraphics
import SwiftUI
@testable import RichTextKit
import XCTest

final class RichTextViewIntegrationTests: XCTestCase {
private var text: NSAttributedString!
private var textBinding: Binding<NSAttributedString>!
private var textView: RichTextView!
private var textContext: RichTextContext!
private var coordinator: RichTextCoordinator!

override func setUp() {
super.setUp()

text = NSAttributedString.empty
textBinding = Binding(get: { self.text }, set: { self.text = $0 })
textView = RichTextView(string: text)
textContext = RichTextContext()
coordinator = RichTextCoordinator(
text: textBinding,
textView: textView,
richTextContext: textContext)
textView.selectedRange = NSRange(location: 0, length: 1)
textView.setRichTextAlignment(.justified)
}

override func tearDown() {
text = nil
textBinding = nil
textView = nil
textContext = nil
coordinator = nil

super.tearDown()
}

private let stringWithoutAttributes = "String without any attributes"
private let lastStringToAppend = " Last addition..."
private let otherStringToAppend = ". And This is some text with other attributes!"

func test_behavior_forFontStyle() throws {
// When starting RichTextEditor we want to check if the font and color is set correctly.
textContext.selectRange(.init(location: 0, length: 0))

XCTAssertEqual(textView.richTextAttributes[.font] as? FontRepresentable, FontRepresentable.systemFont(ofSize: 16))
XCTAssertEqual(textView.richTextAttributes[.foregroundColor] as? ColorRepresentable, ColorRepresentable.label)

// First we fill in the empty textView with some text, select it and set bold and italic to it.
assertFirstTextPart()
// After that we append more text, asserting that this text carries same attributes as the one before
// and we change it.
assertSecondTextPart()
// Finally, we set typingAttributes before we append last text and check if those typingAttributes are set to our
// new text.
assertFinalTextPart()
}

private func assertFirstTextPart() {
textView.simulateTyping(of: stringWithoutAttributes)

textContext.selectRange(.init(location: 0, length: stringWithoutAttributes.count))

XCTAssertEqual(textView.richTextAttributes[.font] as? FontRepresentable, FontRepresentable.systemFont(ofSize: 16))
XCTAssertEqual(textView.richTextAttributes[.foregroundColor] as? ColorRepresentable, ColorRepresentable.label)

textView.setRichTextStyle(.bold, to: true, at: textView.richTextRange)
textView.setRichTextStyle(.italic, to: true, at: textView.richTextRange)

XCTAssertTrue(try XCTUnwrap(textView.richTextFont?.fontDescriptor.symbolicTraits.contains(.traitBold)))
XCTAssertTrue(try XCTUnwrap(textView.richTextFont?.fontDescriptor.symbolicTraits.contains(.traitItalic)))

textView.setRichTextStyle(.bold, to: false, at: textView.richTextRange)
textView.setRichTextStyle(.italic, to: false, at: textView.richTextRange)
XCTAssertFalse(try XCTUnwrap(textView.richTextFont?.fontDescriptor.symbolicTraits.contains(.traitBold)))
XCTAssertFalse(try XCTUnwrap(textView.richTextFont?.fontDescriptor.symbolicTraits.contains(.traitItalic)))
}

private func assertSecondTextPart() {
textView.simulateTyping(of: otherStringToAppend)

textContext.selectRange(NSRange(location: stringWithoutAttributes.count , length: otherStringToAppend.count))
let selectedRange = textView.selectedRange
XCTAssertFalse(try XCTUnwrap(textView.richTextFont?.fontDescriptor.symbolicTraits.contains(.traitBold)))
textView.setRichTextStyle(.strikethrough, to: true, at: selectedRange)

XCTAssertEqual(textView.richTextAttributes[.strikethroughStyle] as? Int, 1)
XCTAssertEqual(textView.richTextAttributes(at: selectedRange)[.strikethroughStyle] as? Int, 1)
XCTAssertNil(
textView.richTextAttributes(at: NSRange(location: .zero, length: stringWithoutAttributes.count))[.strikethroughStyle]
)

textContext.selectRange(NSRange(location: 2 , length: .zero))
XCTAssertNil(textView.richTextAttributes[.strikethroughStyle])
}

private func assertFinalTextPart() {

textView.setRichTextStyle(.bold, to: true)
// Refactor replace into type in tests.
// document this...
textView.simulateTyping(of: lastStringToAppend)

XCTAssertTrue(try XCTUnwrap(textView.richTextFont?.fontDescriptor.symbolicTraits.contains(.traitBold)))

let lastPartLocation = NSRange(
location: stringWithoutAttributes.count + otherStringToAppend.count,
length: lastStringToAppend.count
)

let fontForLastString = textView.richTextAttributes(at: lastPartLocation)[.font] as? FontRepresentable
XCTAssertTrue(try XCTUnwrap(fontForLastString?.fontDescriptor.symbolicTraits.contains(.traitBold)))
}
}
#endif
32 changes: 32 additions & 0 deletions Tests/RichTextKitTests/Utils/RichTextView+Helpers.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//
// RichTextView+Helpers.swift
//
//
// Created by Dominik Bucher on 19.01.2024.
//

import Foundation
import RichTextKit

#if os(iOS) || os(tvOS)
import UIKit

extension UITextView {
func simulateTyping(of text: String) {
replace(
textRange(
from: endOfDocument,
to: endOfDocument
)!,
withText: text
)
}
}
#elseif os(macOS)
import AppKit
extension NSTextView {
func simulateTyping(of text: String) {
// TODO: Implement
}
}
#endif

0 comments on commit a32fb8e

Please sign in to comment.