diff --git a/interject/Interject!.xcodeproj/project.xcworkspace/xcuserdata/roryhinnen.xcuserdatad/UserInterfaceState.xcuserstate b/interject/Interject!.xcodeproj/project.xcworkspace/xcuserdata/roryhinnen.xcuserdatad/UserInterfaceState.xcuserstate index dcaf34d..c51babb 100644 Binary files a/interject/Interject!.xcodeproj/project.xcworkspace/xcuserdata/roryhinnen.xcuserdatad/UserInterfaceState.xcuserstate and b/interject/Interject!.xcodeproj/project.xcworkspace/xcuserdata/roryhinnen.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/interject/Interject!Tests/Interject_Tests.swift b/interject/Interject!Tests/Interject_Tests.swift index a0d4579..61a5aac 100644 --- a/interject/Interject!Tests/Interject_Tests.swift +++ b/interject/Interject!Tests/Interject_Tests.swift @@ -5,29 +5,199 @@ // Created by Rory Hinnen on 21/11/18. // -import XCTest +import Testing @testable import Interject_ -class Interject_Tests: XCTestCase { - - override func setUpWithError() throws { - // Put setup code here. This method is called before the invocation of each test method in the class. - } - - override func tearDownWithError() throws { - // Put teardown code here. This method is called after the invocation of each test method in the class. - } - - func testExample() throws { - // This is an example of a functional test case. - // Use XCTAssert and related functions to verify your tests produce the correct results. - } - - func testPerformanceExample() throws { - // This is an example of a performance test case. - self.measure { - // Put the code you want to measure the time of here. - } - } - +@Suite("Place") struct PlaceTests { + @Test func firstSize() { #expect(Place.first.size() == 35.0) } + @Test func secondSize() { #expect(Place.second.size() == 55.0) } + @Test func nounSize() { #expect(Place.noun.size() == 75.0) } +} + +@Suite("Locked") struct LockedTests { + @Test func defaultsUnlocked() { + let locked = Locked() + #expect(!locked.isLocked(.first)) + #expect(!locked.isLocked(.second)) + #expect(!locked.isLocked(.noun)) + } + + @Test func toggleFirstLocks() { + var locked = Locked() + locked.toggle(.first) + #expect(locked.isLocked(.first)) + #expect(!locked.isLocked(.second)) + #expect(!locked.isLocked(.noun)) + } + + @Test func toggleSecondLocks() { + var locked = Locked() + locked.toggle(.second) + #expect(!locked.isLocked(.first)) + #expect(locked.isLocked(.second)) + #expect(!locked.isLocked(.noun)) + } + + @Test func toggleNounLocks() { + var locked = Locked() + locked.toggle(.noun) + #expect(!locked.isLocked(.first)) + #expect(!locked.isLocked(.second)) + #expect(locked.isLocked(.noun)) + } + + @Test func toggleTwiceUnlocks() { + var locked = Locked() + locked.toggle(.first) + locked.toggle(.first) + #expect(!locked.isLocked(.first)) + } +} + +@Suite("Entry") struct EntryTests { + @Test func sfwWordReturnedWhenSfw() { + let entry = Entry(nsfw: "badword", nsfwMeaning: nil, word: "goodword", meaning: "a meaning") + #expect(entry.word(true) == "goodword") + } + + @Test func nsfwWordReturnedWhenNsfw() { + let entry = Entry(nsfw: "badword", nsfwMeaning: nil, word: "goodword", meaning: "a meaning") + #expect(entry.word(false) == "badword") + } + + @Test func sfwWordFallbackWhenNoNsfw() { + let entry = Entry(nsfw: nil, nsfwMeaning: nil, word: "goodword", meaning: "a meaning") + #expect(entry.word(false) == "goodword") + } + + @Test func sfwDefinitionReturnedWhenSfw() { + let entry = Entry(nsfw: nil, nsfwMeaning: "bad meaning", word: "word", meaning: "good meaning") + #expect(entry.definition(true) == "good meaning") + } + + @Test func nsfwDefinitionReturnedWhenNsfw() { + let entry = Entry(nsfw: nil, nsfwMeaning: "bad meaning", word: "word", meaning: "good meaning") + #expect(entry.definition(false) == "bad meaning") + } + + @Test func sfwDefinitionFallbackWhenNoNsfwMeaning() { + let entry = Entry(nsfw: nil, nsfwMeaning: nil, word: "word", meaning: "good meaning") + #expect(entry.definition(false) == "good meaning") + } +} + +@Suite("Sentence") struct SentenceTests { + let sentence = Sentence( + adjective1: Entry(nsfw: "nsfw1", nsfwMeaning: "nsfw meaning 1", word: "sfw1", meaning: "sfw meaning 1"), + adjective2: Entry(nsfw: nil, nsfwMeaning: nil, word: "sfw2", meaning: "sfw meaning 2"), + noun: Entry(nsfw: "nsfwNoun", nsfwMeaning: nil, word: "sfwNoun", meaning: "noun meaning") + ) + + @Test func wordFirstSfw() { #expect(sentence.word(.first, safe: true) == "sfw1") } + @Test func wordFirstNsfw() { #expect(sentence.word(.first, safe: false) == "nsfw1") } + @Test func wordSecondSfw() { #expect(sentence.word(.second, safe: true) == "sfw2") } + @Test func wordSecondNsfwFallsBackToSfw() { #expect(sentence.word(.second, safe: false) == "sfw2") } + @Test func wordNounSfw() { #expect(sentence.word(.noun, safe: true) == "sfwNoun") } + @Test func wordNounNsfw() { #expect(sentence.word(.noun, safe: false) == "nsfwNoun") } + @Test func definitionFirstSfw() { #expect(sentence.definition(.first, safe: true) == "sfw meaning 1") } + @Test func definitionFirstNsfw() { #expect(sentence.definition(.first, safe: false) == "nsfw meaning 1") } + @Test func definitionSecondSfw() { #expect(sentence.definition(.second, safe: true) == "sfw meaning 2") } + @Test func definitionNounSfw() { #expect(sentence.definition(.noun, safe: true) == "noun meaning") } +} + +// These tests require words.json to be in Bundle.main, which is true when +// the test host is the main app target (the default Xcode setup). +@Suite("Word pool") struct WordPoolTests { + @Test func firstNotEmpty() { #expect(!Sentence.first.isEmpty) } + @Test func adjectivesNotEmpty() { #expect(!Sentence.adjectives.isEmpty) } + @Test func nounsNotEmpty() { #expect(!Sentence.nouns.isEmpty) } + @Test func firstHasThreeEntries() { #expect(Sentence.first.count == 3) } + + @Test func newSentenceHasNonEmptyWords() { + let next = Sentence().new(current: Sentence()) + #expect(!next.word(.first, safe: true).isEmpty) + #expect(!next.word(.second, safe: true).isEmpty) + #expect(!next.word(.noun, safe: true).isEmpty) + } + + @Test func newSentenceExcludesCurrentWords() { + let current = Sentence().new(current: Sentence()) + let next = current.new(current: current) + #expect(next.word(.first, safe: true) != current.word(.first, safe: true)) + #expect(next.word(.second, safe: true) != current.word(.second, safe: true)) + #expect(next.word(.noun, safe: true) != current.word(.noun, safe: true)) + } +} + +@Suite("Settings") struct SettingsTests { + func makeSettings(phrases: [Sentence] = [Sentence()]) -> Settings { + Settings(phrases: phrases, sfw: true, locked: Locked(), font: .helvetica, colorScheme: .automatic) + } + + @Test func addIncreasesCount() { + let settings = makeSettings() + let before = settings.phrases.count + settings.add() + #expect(settings.phrases.count == before + 1) + } + + @Test func removeDecreasesCount() { + let settings = makeSettings(phrases: [Sentence(), Sentence()]) + settings.remove() + #expect(settings.phrases.count == 1) + } + + @Test func removeDoesNotGoBelowOne() { + let settings = makeSettings() + settings.remove() + #expect(settings.phrases.count == 1) + } + + @Test func addRespectsMaximumOfOneHundred() { + let phrases = (0..<100).map { _ in Sentence() } + let settings = makeSettings(phrases: phrases) + settings.add() + #expect(settings.phrases.count == 100) + } + + @Test func addWithLockedFirstPreservesAdjective1() { + let initial = Sentence().new(current: Sentence()) + var locked = Locked() + locked.toggle(.first) + let settings = Settings(phrases: [initial], sfw: true, locked: locked, font: .helvetica, colorScheme: .automatic) + let originalWord = settings.phrases[0].word(.first, safe: true) + settings.add() + #expect(settings.phrases[0].word(.first, safe: true) == originalWord) + } + + @Test func addWithLockedSecondPreservesAdjective2() { + let initial = Sentence().new(current: Sentence()) + var locked = Locked() + locked.toggle(.second) + let settings = Settings(phrases: [initial], sfw: true, locked: locked, font: .helvetica, colorScheme: .automatic) + let originalWord = settings.phrases[0].word(.second, safe: true) + settings.add() + #expect(settings.phrases[0].word(.second, safe: true) == originalWord) + } + + @Test func addWithLockedNounPreservesNoun() { + let initial = Sentence().new(current: Sentence()) + var locked = Locked() + locked.toggle(.noun) + let settings = Settings(phrases: [initial], sfw: true, locked: locked, font: .helvetica, colorScheme: .automatic) + let originalNoun = settings.phrases[0].word(.noun, safe: true) + settings.add() + #expect(settings.phrases[0].word(.noun, safe: true) == originalNoun) + } + + @Test func removeWithLockedFirstCopiesAdjective1ToNext() { + let first = Sentence().new(current: Sentence()) + let second = first.new(current: first) + var locked = Locked() + locked.toggle(.first) + let settings = Settings(phrases: [first, second], sfw: true, locked: locked, font: .helvetica, colorScheme: .automatic) + let originalWord = settings.phrases[0].word(.first, safe: true) + settings.remove() + #expect(settings.phrases[0].word(.first, safe: true) == originalWord) + } }